//native
// X-Api-Key header: the resource's api_key, or one obtained from username/password
async function authHeaders(
auth: RT.IxiaIxnetwork,
base: string
): Promise<Record<string, string>> {
if (auth.api_key) return { "X-Api-Key": auth.api_key }
if (!auth.username) return {}
const response = await fetch(`${base}/api/v1/auth/session`, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify({ username: auth.username, password: auth.password }),
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const { apiKey } = (await response.json()) as { apiKey: string }
return { "X-Api-Key": apiKey }
}
type Operation = {
id?: string
state?: string
progress?: number
message?: string
result?: unknown
url?: string
}
// POST a traffic operation; with wait, poll its status url until it leaves IN_PROGRESS
async function runTrafficOperation(
base: string,
headers: Record<string, string>,
session_id: number,
operation: string,
wait: boolean,
deadline: number
): Promise<Operation> {
const traffic = `/api/v1/sessions/${session_id}/ixnetwork/traffic`
const response = await fetch(`${base}${traffic}/operations/${operation}`, {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ arg1: traffic }),
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
let status = (await response.json()) as Operation
const statusUrl = status.url
const pollUrl = statusUrl?.startsWith("http")
? statusUrl
: `${base}/${statusUrl?.replace(/^\/+/, "")}`
while (wait && status.state === "IN_PROGRESS" && statusUrl) {
if (Date.now() > deadline) {
throw new Error(
`Traffic ${operation} still in progress at timeout: ${JSON.stringify(status)}`
)
}
await new Promise((r) => setTimeout(r, 1000))
const poll = await fetch(pollUrl, {
headers: { ...headers, Accept: "application/json" },
})
if (!poll.ok) {
throw new Error(`${poll.status} ${await poll.text()}`)
}
status = (await poll.json()) as Operation
}
if (status.state === "ERROR" || status.state === "EXCEPTION") {
throw new Error(`Traffic ${operation} failed: ${JSON.stringify(status)}`)
}
return status
}
/**
* Start traffic
* 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).
*/
export async function main(
auth: RT.IxiaIxnetwork,
session_id: number,
apply_traffic: boolean = true,
wait_for_completion: boolean = true,
timeout_seconds: number = 120
) {
const base = auth.base_url.replace(/\/+$/, "")
const headers = await authHeaders(auth, base)
const deadline = Date.now() + (timeout_seconds || 120) * 1000
// apply must finish before start, so it is always awaited
const apply = apply_traffic
? await runTrafficOperation(
base,
headers,
session_id,
"apply",
true,
deadline
)
: undefined
const start = await runTrafficOperation(
base,
headers,
session_id,
"start",
wait_for_completion !== false,
deadline
)
return { apply, start }
}
Submitted by hugo989 6 hours ago