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