v0.84.0: ReassertNetworkMounts — NAS automount survives guest reboots (RCA fix 1)
Storage §8 decision table (stop + enable --now on idle triggers; active mounts untouched), daemon leg at startup with per-running-guest visibility verify, guest-hook post-start leg (root, direct systemctl, non-fatal). Red-proofs: always-rearm table FAIL; unwired hook FAIL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -1,3 +1,35 @@
|
||||
## v0.84.0 — ReassertNetworkMounts: NAS automount survives guest reboots (RCA fix 1) (2026-07-11)
|
||||
|
||||
Agent half of the RCA fix pair (controller v0.117.0). Source:
|
||||
`felhom.eu/documentation/audits/AUDIT-nas-cwa-rca-2026-07-11.md` — a fresh guest namespace inherits
|
||||
REAL submounts (ext4/nfs4) but NOT an idle autofs trigger, so after any guest reboot an idle NAS
|
||||
share silently degrades to a local stub inside the guest. The heal (re-create the automount → the
|
||||
fresh trigger-mount event propagates live into running guests) was live-proven in the RCA
|
||||
remediation; this release makes it automatic.
|
||||
|
||||
- **`internal/storage/netreassert.go`** `SudoHostOps.ReassertNetworkAutomounts`: per configured
|
||||
network mount, the §8 decision table — real nfs/nfs4/cifs mounted → skip (inherited); `autofs`
|
||||
trigger at the path → **stop + enable --now the `.automount`** (existing FELHOM_NETMOUNT sudoers
|
||||
verbs; there is NO restart grant); neither → skip (removed/orphan states owned by add/remove).
|
||||
Idempotent; per-share errors never stop the pass. Unit enumeration factored into
|
||||
`networkUnitEntries()` (shared with `ListNetworkMounts`, behavior unchanged).
|
||||
- **`internal/localapi/netreassert.go`** `Server.ReassertNetworkMounts`: the daemon leg — runs the
|
||||
host-global pass once, then best-effort verifies each RUNNING guest actually sees each share path
|
||||
(`GuestSeesMount`; the RCA's masking lesson). Type-asserted capability (the lean
|
||||
`NetworkStorageOps` interface and its fakes stay unchanged — the main.go
|
||||
`ReassertEnrolledMounts` pattern). Wired at agent startup after `ReassertGuestBinds`;
|
||||
deliberately NOT in the 20 s ticker (an idle trigger is healthy and must not be churned).
|
||||
- **`internal/guesthook/netreassert.go`** + `PhasePostStart`: the hook leg — PVE runs the hookscript
|
||||
as root, so `guest-hook <vmid> post-start` re-arms triggers with DIRECT systemctl and verifies
|
||||
via `GuestSeesPath` (hook-process mirror of GuestSeesMount). Non-fatal by contract (stderr → PVE
|
||||
task log; exit 0 always); 30 s bound. The installed wrapper snippet already forwards all phases —
|
||||
no snippet re-install needed.
|
||||
- Tests + red-proofs: §8 table (red-proof: always-rearm shape → FAIL "nfs → rearmed, want
|
||||
skip-active" — the live-mount churn the table prevents); rearm emits EXACTLY stop+enable-now on
|
||||
the right unit; active mount → ZERO systemctl calls; idempotent double-pass; hook wiring
|
||||
(red-proof: PhasePostStart case removed → FAIL "got []"); daemon leg verifies running guests
|
||||
only; invisible-share verify is WARN-only (non-fatal).
|
||||
|
||||
## v0.83.0 — observability pass: always-DEBUG capture ring + GET /debug/logs + heartbeat log-pull + gap-fill sweep (2026-07-11)
|
||||
|
||||
Agent half of the cross-repo observability task (controller v0.116.0 + hub v0.46.0). Motivating
|
||||
|
||||
Reference in New Issue
Block a user