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:
@@ -1,5 +1,13 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v0.67.2 — gate: key "present" on BoundUnderParent (reboot convergence) (2026-06-15)
|
||||||
|
|
||||||
|
The drive-absent gate now treats a stable path as usable only when the agent reports it BOUND UNDER THE
|
||||||
|
PARENT (`BoundUnderParent`), not merely host-mounted (`State==attached`). This makes a host reboot
|
||||||
|
converge correctly: at boot the raw drive mounts early but the agent binds it under the parent slightly
|
||||||
|
later, so until then the apps' stable-path binds are empty — the gate keeps the apps stopped and
|
||||||
|
restarts (recreates) them once the bind is live. Legacy raw paths still use the host-mount signal.
|
||||||
|
|
||||||
### v0.67.1 — gate: only act on external drives under /mnt/felhom-drives/ (2026-06-15)
|
### v0.67.1 — gate: only act on external drives under /mnt/felhom-drives/ (2026-06-15)
|
||||||
|
|
||||||
Fix (caught live on the v0.67.0 deploy): `planDriveGates` marked the internal SSD path
|
Fix (caught live on the v0.67.0 deploy): `planDriveGates` marked the internal SSD path
|
||||||
|
|||||||
@@ -90,13 +90,17 @@ func planDriveGates(paths []settings.StoragePath, disks []agentapi.DiskInfo) []g
|
|||||||
present := map[string]bool{}
|
present := map[string]bool{}
|
||||||
rawByPath := map[string]string{}
|
rawByPath := map[string]string{}
|
||||||
for _, d := range disks {
|
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 != "" {
|
if d.GuestPath != "" {
|
||||||
present[d.GuestPath] = present[d.GuestPath] || live
|
present[d.GuestPath] = present[d.GuestPath] || d.BoundUnderParent
|
||||||
rawByPath[d.GuestPath] = d.MountPath
|
rawByPath[d.GuestPath] = d.MountPath
|
||||||
}
|
}
|
||||||
if d.MountPath != "" { // legacy: a raw path registered directly
|
if d.MountPath != "" { // legacy raw path registered directly — host mount is the usable signal
|
||||||
present[d.MountPath] = present[d.MountPath] || live
|
present[d.MountPath] = present[d.MountPath] || d.State == "attached"
|
||||||
rawByPath[d.MountPath] = d.MountPath
|
rawByPath[d.MountPath] = d.MountPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,13 @@ func TestPlanDriveGates(t *testing.T) {
|
|||||||
{Path: "/mnt/sys_drive/felhom-data"}, // INTERNAL SSD (absent from agent) → never gated
|
{Path: "/mnt/sys_drive/felhom-data"}, // INTERNAL SSD (absent from agent) → never gated
|
||||||
}
|
}
|
||||||
disks := []agentapi.DiskInfo{
|
disks := []agentapi.DiskInfo{
|
||||||
{MountPath: "/mnt/usb", GuestPath: "/mnt/felhom-drives/usb", State: "attached"},
|
// present = BoundUnderParent (the usable-in-guest signal), not merely State==attached.
|
||||||
{MountPath: "/mnt/back", GuestPath: "/mnt/felhom-drives/back", State: "attached"},
|
{MountPath: "/mnt/usb", GuestPath: "/mnt/felhom-drives/usb", State: "attached", BoundUnderParent: true},
|
||||||
// flash + gone + dead report NO present disk
|
{MountPath: "/mnt/back", GuestPath: "/mnt/felhom-drives/back", State: "attached", BoundUnderParent: true},
|
||||||
|
// flash reports State=attached but NOT bound under parent yet → still treated ABSENT (the
|
||||||
|
// reboot-ordering case: raw drive mounted, agent hasn't bound it under the parent yet).
|
||||||
|
{MountPath: "/mnt/flash", GuestPath: "/mnt/felhom-drives/flash", State: "attached", BoundUnderParent: false},
|
||||||
|
// gone + dead report NO present disk
|
||||||
}
|
}
|
||||||
actions := map[string]gateAction{}
|
actions := map[string]gateAction{}
|
||||||
for _, a := range planDriveGates(paths, disks) {
|
for _, a := range planDriveGates(paths, disks) {
|
||||||
|
|||||||
Reference in New Issue
Block a user