fix(localapi): F2 mount-role fallback — enrolled user-data drives ejectable again (v0.73.0)

roleForMountPath resolved role only from the PVE storage view; a bind-mounted
RAW enrolled user-data drive is not a PVE storage, so it fail-safe'd to system
and the eject/decommission gates 403'd EVERY user-data drive in the standard
topology (campaign F2, where=/mnt/teszt_enroll role=system). Add a mount-table
fallback mirroring durableIDForMount Impl-2b: device-keyed classification with a
whole-disk containment pass (new storage.SameWholeDisk) and the Observe-error
early return kept BEFORE the fallback (else a blind view -> permissive). Only
roleForMountPath touched. Tests A1/B1/B2/C1-C3 + 3 red-proofs; existing RoleGated
tests green unmodified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-06 20:07:45 +02:00
parent 26664d6d51
commit 7545af8a2c
4 changed files with 266 additions and 4 deletions
+11
View File
@@ -136,3 +136,14 @@ func RoleForRawDevice(device string, sysDisks map[string]bool, sysKnown bool) De
}
return RoleUserData
}
// SameWholeDisk reports whether two device paths live on the same physical whole disk
// (e.g. /dev/sdb and /dev/sdb1). Storage targets carry BOTH granularities in practice (a dir
// storage's BackingDevice is the mounted PARTITION, a raw enrolled drive mounts the WHOLE disk),
// so containment checks must compare at whole-disk level — mirroring isSystemBacked. False when
// either side's whole-disk is unrecognizable (device-mapper/network) — callers fail safe.
func SameWholeDisk(a, b string) bool {
wa, oka := wholeDiskOf(a)
wb, okb := wholeDiskOf(b)
return oka && okb && wa == wb
}