Declare the persistent volumes a microvm archetype requires #26
No reviewers
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
allod/archetypes!26
Loading…
Reference in a new issue
No description provided.
Delete branch "agent/microvm-persistent-volumes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Gives a microVM the persistent disks it needs to be usable. Since #23 the inventory
runtimefact selects the guest module, but nothing declared volumes — so a machine choosingmicrovmcould not evaluate at all, failing on allod/vm's store-volume contract. This closes that:/nix/var/nixfor every microVM guest, plus the dev user's home for dev machines.It declares disks. It does not create, format, label or own an image — contract 13 keeps that an explicit deployer action, and allod/nexus's launcher already refuses a missing or unreadable image before QEMU starts.
Closes #25
Refs allod/strategy#20
Risk
R2, conditional on one gate: this slice validates no runtime behaviour. Nothing here proves a guest boots, mounts, or retains a byte.
microvm-testmust not be enabled or booted as a microVM on the strength of this PR — the store-lifecycle boots in a later slice are what license that, and the parent plan already blocks on them. Without that gate the honest score is R3.Every libvirt machine is untouched: declarations are gated on
runtime == "microvm"at the Nix level, so a libvirt machine's module list is unchanged. Rollback is a straight revert; nothing creates or mutates an image, so a revert cannot strand state.Validation
All four system derivations byte-identical to master, verified on clean trees:
Review also diffed the full check set: all nine pre-existing checks unchanged, only
runtime-module-selectionmoves.nix flake checkgreen, 10/10, reporting 19 negative cases.neededForBootrenders tox-initrd.mount, measured both ways — with it,/dev/disk/by-label/home /home/allod ext4 x-initrd.mount; without,defaults. Upstream auto-adds it only for the store-overlay mount, so the home volume sets it explicitly and an assertion now pins it against a profile forcing it off.Review history
Plan reviewed by
gpt-5.6-solathigheffort, then the diff reviewed adversarially. Both found real defects.The plan review refuted my central safety claim. An earlier draft said omitting
neededForBootcauses silent data loss — a machine that comes up healthy and discards work. That is wrong: the home entry rendersdefaultswith nonofail, so a corrupt image failslocal-fs.targetloudly into emergency. The real reasonneededForBootis required is contract 13's own — it moves validation into the initrd, before any writer can use the tmpfs directory underneath. Narrower defect, still worth closing, but the test exists to close a write window, not to prevent silent loss. The plan records the correction rather than quietly rewriting it.The diff review found the blocker: five of six sabotage fixtures for the image-root rules could not distinguish the assertion they named from a neighbour, because their needles were unanchored and the per-image validator produced the same substrings. Proven by deleting the assertion and watching five stay green. Now anchored to the option name; re-verified independently by neutering the assertion, at which point all six fire.
Seven smaller fixes rode along, including a real edge case: a volume declared with
mountPoint = null— which upstream supports and nexus fixtures use — collapsed to""and tripped a bogus duplicate-mount-point error.Residual risk worth a human eye
A privacy microVM gets no home volume, so that user's home lives on the tmpfs root and is discarded on reboot with no diagnostic. That follows contract 13, which scopes home to the dev archetype, but it is a real behavioural consequence nobody has written down as deliberate. Worth a decision before any privacy machine moves to this runtime.
The check now requires a privacy machine in the inventory, where before it needed only a dev machine. The throw is named and actionable and symmetric with the existing dev-machine throw, but it is a new input requirement on a redirected inventory.
nix flake checkpeak memory rose from ~4.0 GB to ~5.9 GB on a 7 GiB box with no swap.allod/memorynix.mdalready records configurations being OOM-killed near 7 GiB, so the next slice inherits a tighter budget. Sabotage fixtures are consumed once as thunks specifically to bound this; holding all sixteen live was measured as an OOM kill.One coverage regression, flagged in a comment where it happens. Every microVM fixture now carries volume declarations by design, so a selector mis-mapping
microvmto the qemu guest surfaces asThe option `microvm' does not existduring option-tree construction rather than as a marker mismatch. Loud, not silent; the libvirt direction stays pinned over every real machine.Plan:
allod/strategydev-plans/microvm-persistent-volumes.md.Scoped stability pass done on
5b8ea7f, rotated to a different model than the one that authored both the implementation and the fixes. All eight fixes verified sound and falsifiable where they claim falsifiability; both deliberate skips judged correct; no regression in the recursion workaround,size = 0semantics, theeither str pathtyping, the privacy-builder placement, or the four libvirt derivations.It confirmed the blocker fix independently: neutering the image-root assertion now turns up exactly six findings, one per fixture, each naming its own anchored needle. Before the fix that experiment produced one. It also verified the reworded comments are now true at source, checking the upstream microvm options, allod/vm's store module, and nexus's host composition rather than taking them on trust.
One LOW finding, now closed in
3a3b430. The unmounted-volume guard proved only that such a declaration is not rejected, never that it survives into the merged list — so a change silently dropping null-mountPoint entries would have left it green while the declarations vanished before allod/nexus could report them, and nexus at host composition is the only thing that reports an unmounted image. Verified falsifiable: simulating that drop names both images.Final state —
nix flake checkexit 0, all 10 checks, 5.71 GB peak measured withtime -v. All four derivations still byte-identical.Worth recording for whoever picks up the next slice: that peak sits on a 7 GiB box with no swap, and
allod/memorynix.mdalready notes configurations being OOM-killed near 7 GiB. Headroom was measured at ~840 MiB during a run. The next slice inherits that budget, and sabotage fixtures are already consumed one at a time specifically to stay inside it.