agent v0.87.0: SystemDisks device-mapper walk — legacy-boot hosts get a working drive wizard (IA finding 2, MEDIUM)

Operator ruling 2026-07-13: walk the root's backing device through /sys/block/<dev>/slaves
recursively down to physical disks (dm AND md; topology, never VG names); those + any mounted-ESP
holder are system; the all-system fail-safe returns to being the WALK-FAILURE error case only.
SAFETY DIRECTION: a root-backing disk classified candidate is made impossible — per-branch
conservatism (any unresolvable slave fails the WHOLE walk -> ok=false -> the unchanged all-system
path).

- physicalDisksOf/walkSlaves in role.go (symlink canon -> wholeDiskOf fast path -> recursive
  slaves walk; cycle/depth guard; non-/dev sources unwalkable)
- HostReader.BlockSlaves(name) — the ONE new seam method; ProcHostReader reads
  /sys/block/<name>/slaves; all four test fakes mirror it
- role_walk_test.go: signature table (root-backing disk ALWAYS system across legacy-LVM /
  md-raid / EFI+raw / EFI+LVM / nested dm-on-md — NEVER weaken) + dead-wizard-lives +
  dangling-slave fail-safe (real sysKnown=false path) + cycle + empty-slaves; red-proofs A/B/D
  run->fail->revert (recorded in REPORT)
- §3 spike transcripts (drill legacy: dm-1->sda3->sda; felhom-pve: ESP+walk agree on sda ->
  byte-identical regression); caller audit: none relied on all-system as a feature
- format/mkfs paths, data-bearing guards, wizard UI untouched
This commit is contained in:
2026-07-13 13:15:03 +02:00
parent c20814e6c2
commit 3c174bc6f2
11 changed files with 450 additions and 63 deletions
+37
View File
@@ -1,3 +1,40 @@
## v0.87.0 — SystemDisks device-mapper walk: legacy-boot hosts get a working drive wizard (IA finding 2, MEDIUM) (2026-07-13)
On a legacy-boot PVE (LVM root, no mounted ESP) `SystemDisks` resolved NOTHING — `wholeDiskOf`
stops at `/dev/mapper/pve-root` — so the all-system fail-safe classified EVERY disk system and
the drive wizard could never offer a candidate (the IA validation's hot-added 5 GB disk stayed
invisible on the drill box). Operator ruling 2026-07-13: walk the root's backing device through
`/sys/block/<dev>/slaves` recursively down to physical disks (dm AND md; topology, never VG
names); those + any mounted-ESP holder are system; the all-system fail-safe returns to being the
WALK-FAILURE error case only. SAFETY DIRECTION: the outcome made impossible is a root-backing
disk classified candidate — per-branch conservatism means ANY unresolvable slave fails the whole
walk (`ok=false` → all-system, the unchanged code path).
- **`physicalDisksOf` + `walkSlaves`** (`internal/storage/role.go`): symlink-canonicalize →
fast-path `wholeDiskOf` (raw disks/partitions, unchanged) → recursive sysfs slaves walk for
virtual devices, with cycle/depth guard; non-`/dev` sources (ZFS datasets, NFS, overlay) stay
unwalkable → fail-safe. Partition slaves resolve via the existing regexes (`sda3 → /dev/sda`);
exotic partition names the regexes don't cover (e.g. `md0p1`) fail the walk → fail-safe.
- **`HostReader.BlockSlaves(name)`** — the ONE new seam method (root-free: sysfs is
world-readable): slaves list + hasDir; production reads `/sys/block/<name>/slaves`; every test
fake mirrors it. Live-probed (§3): physical disks carry an EMPTY slaves dir — hasDir alone is
not resolution; a virtual device with an empty/unlistable slaves dir fails the walk.
- **Behavior deltas:** legacy-boot LVM hosts now resolve (`{root's physical parents}`, ok=true)
— the wizard lives (still behind the untouched data-bearing/claim guards); EFI(+LVM) hosts are
byte-identical (ESP and walk agree on the same disk — §3 felhom-pve transcript + fixture);
md-raid roots mark BOTH members system. NEW protective delta: a host whose ROOT topology
cannot be fully grounded is now all-system even if an ESP resolved (pre-fix it silently
trusted the ESP alone; ruling's per-disk conservatism).
- **Tests** (`role_walk_test.go`, fake-sysfs fixtures mirroring the §3 transcripts): the
SIGNATURE table (root-backing disk(s) ALWAYS in the system set across legacy-LVM / md-raid /
EFI+raw / EFI+LVM / nested dm-on-md — never weaken), dead-wizard-lives (A), dangling-slave
fail-safe through the REAL sysKnown=false path (D), cycle guard, empty-slaves. Red-proofs
recorded: A pre-fix resolver → dead wizard reproduced; B walk-returns-dm-node → SIGNATURE
VIOLATION naming the missing disk; D conservatism removed → "scratch classified candidate
while walk incomplete".
- Format/mkfs paths, data-bearing guards, wizard UI: UNTOUCHED. MinAgent/controller coupling:
none (agent-internal classification).
## v0.86.0 — DR-tier-by-default: capability `inactive` state + F-3 provision-parent ownership (2026-07-12)
Agent half of the DR-tier-by-default batch (DRILL-day0-vm-2026-07-12; operator decisions: DR