// 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 ===");