matrix — guide
Class:
guide· audience: an engineer running the live multi-OS install matrix. The what is inmatrix-design.md; the why inmatrix-reasoning.md.
Build the probe binaries first
The matrix injects two static-musl binaries into each guest. Build them:
cargo build --release --target x86_64-unknown-linux-musl \
-p skidbladnir-probe --bin skidbladnir-probe --bin skidbladnir-testsvc
Run the live matrix
It is a heavy, #[ignore]d test that boots real KVM guests, so run it explicitly:
export SKID_ISOS=/path/to/cloud-images # ubuntu-24.04, debian-12, fedora-42, alpine-3.21 qcow2s
export SKID_VMS=/var/tmp/skid-vms # scratch for per-cell VM disks
export WORKSPACE_SKIDBLADNIR=/path/to/warehouse # where rows are sunk
cargo test --features matrix --test install_matrix_live -- --ignored --nocapture
Optional knobs: SKID_ONLY=alpine-3.21 (subset), SKID_BOOT_TIMEOUT=360 (seconds).
What a run does, per cell
renderer_for(backend)— if the backend has no renderer, the cell isSkipped(honest).- build the payload FAT image (
skidbladnir-probe+skidbladnir-testsvc+ the rendered units). - boot the KVM guest; cloud-init installs
skidtest, runs the renderer's enable/start verbs, runs the probe, and tees theProbeReportto theorg.skidbladnir.reportvirtio-serial port. - the host polls that serial file for a parseable
ProbeReportand classifies the cell (Passed/Unhealthy/NoReport/Skipped).
Results sink to <WORKSPACE_SKIDBLADNIR>/probe_reports.jsonl and to airgap_events (op = matrix_probe).
Drive the machine layer directly
# #[cfg(feature = "kvm")] {
use skidbladnir::machine::{MachineController, MachineSpec, NetMode, Readiness, kvm::KvmController};
let ctrl = KvmController::new();
let spec = MachineSpec::vm("probe-vm", disk).net(NetMode::Isolated).readiness(Readiness::CloudInitDone);
let h = ctrl.start(&spec)?;
ctrl.wait_ready(&h, &Readiness::CloudInitDone, std::time::Duration::from_secs(360))?;
let out = ctrl.exec(&h, &["systemctl", "is-active", "skidtest"])?; // over the guest agent
ctrl.stop(&h)?; // idempotent
# }
Gotchas
- The matrix is server-side and heavy — it needs qemu, the musl probe binaries, and the base cloud images. It is never compiled into the lean embedded client.
NetMode::Isolatedgives a guest with no NIC; the probe still reports back over virtio-serial, so the assert works with zero egress.- Base images are booted under
snapshot=on— the qcow2 you pointSKID_ISOSat is never mutated. - The matrix grows automatically: as new
renderer_forbackends land, their cells stop beingSkippedand start running — no matrix code changes.