v0.184.1 — E-2b keying fix: the backup-target branch was unreachable

Caught before deploy by tracing a.Path back to its source, not by a failure. The
0.184.0 image is superseded and must not be shipped.

ReconcileDriveGates resolves the target as isTarget[a.Path], and a.Path is the
REGISTERED StoragePath -- for an external drive that is the GUEST path
/mnt/felhom-drives/<name>, not the agent's host MountPath (/mnt/<name>) that
/disks reports. driveTargetByPath keyed on MountPath alone, so the lookup never
matched: every absent drive, the target included, fell through to the generic
storage_disconnected.

The alarm would have looked wired, passed its own unit tests, shipped, and been
silently wrong on exactly the drive it exists for -- the same defect class E-2b
was opened to fix, one level down.

Now keyed under BOTH paths, mirroring planDriveGates which already registers
present[] under GuestPath and MountPath for the same reason.

Red-proof: MountPath-only keying fails with "the backup target is not resolvable
by its GUEST path -- the gate passes a.Path (the registered StoragePath), so the
backup-target branch would never fire".

Green gate: build + vet + test rc=0, run separately from this commit.
This commit is contained in:
2026-07-29 08:30:36 +02:00
parent c1a63de1c7
commit 4d6c8a6056
3 changed files with 82 additions and 1 deletions
+10 -1
View File
@@ -600,8 +600,17 @@ func (s *Server) gateWhere(w http.ResponseWriter, r *http.Request) (string, bool
// intent was never recorded while the drive really is the target. An older agent omits the field, so
// every entry is false and we degrade to the generic disconnect alarm — never a wrong one.
func driveTargetByPath(disks []agentapi.DiskInfo) map[string]bool {
out := make(map[string]bool, len(disks))
out := make(map[string]bool, 2*len(disks))
for _, d := range disks {
// BOTH keyings, mirroring planDriveGates (which registers present[] under GuestPath AND
// MountPath). The gate's a.Path is the REGISTERED StoragePath, and for an external drive that
// is the GUEST path /mnt/felhom-drives/<name> — not the agent's host /mnt/<name>. Keying this
// map on MountPath alone made the backup-target branch unreachable: every absent drive,
// including the target, fell through to the generic storage_disconnected. Caught before
// deploy by tracing a.Path back to its source rather than assuming it matched.
if d.GuestPath != "" {
out[d.GuestPath] = d.BackupTarget
}
if d.MountPath != "" {
out[d.MountPath] = d.BackupTarget
}