69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
|
|
// Libvirt network management for integration tests.
|
||
|
|
|
||
|
|
import { execSync, spawnSync } from "node:child_process";
|
||
|
|
import { writeFileSync, unlinkSync } from "node:fs";
|
||
|
|
import { log } from "./libvirt.js";
|
||
|
|
|
||
|
|
export const TEST_NETWORK_NAME = "lab-test";
|
||
|
|
export const TEST_NETWORK_BRIDGE = "virbr-lab";
|
||
|
|
export const TEST_NETWORK_SUBNET = "192.168.250";
|
||
|
|
export const TEST_NETWORK_GATEWAY = `${TEST_NETWORK_SUBNET}.1`;
|
||
|
|
|
||
|
|
const IS_ROOT = process.getuid?.() === 0;
|
||
|
|
|
||
|
|
function run(cmd: string): string {
|
||
|
|
const full = IS_ROOT ? cmd : `sudo ${cmd}`;
|
||
|
|
return execSync(full, { encoding: "utf-8", stdio: "pipe" });
|
||
|
|
}
|
||
|
|
|
||
|
|
function virsh(...args: string[]): { status: number; stdout: string } {
|
||
|
|
const cmd = IS_ROOT ? "virsh" : "sudo";
|
||
|
|
const finalArgs = IS_ROOT ? args : ["virsh", ...args];
|
||
|
|
const result = spawnSync(cmd, finalArgs, { encoding: "utf-8", stdio: "pipe" });
|
||
|
|
return { status: result.status ?? 1, stdout: result.stdout ?? "" };
|
||
|
|
}
|
||
|
|
|
||
|
|
const NETWORK_XML = `<network>
|
||
|
|
<name>${TEST_NETWORK_NAME}</name>
|
||
|
|
<forward mode='nat'/>
|
||
|
|
<bridge name='${TEST_NETWORK_BRIDGE}' stp='on' delay='0'/>
|
||
|
|
<ip address='${TEST_NETWORK_GATEWAY}' netmask='255.255.255.0'>
|
||
|
|
<dhcp>
|
||
|
|
<range start='${TEST_NETWORK_SUBNET}.100' end='${TEST_NETWORK_SUBNET}.200'/>
|
||
|
|
</dhcp>
|
||
|
|
</ip>
|
||
|
|
</network>`;
|
||
|
|
|
||
|
|
/** Ensure the test libvirt network exists and is active. */
|
||
|
|
export function ensureTestNetwork(): void {
|
||
|
|
const result = virsh("net-info", TEST_NETWORK_NAME);
|
||
|
|
|
||
|
|
if (result.status === 0 && result.stdout.includes("Active: yes")) {
|
||
|
|
log(`Network ${TEST_NETWORK_NAME} already active`);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Destroy existing if present but inactive
|
||
|
|
if (result.status === 0) {
|
||
|
|
virsh("net-destroy", TEST_NETWORK_NAME);
|
||
|
|
virsh("net-undefine", TEST_NETWORK_NAME);
|
||
|
|
}
|
||
|
|
|
||
|
|
const xmlPath = `/tmp/lab-test-network.xml`;
|
||
|
|
writeFileSync(xmlPath, NETWORK_XML);
|
||
|
|
|
||
|
|
log(`Creating libvirt network: ${TEST_NETWORK_NAME} (${TEST_NETWORK_SUBNET}.0/24)`);
|
||
|
|
run(`virsh net-define "${xmlPath}"`);
|
||
|
|
run(`virsh net-start "${TEST_NETWORK_NAME}"`);
|
||
|
|
|
||
|
|
try { unlinkSync(xmlPath); } catch { /* ignore */ }
|
||
|
|
log(`Network ${TEST_NETWORK_NAME} created and active`);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Destroy the test network. */
|
||
|
|
export function destroyTestNetwork(): void {
|
||
|
|
log(`Destroying network: ${TEST_NETWORK_NAME}`);
|
||
|
|
virsh("net-destroy", TEST_NETWORK_NAME);
|
||
|
|
virsh("net-undefine", TEST_NETWORK_NAME);
|
||
|
|
}
|