Files
herolib_rust/packages/system/virt/tests/rhai/05_cloudhv_basic.rhai
2025-08-25 15:25:00 +02:00

164 lines
5.1 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Basic Cloud Hypervisor SAL smoke test (minimal)
// - Skips gracefully if dependencies or inputs are missing
// - Creates a VM spec, optionally starts/stops it if all inputs are available
print("=== Cloud Hypervisor Basic Tests ===");
// Dependency checks (static binaries only)
let chs = which("cloud-hypervisor-static");
let chrs = which("ch-remote-static");
// Normalize which() results: () or "" both mean missing (depending on SAL which variant)
let ch_missing = (chs == () || chs == "");
let chr_missing = (chrs == () || chrs == "");
if ch_missing || chr_missing {
print("⚠️ cloud-hypervisor-static and/or ch-remote-static not available - skipping CloudHV tests");
print("Install Cloud Hypervisor static binaries to run these tests.");
print("=== CloudHV Tests Skipped ===");
exit();
}
// Inputs (adjust these for your environment)
// Prefer firmware boot if firmware is available; otherwise fallback to direct kernel boot.
let firmware_path = "/tmp/virt_images/hypervisor-fw";
let kernel_path = "/path/to/vmlinux"; // optional when firmware_path is present
// We can reuse the base image from the QCOW2 test/builder if present.
let disk_path = "/tmp/virt_images/noble-server-cloudimg-amd64.img";
// Validate inputs
let missing = false;
let have_firmware = exist(firmware_path);
let have_kernel = exist(kernel_path);
if !have_firmware && !have_kernel {
print(`⚠️ neither firmware_path (${firmware_path}) nor kernel_path (${kernel_path}) found (start/stop will be skipped)`);
missing = true;
}
if !exist(disk_path) {
print(`⚠️ disk_path not found: ${disk_path} (start/stop will be skipped)`);
missing = true;
}
// Unique id
let rid = run_silent("date +%s%N");
let suffix = if rid.success && rid.stdout != "" { rid.stdout.trim() } else { "100000" };
let vm_id = `testvm_${suffix}`;
print("\n--- Test 1: Create VM definition ---");
let spec = #{
"id": vm_id,
"disk_path": disk_path,
"api_socket": "", // default under VM dir
"vcpus": 1,
"memory_mb": 1024,
// For firmware boot:
// Provide firmware_path only if it exists
// For kernel boot:
// Provide kernel_path and optionally a cmdline
};
if have_firmware {
spec.firmware_path = firmware_path;
} else if have_kernel {
spec.kernel_path = kernel_path;
spec.cmdline = "console=ttyS0 reboot=k panic=1";
}
// "extra_args": can be added if needed, e.g.:
// spec.extra_args = ["--rng", "src=/dev/urandom"];
try {
let created_id = cloudhv_vm_create(spec);
print(`✓ VM created: ${created_id}`);
} catch (err) {
print(`❌ VM create failed: ${err}`);
print("=== CloudHV Tests Aborted ===");
exit();
}
print("\n--- Test 2: VM info ---");
try {
let info = cloudhv_vm_info(vm_id);
print(`✓ VM info loaded: id=${info.spec.id}, status=${info.runtime.status}`);
} catch (err) {
print(`❌ VM info failed: ${err}`);
print("=== CloudHV Tests Aborted ===");
exit();
}
print("\n--- Test 3: VM list ---");
try {
let vms = cloudhv_vm_list();
print(`✓ VM list size: ${vms.len()}`);
} catch (err) {
print(`❌ VM list failed: ${err}`);
print("=== CloudHV Tests Aborted ===");
exit();
}
// Start/Stop only if inputs exist
if !missing {
print("\n--- Test 4: Start VM ---");
try {
cloudhv_vm_start(vm_id);
print("✓ VM start invoked");
} catch (err) {
print(`⚠️ VM start failed (this can happen if kernel/cmdline are incompatible): ${err}`);
}
print("\n waiting for VM to be ready...");
// Discover API socket and PID from SAL
let info1 = cloudhv_vm_info(vm_id);
let api_sock = info1.spec.api_socket;
let pid = info1.runtime.pid;
// 1) Wait for API socket to appear (up to ~50s)
let sock_ok = false;
for x in 0..50 {
if exist(api_sock) { sock_ok = true; break; }
sleep(1);
}
print(`api_sock_exists=${sock_ok} path=${api_sock}`);
// 2) Probe ch-remote info with retries (up to ~20s)
if sock_ok {
let info_ok = false;
for x in 0..20 {
let r = run_silent(`ch-remote-static --api-socket ${api_sock} info`);
if r.success {
info_ok = true;
break;
}
sleep(1);
}
if info_ok {
print("VM API is ready (ch-remote info OK)");
} else {
print("⚠️ VM API did not become ready in time (continuing)");
}
} else {
print("⚠️ API socket not found (continuing)");
}
// print("\n--- Test 5: Stop VM (graceful) ---");
// try {
// cloudhv_vm_stop(vm_id, false);
// print("✓ VM stop invoked (graceful)");
// } catch (err) {
// print(`⚠️ VM stop failed: ${err}`);
// }
} else {
print("\n⚠ Skipping start/stop because required inputs are missing.");
}
// print("\n--- Test 6: Delete VM definition ---");
// try {
// cloudhv_vm_delete(vm_id, false);
// print("✓ VM deleted");
// } catch (err) {
// print(`❌ VM delete failed: ${err}`);
// print("=== CloudHV Tests Aborted ===");
// exit();
// }
print("\n=== Cloud Hypervisor Basic Tests Completed ===");