Gunnar

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`](matrix-reasoning.md).

![The install matrix](assets/install-matrix.svg)

## 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)`.

- `OsImage` (`matrix.rs:88`) — a cloud base image + its `Backend`. `test_service_spec(scope)`
  (`matrix.rs:150`) is the trivial `skidtest` service (`TEST_SERVICE`, `matrix.rs:42`) every cell
  installs, binding `TEST_PORT` 7070.
- `run_cell(...)` (`matrix.rs:247`) runs one cell end-to-end: `renderer_for(backend)` filter → if
  `None`, `Skipped{reason:"no renderer"}` (honest); else build the payload FAT image
  (`skidbladnir-probe` + `skidbladnir-testsvc` + rendered units), boot the KVM guest, and poll the
  serial report. `render_user_data` (`matrix.rs:171`) is the pure cloud-init that mounts the
  payload, runs the renderer's enable/start verbs, runs the probe, and tees the `ProbeReport` to
  `/dev/virtio-ports/org.skidbladnir.report`.
- `run_matrix(...)` (`matrix.rs:347`) is the cartesian `(OS × backend)` sweep; `sink_results`
  (`matrix.rs:368`) writes one `ProbeReport` JSON line per cell to `<root>/probe_reports.jsonl`
  **and** one `AirgapEvent` (`op = matrix_probe`) per cell (→ `airgap_events`, for nornir's autonom
  ingest).

`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`).