Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

.nornir/matrix-design.md

matrix — design

Class: design · Function axis: f9 (machine lifecycle + the live install matrix). Server-side, behind the machine/kvm/matrix features. States only the shape we ship; the why is in matrix-reasoning.md.

Machine lifecycle (machine.rs, feature machine)

pub trait MachineController (machine.rs:273) — one trait, two impls: start, stop (idempotent), exec, wait_ready (machine.rs:275–:281). MachineSpec (machine.rs:124) describes a machine controller-agnostically: image (ImageRef, machine.rs:112), cpus, memory_mb, net (NetMode, machine.rs:53 — Nat | Isolated | Named), provision (Provision, machine.rs:80 — None | CloudInit | Ignition), mounts, readiness (Readiness, machine.rs:94), and the report/agent channels serial_out/qga_sock (machine.rs:145,:150). needs_real_machine() (machine.rs:232) picks KVM over container when isolation, cloud-init, or a systemd-unit readiness is required.

KvmController (machine.rs:481, feature kvm) launches qemu: full_argv (machine.rs:571) builds the q35 argv with per-drive snapshot=on (base image never mutated), -nic none under Isolated, and the two virtio-serial ports org.skidbladnir.report + org.qemu.guest_agent.0. Seed/payload media are authored as pure-Rust FAT images via build_fat_image (machine.rs:511, fatfs) — no genisoimage. exec runs over the qemu-guest-agent (machine.rs:816); ContainerController (machine.rs:891, feature container) is the fast, stateless twin.

ImageCache (machine.rs:312) is content-addressed (SHA-256 keyed blobs + name pointers): put_bytes/put_file (machine.rs:339,:351) dedup by hash, path_for (machine.rs:380) re-hashes on read (verify-on-receipt; corruption is an error), import_znippy_set (machine.rs:439, feature znippy) imports a znippy archive of images.

The install matrix (matrix.rs, feature matrix)

Asserts, as data, that a product installs + starts + stays healthy across OSes (⇒ init backends) inside KVMs. A cell is (OsImage × Backend × scope).

CellOutcome (matrix.rs:111) = Passed | Unhealthy | NoReport{reason} | Skipped{reason}; ProbeReport (matrix.rs:63) — service, backend, os, running, pid, ports, health, logs_tail, asserted_at; is_healthy() (matrix.rs:81) = running && health.ok.

The injected probe (probe/)

skidbladnir-probe (static musl, std-only) introspects the just-installed service and prints one JSON line: running?/pid (systemd is-active/MainPID, OpenRC rc-service status/pidfile, or a /proc scan fallback), ports (TcpStream::connect), health (ComponentSpec Tcp/Http), logs tail. skidbladnir-testsvc is the trivial "product" it asserts on — binds a port and answers GET /health with 200 OK. Both run under systemd and OpenRC.

Contract

tests/install_matrix_live.rs::live_install_matrix (install_matrix_live.rs:31, #[ignore], heavy) boots 4 OS guests (ubuntu-24.04 / debian-12 / fedora-42 → systemd; alpine-3.21 → OpenRC), runs run_matrix, sinks the rows, and asserts at least two distinct OS guests round-tripped a ProbeReport (install_matrix_live.rs:102).