Merge reviewed Unraid empty-slot fix

Integrate the reviewed false-alert regression fix without re-parenting its verified candidate commit.

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-09-02 06:27:42 +01:00
6 changed files with 33 additions and 5 deletions
+2 -2
View File
@@ -522,10 +522,10 @@ func isUnraidEmptySlot(disk agentshost.UnraidDisk) bool {
// Unraid names every configured slot (for example disk6 or parity2), even
// when it has never been assigned. A slot label is therefore topology, not
// membership evidence. Preserve DISK_NP members only when native identity,
// device, filesystem, or size evidence shows that a disk was assigned.
// device, a concrete filesystem, or size evidence shows that a disk was assigned.
return strings.TrimSpace(disk.Device) == "" &&
!unraidstatus.HasMeaningfulIdentity(disk.Model, disk.Serial) &&
strings.TrimSpace(disk.Filesystem) == "" &&
!unraidstatus.HasMeaningfulFilesystem(disk.Filesystem) &&
disk.SizeBytes == 0
}
+4
View File
@@ -154,6 +154,7 @@ diskNumber.5=5
diskName.5=disk5
diskSize.5=0
diskId.5=ata-_
diskFsType.5=auto
rdevStatus.5=DISK_NP
rdevName.5=
rdevId.5=ata-_
@@ -161,6 +162,7 @@ diskNumber.29=29
diskName.29=parity2
diskSize.29=0
diskId.29=ata-_
diskFsType.29=auto
rdevStatus.29=DISK_NP_DSBL
rdevName.29=
rdevId.29=ata-_
@@ -286,6 +288,7 @@ id="ata-_"
size="0"
status="DISK_NP"
type="Data"
fsType="auto"
["parity2"]
idx="29"
name="parity2"
@@ -294,6 +297,7 @@ id="ata-_"
size="0"
status="DISK_NP_DSBL"
type="Parity"
fsType="auto"
`
disks := parseUnraidDisksINI(input)
+1 -1
View File
@@ -4147,7 +4147,7 @@ func isLegacyUnraidEmptySlot(disk agentshost.UnraidDisk, normalizedStatus string
}
return strings.TrimSpace(disk.Device) == "" &&
!unraidstatus.HasMeaningfulIdentity(disk.Model, disk.Serial) &&
strings.TrimSpace(disk.Filesystem) == "" &&
!unraidstatus.HasMeaningfulFilesystem(disk.Filesystem) &&
disk.SizeBytes == 0
}
@@ -2588,8 +2588,8 @@ func TestApplyHostReportFiltersLegacyUnraidEmptySlots(t *testing.T) {
Disks: []agentshost.UnraidDisk{
{Name: "parity", Device: "/dev/sdb", Role: "parity", RawStatus: "DISK_OK", SizeBytes: 5860522532},
{Name: "disk1", Device: "/dev/sde", Role: "data", RawStatus: "DISK_OK", SizeBytes: 5860522532},
{Name: "disk6", Role: "data", RawStatus: "DISK_NP", Model: "ata -", Serial: "ata-_", Slot: 6},
{Name: "parity2", Role: "parity", RawStatus: "DISK_NP_DSBL", Model: "ata -", Serial: "ata-_", Slot: 29},
{Name: "disk6", Role: "data", Status: "missing", RawStatus: "DISK_NP", Model: "ata -", Serial: "ata-_", Filesystem: "auto", Slot: 6},
{Name: "parity2", Role: "parity", Status: "missing", RawStatus: "DISK_NP_DSBL", Model: "ata -", Serial: "ata-_", Filesystem: "auto", Slot: 29},
},
},
Timestamp: time.Now().UTC(),
+9
View File
@@ -31,6 +31,15 @@ func HasMeaningfulIdentity(model, serial string) bool {
return NormalizeNativeIdentity(model) != "" || NormalizeNativeIdentity(serial) != ""
}
// HasMeaningfulFilesystem reports whether a native filesystem field is
// evidence that a slot has a disk assigned. Unraid emits "auto" for configured
// but empty DISK_NP slots, so presence of that value alone cannot establish
// membership.
func HasMeaningfulFilesystem(filesystem string) bool {
filesystem = strings.TrimSpace(filesystem)
return filesystem != "" && !strings.EqualFold(filesystem, "auto")
}
// IsExplicitMissingMember reports Unraid's provider-owned status for a slot
// that was assigned but whose device is no longer present. Plain DISK_NP means
// no device is assigned and must not be treated as equivalent.
+15
View File
@@ -35,3 +35,18 @@ func TestIsExplicitMissingMember(t *testing.T) {
}
}
}
func TestHasMeaningfulFilesystem(t *testing.T) {
t.Parallel()
for _, filesystem := range []string{"", "auto", " AUTO "} {
if HasMeaningfulFilesystem(filesystem) {
t.Errorf("%q must not establish Unraid disk assignment", filesystem)
}
}
for _, filesystem := range []string{"xfs", "btrfs", "luks:xfs"} {
if !HasMeaningfulFilesystem(filesystem) {
t.Errorf("%q must establish Unraid disk assignment", filesystem)
}
}
}