VIRTUALIZATION.md: storage decision revised — a Disk location picker, plain files on grid's root disk

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-10-11 14:36:06 -07:00
co-authored by Claude Fable 5.1
parent ae72e45bf5
commit faf444d8ce
+24 -21
View File
@@ -1,20 +1,17 @@
# Virtualization tab — plan (2026-10-09; phase 1 built the same day) # Virtualization tab — plan (2026-10-09; phase 1 built the same day)
**Status:** phases 1 and 2 are **deployed to all five machines as v0.1.0-188** (2026-10-09). **Status:** phases 1 and 2 are **deployed to all five machines as v0.1.0-196** (2026-10-11).
Incus runs on `grid` (installed from the tab); the other machines show Install or, on `gate`, Incus runs on `grid` with **plain-files storage on its root disk** (`local`, see decision 1,
unavailable. Phase 2 verified live on `grid` through the hub: ISO fetched by URL with its revised 2026-10-11 — the file-backed ZFS pool and the test VM are gone); the other machines
sha256 checked, **New VM from ISO** booted Alpine with Secure Boot off, **the VGA console show Install or, on `gate`, unavailable. A **Disk location** picker is on both create forms,
drew it in a real browser** (headless Chromium, 1280×800 canvas, keyboard and mouse live), with add/remove of locations. Phase 2 verified live on `grid` through the hub on 2026-10-09:
a virtiofs mount appeared in a running VM, an export tarball landed in `virt/exports/` and the ISO fetched by URL with its sha256 checked, New VM from ISO booted Alpine with Secure Boot
nightly cron line is written, `instance.*` sensors flow and the "VM or container down" alert off, the VGA console drew it in a real browser (headless Chromium; needed the `binary`
default is in. Two things found and fixed on the way: spice-html5 wants the `binary` websocket subprotocol and one console operation per VM with a data websocket per SPICE
websocket subprotocol agreed; and it opens one websocket per SPICE channel, so the bridge channel), a virtiofs mount appeared in a running VM, an export tarball landed and the nightly
holds **one console operation per VM** and gives each channel its own data websocket on it cron line is written, `instance.*` sensors flow and the "VM or container down" alert default
(Incus refuses a second operation as "already connected"). **Left from phase 2:** the LAN is in. **Left:** the LAN bridge step (his call, needs him near the NanoKVM), cloud-init
bridge step (`br0` on the uplink — needs a live test on a machine that can afford to drop presets beyond "Use my SSH keys", a backup line for `grid`'s `virt/exports/`.
off the network for a moment, which is a decision, not a build), cloud-init presets beyond
"Use my SSH keys", and a backup line for `grid`'s `virt/exports/` (see `hamlet/docs/backups.md`).
`t-alpine` on `grid` is the live example; delete it from the tab when done.
A tab for creating, watching, consoling into and deleting **LXC containers and KVM virtual A tab for creating, watching, consoling into and deleting **LXC containers and KVM virtual
machines**, the way Proxmox does with `pct` and `qm` — **per machine, like every other machines**, the way Proxmox does with `pct` and `qm` — **per machine, like every other
@@ -236,12 +233,18 @@ like everything else.
## Layout decisions Ham Lab makes per machine (overridable in the Install dialog) ## Layout decisions Ham Lab makes per machine (overridable in the Install dialog)
1. **Storage.** The instance pool's backing lives in Ham Lab's folder: Install creates a 1. **Storage — revised 2026-10-11.** The create forms carry a **Disk location** picker: a
sparse `virt/pool.img` and hands it to Incus as the pool's `source` (zfs or btrfs by the list of the machine's Incus storage pools, each described by where its bytes land, with
detection above), or `virt/pool/` as a `dir` pool where neither is available. Sized from "+ add a location" (any folder on the machine becomes a plain-files pool). On `grid` the
the disk's free space, shown and editable. Bulk data is **bind-mounted in**, not stored in one location is `local`: plain files under `virt/pool/` on the root NVMe, each VM's disk
the pool. The driver, path and size are recorded in `virt.json` so the page can say where its own sparse file sized on its own, each container a directory, nothing pre-sized.
the data is and Install can rebuild the pool from the file after a reinstall. *The first design* (a ZFS pool inside one sparse file, handed to Incus as the pool's
source, for instant snapshots and clones) was built, ran for two days, and was taken out
at Mitchell's instruction: one pre-sized file holding every disk is an opaque middle
layer with a number on it that reads as a reservation, and "zfs · hamlab-virt" on the page
read as the NAS pool. The Install dialog still offers zfs/btrfs-in-a-file for a machine
that wants instant snapshots; the labels now say exactly what each is. Bulk data is still
**bind-mounted in**, not stored in the pool.
2. **Bridge subnet, computed.** Incus's `auto` picks a random `10.x.y.0/24`, and **this 2. **Bridge subnet, computed.** Incus's `auto` picks a random `10.x.y.0/24`, and **this
LAN is `10.0.0.0/8`** — every host has a /8 on its NIC, so any 10.x bridge collides. LAN is `10.0.0.0/8`** — every host has a /8 on its NIC, so any 10.x bridge collides.
Ham Lab reads the machine's routes and picks the first free /24 from `192.168.0.0/16`, Ham Lab reads the machine's routes and picks the first free /24 from `192.168.0.0/16`,