Support Linux hosts (KVM) and add Void Linux as a managed environment - #2
Support Linux hosts (KVM) and add Void Linux as a managed environment#2EnigmataTech wants to merge 1 commit into
Conversation
…a managed environment QEMU engine now runs on Linux (KVM instead of WHPX, unzip/curl instead of tar.exe/curl.exe, XDG data dir resolution) in addition to Windows, so the same binary can drive a remote/headless Linux host over the network. On top of that, add Void Linux as a second first-class managed environment alongside Arch, selectable per-session via --family: - new DistroFamily::Void, xbps/runit provisioning path alongside pacman/systemd - ext4 reader gains a prefix-matched fallback for kernel/initramfs filenames, since Void versions them (vmlinuz-<ver>) instead of Arch's fixed names - provision_via_serial hardened: wait for the getty session to stop respawning before sending commands, and flow-control each send against the guest's terminal echo instead of a blind fixed delay -- fixes a real corruption bug in guest provisioning, not Void-specific - chpasswd now given an explicit crypt method (some base images have no default ENCRYPT_METHOD, so it silently no-ops otherwise) - dbus enabled alongside the display manager (hard prerequisite for lightdm/gdm/sddm, previously missing) Validated end-to-end on a Void base image: boot, XFCE + lightdm install, credential provisioning, and a working graphical login over VNC. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
NAME0x0
left a comment
There was a problem hiding this comment.
Reviewed the full diff and built/ran the branch on Windows: cargo build is clean and 275/275 tests pass on x86_64-pc-windows-msvc (the count is higher than your 202 because main has moved; your branch's merge-base is current main, no conflicts). So the Windows/WHPX path you flagged in the test plan compiles and its test surface is green here — I have not booted a guest on Windows from this branch yet.
The general fixes in here are the best part and stand on their own merit, independent of Void: the flow-controlled serial send (waiting for the guest echo instead of a blind 700ms), the getty-respawn settle loop, chpasswd -c SHA512, and enabling dbus before the display manager. Those are real Arch bugs. Thanks.
One blocking issue, one related, and a few smaller things.
1. Family scoping is incomplete — --family void will silently boot Arch (blocking)
runtime_for_family makes base_os_image family-aware. Everything else in the session root stayed family-blind, and the default session name is pane for every subcommand:
| Path | Family-scoped? |
|---|---|
images/{family}-base.paneimg |
yes (this PR) |
disks/root-overlay.qcow2 |
no |
engines/distro-kernel.img |
no |
engines/distro-initramfs.img |
no |
state/base-os-image.json |
no |
disks/user-data.qcow2 |
no |
Both derivation paths are cache-first:
extract_from_base_image(src/app.rs:3046) —if cache.exists() { return Ok(cache) }ensure_qcow2_overlay(src/qemu.rs:438) —if overlay.exists() { return Ok(()) }
So on any machine that has already run Arch in session pane:
pane launch --family void
resolves the cached Arch vmlinuz, the cached Arch initramfs, and the existing root overlay whose qcow2 backing file is arch-base.paneimg. It boots Arch. No error, no warning, nothing Void involved — and --family void is right there in the command line saying otherwise.
This can't show up in your testing because a fresh Linux host with only Void registered has no Arch cache to collide with, but it's the default path for every existing Windows user who tries the new flag.
Smallest fix that closes it: fold family.slug() into those filenames the same way you did for the base image, e.g. root-overlay-{slug}.qcow2, distro-kernel-{slug}.img, distro-initramfs-{slug}.img. Alternatively give runtime_for_family a family-suffixed session root so the whole tree is separated — heavier, but it also fixes #2 below for free and leaves no other shared-state landmines.
Either way it'd be worth a test asserting two families in the same session resolve to different overlay/kernel/initramfs paths, since the existing runtime_for_family_derives_base_image_name test only covers the one field that was actually changed.
2. state/base-os-image.json is shared across families
register_base_os_image writes to paths.base_os_metadata, which runtime_for_family leaves as state/base-os-image.json. Registering a Void image into a session that already has Arch overwrites the Arch registration record — size, digest, format — while arch-base.paneimg is still sitting on disk. pane doctor / pane status then verify the Arch image against the Void digest and report it as corrupt.
Falls out of whichever fix you pick for #1.
3. --family accepts four values that can't work
The blanket ValueEnum derive on DistroFamily exposes ubuntu, debian, fedora, and unknown on every flag, and they show up in --help. They parse fine and then fail downstream with a missing-image error. Given is_mvp_supported() already encodes the real answer, it'd be better to reject them at parse time (a separate CLI-facing enum, or a value parser gated on is_mvp_supported) so --help only advertises what exists.
4. Smaller things
extract_file_by_namepicks the lexicographically-first match, not the newest. The sort iscontains("fallback")thena.0.cmp(&b.0), so with two kernels in/bootyou get whichever name sorts first — forvmlinuz-6.9.xvsvmlinuz-6.10.xthat happens to land on 6.10, but only by accident of string ordering. Fine for a single-kernel base image; worth at least a comment noting the assumption, since the whole point of the function is handling distros that version the filename.let _ = name;at the end ofextract_file_by_nameis dead — either drop the binding or use it in the "derived X from the base image" log line, which would actually be useful for confirming which kernel got picked.accel_flag()returnskvmfor every non-Windows target, including macOS, where it should behvf. Pane doesn't claim macOS today so this isn't urgent, butcfg!(windows)/else is a bit blunt for something named after the accelerator.unzipis a new hard dependency on Linux with no preflight.ensure_qemu_availablegives a nice actionable error for a missing QEMU; a missingunzipgetsCould not run unzip to extract the base image archive: ...fromio::Error. Worth the same treatment.- The Linux QEMU-missing hints are Arch-specific.
ensure_qemu_availableandqemu_not_found_messageboth suggestsudo pacman -S qemu-desktop, which is wrong advice on a Debian, Fedora, or (ironically) Void host. Something distro-neutral like "install your distribution'sqemu-system-x86_64package" would travel better. curl.exe→curlis fine on Windows (CreateProcessappends.exewhen the name has no extension), just noting it's a behavior change on the Windows path inside a Linux-support PR.
5. Void's catalog tier — worth discussing, not blocking
docs/product-contract.md has a Support Policy stating an environment shouldn't be surfaced unless it has import, bootstrap, launch, reconnect, reset/repair, logging, known-good defaults, and a support statement — "hidden or locked is better than exposed but unreliable" — and "Managed Environment Order" names Ubuntu LTS as the second first-class environment.
This PR sets Void to stage: Current, tier: FirstClass, launchable_now: true, while (by your own note) there's no hosted or auto-downloadable base image, no GUI exposure, and no Windows validation. That's a direct conflict with the written contract. Two coherent ways out — mark Void CuratedPreview / launchable_now: false until it has a hosted image, or amend product-contract.md and vision.md to change the stated environment order — but the current state has code and docs disagreeing. Happy to defer this until the above are sorted.
6. Docs
No docs changed in this PR. If it lands as-is, at minimum: --family is missing from docs/cli-reference.md; README.md says Windows-only in four places including a FAQ that answers "Yes"; and the README FAQ on distro support doesn't mention Void. I can take that pass once the code shape settles — no need for you to.
Nothing here is structural. #1 and #2 are one filename change away, and the rest is polish. The KVM/XDG/host-detection work and the serial-reliability fixes are solid.
Summary
unzip/curlinstead oftar.exe/curl.exe, XDG data-dir resolution), in addition to Windows.--family arch/--family voidoninstall-desktop,launch,runtime, andprovision.provision_via_serialreliability bugs uncovered while testing Void (getty respawn race, unpaced serial writes) — not Void-specific, benefits Arch too.chpasswdnow given an explicit crypt method, since some base images (Void's included) have no defaultENCRYPT_METHODand silently no-op otherwise.dbusnow enabled alongside the display manager (hard prerequisite for lightdm/gdm/sddm).Note: unlike Arch, there's no hosted/auto-downloaded Void base image yet — a
.paneimghas to be built and registered manually via--register-base-imagefor now.Test plan
cargo test— 202/202 passing (all pre-existing Arch tests untouched)🤖 Generated with Claude Code