Normalize typed SMART device labels for temp merge

This commit is contained in:
rcourtman
2026-04-05 21:13:34 +01:00
parent b83f717ce7
commit 22f8dd3bbb
2 changed files with 71 additions and 6 deletions
+51
View File
@@ -104,6 +104,26 @@ func TestMergeNVMeTempsIntoDisks(t *testing.T) {
{Node: "node1", DevPath: "/dev/sdc", Temperature: 35},
},
},
{
name: "SMART temperature matched by typed device label",
disks: []models.PhysicalDisk{
{Node: "node1", DevPath: "/dev/sdd", Temperature: 0},
},
nodes: []models.Node{
{
Name: "node1",
Temperature: &models.Temperature{
Available: true,
SMART: []models.DiskTemp{
{Device: "sdd [scsi]", Temperature: 39},
},
},
},
},
expected: []models.PhysicalDisk{
{Node: "node1", DevPath: "/dev/sdd", Temperature: 39},
},
},
{
name: "NVMe legacy fallback when no SMART match",
disks: []models.PhysicalDisk{
@@ -331,3 +351,34 @@ func TestMergeNVMeTempsIntoDisks_OriginalSliceUnchanged(t *testing.T) {
t.Errorf("original disk temperature was modified: got %d, want 0", original[0].Temperature)
}
}
func TestMergeHostAgentSMARTIntoDisks_MatchesTypedDeviceLabel(t *testing.T) {
disks := []models.PhysicalDisk{{
Node: "node1",
Instance: "inst",
DevPath: "/dev/sda",
Temperature: 0,
}}
nodes := []models.Node{{
Name: "node1",
Instance: "inst",
LinkedHostAgentID: "host-1",
}}
hosts := []models.Host{{
ID: "host-1",
Sensors: models.HostSensorSummary{
SMART: []models.HostDiskSMART{{
Device: "/dev/sda [scsi]",
Temperature: 41,
}},
},
}}
merged := mergeHostAgentSMARTIntoDisks(disks, nodes, hosts)
if len(merged) != 1 {
t.Fatalf("expected 1 merged disk, got %#v", merged)
}
if merged[0].Temperature != 41 {
t.Fatalf("expected SMART temperature 41, got %#v", merged[0])
}
}
+20 -6
View File
@@ -162,6 +162,20 @@ func (m *Monitor) getInstanceConfig(instanceName string) *config.PVEInstance {
return nil
}
func normalizeSMARTDeviceIdentifier(device string) string {
normalized := strings.TrimSpace(device)
if normalized == "" {
return ""
}
if base, suffix, found := strings.Cut(normalized, " ["); found && strings.HasSuffix(suffix, "]") {
normalized = base
}
normalized = strings.TrimSpace(normalized)
return strings.TrimPrefix(normalized, "/dev/")
}
func mergeNVMeTempsIntoDisks(disks []models.PhysicalDisk, nodes []models.Node) []models.PhysicalDisk {
if len(disks) == 0 || len(nodes) == 0 {
return disks
@@ -275,10 +289,10 @@ func mergeNVMeTempsIntoDisks(disks []models.PhysicalDisk, nodes []models.Node) [
// Last resort: match by device path (normalized)
if updated[i].Temperature == 0 {
normalizedDevPath := strings.TrimPrefix(updated[i].DevPath, "/dev/")
normalizedDevPath := normalizeSMARTDeviceIdentifier(updated[i].DevPath)
for _, temp := range smartTemps {
normalizedTempDev := strings.TrimPrefix(temp.Device, "/dev/")
if normalizedTempDev == normalizedDevPath {
normalizedTempDev := normalizeSMARTDeviceIdentifier(temp.Device)
if normalizedTempDev != "" && normalizedTempDev == normalizedDevPath {
if temp.Temperature > 0 && !temp.StandbySkipped {
updated[i].Temperature = temp.Temperature
log.Debug().
@@ -401,10 +415,10 @@ func mergeHostAgentSMARTIntoDisks(disks []models.PhysicalDisk, nodes []models.No
// Last resort: match by device path
if matched == nil {
normalizedDevPath := strings.TrimPrefix(updated[i].DevPath, "/dev/")
normalizedDevPath := normalizeSMARTDeviceIdentifier(updated[i].DevPath)
for j := range smartData {
normalizedDiskDev := strings.TrimPrefix(smartData[j].Device, "/dev/")
if normalizedDiskDev == normalizedDevPath {
normalizedDiskDev := normalizeSMARTDeviceIdentifier(smartData[j].Device)
if normalizedDiskDev != "" && normalizedDiskDev == normalizedDevPath {
matched = &smartData[j]
break
}