0

Start traffic

by
Published today

Apply and start the traffic of an IxNetwork session.

Script ixia_ixnetwork Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 6 hours ago
1
//native
2

3
// X-Api-Key header: the resource's api_key, or one obtained from username/password
4
async function authHeaders(
5
  auth: RT.IxiaIxnetwork,
6
  base: string
7
): Promise<Record<string, string>> {
8
  if (auth.api_key) return { "X-Api-Key": auth.api_key }
9
  if (!auth.username) return {}
10
  const response = await fetch(`${base}/api/v1/auth/session`, {
11
    method: "POST",
12
    headers: { "Content-Type": "application/json", Accept: "application/json" },
13
    body: JSON.stringify({ username: auth.username, password: auth.password }),
14
  })
15
  if (!response.ok) {
16
    throw new Error(`${response.status} ${await response.text()}`)
17
  }
18
  const { apiKey } = (await response.json()) as { apiKey: string }
19
  return { "X-Api-Key": apiKey }
20
}
21

22
type Operation = {
23
  id?: string
24
  state?: string
25
  progress?: number
26
  message?: string
27
  result?: unknown
28
  url?: string
29
}
30

31
// POST a traffic operation; with wait, poll its status url until it leaves IN_PROGRESS
32
async function runTrafficOperation(
33
  base: string,
34
  headers: Record<string, string>,
35
  session_id: number,
36
  operation: string,
37
  wait: boolean,
38
  deadline: number
39
): Promise<Operation> {
40
  const traffic = `/api/v1/sessions/${session_id}/ixnetwork/traffic`
41
  const response = await fetch(`${base}${traffic}/operations/${operation}`, {
42
    method: "POST",
43
    headers: {
44
      ...headers,
45
      "Content-Type": "application/json",
46
      Accept: "application/json",
47
    },
48
    body: JSON.stringify({ arg1: traffic }),
49
  })
50
  if (!response.ok) {
51
    throw new Error(`${response.status} ${await response.text()}`)
52
  }
53
  let status = (await response.json()) as Operation
54
  const statusUrl = status.url
55
  const pollUrl = statusUrl?.startsWith("http")
56
    ? statusUrl
57
    : `${base}/${statusUrl?.replace(/^\/+/, "")}`
58

59
  while (wait && status.state === "IN_PROGRESS" && statusUrl) {
60
    if (Date.now() > deadline) {
61
      throw new Error(
62
        `Traffic ${operation} still in progress at timeout: ${JSON.stringify(status)}`
63
      )
64
    }
65
    await new Promise((r) => setTimeout(r, 1000))
66
    const poll = await fetch(pollUrl, {
67
      headers: { ...headers, Accept: "application/json" },
68
    })
69
    if (!poll.ok) {
70
      throw new Error(`${poll.status} ${await poll.text()}`)
71
    }
72
    status = (await poll.json()) as Operation
73
  }
74

75
  if (status.state === "ERROR" || status.state === "EXCEPTION") {
76
    throw new Error(`Traffic ${operation} failed: ${JSON.stringify(status)}`)
77
  }
78
  return status
79
}
80

81
/**
82
 * Start traffic
83
 * Start the traffic of an IxNetwork session, applying the traffic configuration first unless apply_traffic is off (turn it off while a packet capture is running, since applying stops the capture).
84
 */
85
export async function main(
86
  auth: RT.IxiaIxnetwork,
87
  session_id: number,
88
  apply_traffic: boolean = true,
89
  wait_for_completion: boolean = true,
90
  timeout_seconds: number = 120
91
) {
92
  const base = auth.base_url.replace(/\/+$/, "")
93
  const headers = await authHeaders(auth, base)
94
  const deadline = Date.now() + (timeout_seconds || 120) * 1000
95

96
  // apply must finish before start, so it is always awaited
97
  const apply = apply_traffic
98
    ? await runTrafficOperation(
99
        base,
100
        headers,
101
        session_id,
102
        "apply",
103
        true,
104
        deadline
105
      )
106
    : undefined
107
  const start = await runTrafficOperation(
108
    base,
109
    headers,
110
    session_id,
111
    "start",
112
    wait_for_completion !== false,
113
    deadline
114
  )
115

116
  return { apply, start }
117
}
118