agent v0.37.0: re-assert mounted-but-DISABLED units (live felhom-usb fix)

The skip-if-mounted optimization defeated the actual root cause: felhom-usb is
mounted now but its unit is `disabled`, so a host reboot would not auto-mount
it. ReassertEnrolledMounts now skips ONLY the durable steady state (mounted AND
enabled) via the pure shouldReassertMount; a mounted-but-disabled unit is
re-asserted so enable --now re-creates the wants-symlink. Enabled-state read by
privilege-free Lstat of the multi-user.target.wants symlink (unitEnabled) — no
systemctl is-enabled subprocess, no new sudoers entry.

Tests: TestShouldReassertMount (4 combos), TestUnitEnabled (wants-symlink).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-16 17:55:48 +02:00
parent a621f4c5a0
commit 3e39dbb4f8
4 changed files with 96 additions and 12 deletions
+10 -5
View File
@@ -18,16 +18,21 @@ already correct (by-UUID), but nothing re-asserted the unit at startup.
- `storage.parseFelhomMountUnit` — pure inverse of `renderMountUnit` (Name/UUID/Where/Type/Options) keyed
on a `Managed by felhom-agent` marker; ignores any foreign `.mount` unit.
- `(*SudoHostOps).ReassertEnrolledMounts(ctx)` — at startup (BEFORE binding into the guest) and on the
periodic 20s tick: for each enrolled `.mount` unit not currently mounted (per `/proc/mounts`), re-resolve
by UUID and re-run `EnsureMount` (idempotent `systemctl enable --now`) — re-enables a disabled unit AND
mounts the CURRENT device by UUID, so a `/dev/sdX` reshuffle is a no-op. Already-mounted drives are
skipped (no daemon-reload churn); an absent UUID is skipped (re-asserts on a later tick).
periodic 20s tick: for each enrolled `.mount` unit, re-resolve by UUID and re-run `EnsureMount`
(idempotent `systemctl enable --now`) — re-enables a disabled unit AND mounts the CURRENT device by
UUID, so a `/dev/sdX` reshuffle is a no-op. Skips ONLY the durable steady state (mounted AND enabled),
via the pure `shouldReassertMount`; a **mounted-but-DISABLED** unit (the exact live felhom-usb bug — it
serves now but a reboot would not auto-mount it) is still re-asserted to re-create the wants-symlink.
Enabled-state is read with a privilege-free `os.Lstat` of the `multi-user.target.wants` symlink
(`unitEnabled`) — no `systemctl is-enabled` subprocess, no new sudoers entry. An absent UUID is skipped
(re-asserts on a later tick).
- Wired in `main.go` ahead of `ReassertGuestBinds` so mounts are live before the guest binds re-assert.
- Tests (Linux, seam the device-resolution): `TestResolveStorageDevice_ToleratesDeviceLetterMove`
(UUID symlink moved sdb→sdc → resolves sdc; companion asserts the cached enroll-time node differs from
the freshly-resolved one — a node-based remount would target the wrong device), `..._AbsentAndScheme`
(absent UUID errors; only the `uuid:` scheme resolvable), `TestParseFelhomMountUnit` (render→parse
round-trip + rejects a foreign unit).
round-trip + rejects a foreign unit), `TestShouldReassertMount` (the four mounted/enabled combos — pins
the mounted-but-disabled re-assert), `TestUnitEnabled` (wants-symlink detection).
**TASK A2 — verdict: enrolling a NEW drive does NOT need an LXC restart.** The enroll path lands on the
live intermediary-mount `AttachDrive` (`/disks/guest-attach``handleDiskGuestAttach``AttachDrive`,