controller v0.67.2: gate keys present on BoundUnderParent (reboot convergence)

The drive-absent gate treats a stable path usable only when bound under the parent
(BoundUnderParent), not merely host-mounted. Makes a host reboot converge: apps
stay gated until the agent binds the drive under the parent, then are restarted
(recreated) on the populated path. Test updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 17:10:02 +02:00
parent 38294d4eb5
commit 3adfa41a09
3 changed files with 23 additions and 7 deletions
+8 -4
View File
@@ -90,13 +90,17 @@ func planDriveGates(paths []settings.StoragePath, disks []agentapi.DiskInfo) []g
present := map[string]bool{}
rawByPath := map[string]string{}
for _, d := range disks {
live := d.State == "attached"
// A STABLE path is usable only when the drive's felhom-data is actually BOUND UNDER THE PARENT
// (BoundUnderParent) — NOT merely when the raw drive is host-mounted (State==attached). This is
// what makes the gate converge a reboot correctly: at boot the raw drive mounts early but the
// agent binds it under the parent slightly later; until then the apps' stable-path binds are empty,
// so the gate keeps them stopped and restarts (recreates) them once the bind is live.
if d.GuestPath != "" {
present[d.GuestPath] = present[d.GuestPath] || live
present[d.GuestPath] = present[d.GuestPath] || d.BoundUnderParent
rawByPath[d.GuestPath] = d.MountPath
}
if d.MountPath != "" { // legacy: a raw path registered directly
present[d.MountPath] = present[d.MountPath] || live
if d.MountPath != "" { // legacy raw path registered directly — host mount is the usable signal
present[d.MountPath] = present[d.MountPath] || d.State == "attached"
rawByPath[d.MountPath] = d.MountPath
}
}