1 | |
2 |
|
3 | |
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 | |
32 | * Stop traffic |
33 | * Stop the running traffic of an IxNetwork session. |
34 | */ |
35 | export async function main( |
36 | auth: RT.IxiaIxnetwork, |
37 | session_id: number, |
38 | wait_for_completion: boolean = true, |
39 | timeout_seconds: number = 120 |
40 | ) { |
41 | const base = auth.base_url.replace(/\/+$/, "") |
42 | const headers = await authHeaders(auth, base) |
43 | const deadline = Date.now() + (timeout_seconds || 120) * 1000 |
44 |
|
45 | const traffic = `/api/v1/sessions/${session_id}/ixnetwork/traffic` |
46 | const response = await fetch(`${base}${traffic}/operations/stop`, { |
47 | method: "POST", |
48 | headers: { |
49 | ...headers, |
50 | "Content-Type": "application/json", |
51 | Accept: "application/json", |
52 | }, |
53 | body: JSON.stringify({ arg1: traffic }), |
54 | }) |
55 | if (!response.ok) { |
56 | throw new Error(`${response.status} ${await response.text()}`) |
57 | } |
58 | let status = (await response.json()) as Operation |
59 | const statusUrl = status.url |
60 | const pollUrl = statusUrl?.startsWith("http") |
61 | ? statusUrl |
62 | : `${base}/${statusUrl?.replace(/^\/+/, "")}` |
63 |
|
64 | |
65 | while ( |
66 | wait_for_completion !== false && |
67 | status.state === "IN_PROGRESS" && |
68 | statusUrl |
69 | ) { |
70 | if (Date.now() > deadline) { |
71 | throw new Error( |
72 | `Traffic stop still in progress at timeout: ${JSON.stringify(status)}` |
73 | ) |
74 | } |
75 | await new Promise((r) => setTimeout(r, 1000)) |
76 | const poll = await fetch(pollUrl, { |
77 | headers: { ...headers, Accept: "application/json" }, |
78 | }) |
79 | if (!poll.ok) { |
80 | throw new Error(`${poll.status} ${await poll.text()}`) |
81 | } |
82 | status = (await poll.json()) as Operation |
83 | } |
84 |
|
85 | if (status.state === "ERROR" || status.state === "EXCEPTION") { |
86 | throw new Error(`Traffic stop failed: ${JSON.stringify(status)}`) |
87 | } |
88 | return status |
89 | } |
90 |
|