feat(models): resolve CPU serial from source PPIN as common fallback
Centralize CPU identity in models.ResolveCPUSerialNumber: an explicit source serial wins, otherwise a valid source PPIN is used, placeholders rejected. Dell, H3C and Redfish apply it while parsing; canonical-device and Reanimator conversion apply it again at the output boundary. No identity is synthesized from socket/model/board serial. See ADL-058. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
9d701885da
commit
07c270cda2
@@ -20,7 +20,7 @@ func TestExportCSV_IncludesAllComponentTypesWithUsableSerials(t *testing.T) {
|
||||
Manufacturer: "Supermicro",
|
||||
},
|
||||
CPUs: []models.CPU{
|
||||
{Socket: 0, Model: "Xeon", SerialNumber: "CPU-001"},
|
||||
{Socket: 0, Model: "Xeon", PPIN: "D46E5D6B1D3E40E1"},
|
||||
},
|
||||
Memory: []models.MemoryDIMM{
|
||||
{Slot: "DIMM0", PartNumber: "MEM-PN", SerialNumber: "MEM-001", Manufacturer: "Samsung"},
|
||||
@@ -73,7 +73,7 @@ func TestExportCSV_IncludesAllComponentTypesWithUsableSerials(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
want := []string{"FRU-001", "BOARD-001", "CPU-001", "MEM-001", "SSD-001", "GPU-001", "PCIE-001", "NIC-001", "LNIC-001", "PSU-001"}
|
||||
want := []string{"FRU-001", "BOARD-001", "D46E5D6B1D3E40E1", "MEM-001", "SSD-001", "GPU-001", "PCIE-001", "NIC-001", "LNIC-001", "PSU-001"}
|
||||
for _, sn := range want {
|
||||
if !serials[sn] {
|
||||
t.Fatalf("expected serial %s in csv export", sn)
|
||||
|
||||
@@ -113,12 +113,13 @@ func buildDevicesFromLegacy(hw *models.HardwareConfig) []models.HardwareDevice {
|
||||
details := mergeDetailMaps(nil, cpu.Details)
|
||||
details = mergeDetailMaps(details, map[string]any{
|
||||
"socket": cpu.Socket,
|
||||
"ppin": cpu.PPIN,
|
||||
})
|
||||
appendDevice(models.HardwareDevice{
|
||||
Kind: models.DeviceKindCPU,
|
||||
Slot: fmt.Sprintf("CPU%d", cpu.Socket),
|
||||
Model: cpu.Model,
|
||||
SerialNumber: cpu.SerialNumber,
|
||||
SerialNumber: models.ResolveCPUSerialNumber(cpu.SerialNumber, cpu.PPIN),
|
||||
Cores: cpu.Cores,
|
||||
Threads: cpu.Threads,
|
||||
FrequencyMHz: cpu.FrequencyMHz,
|
||||
@@ -837,7 +838,10 @@ func convertCPUsFromDevices(devices []models.HardwareDevice, collectedAt, boardS
|
||||
UncorrectableErrorCount: int64FromDetailMap(d.Details, "uncorrectable_error_count"),
|
||||
LifeRemainingPct: floatFromDetailMap(d.Details, "life_remaining_pct"),
|
||||
LifeUsedPct: floatFromDetailMap(d.Details, "life_used_pct"),
|
||||
SerialNumber: strings.TrimSpace(d.SerialNumber),
|
||||
SerialNumber: models.ResolveCPUSerialNumber(
|
||||
d.SerialNumber,
|
||||
stringFromDetailMap(d.Details, "ppin"),
|
||||
),
|
||||
Firmware: firstNonEmptyString(
|
||||
stringFromDetailMap(d.Details, "microcode"),
|
||||
microcodeBySocket[socket],
|
||||
@@ -1529,7 +1533,7 @@ func convertCPUs(cpus []models.CPU, collectedAt string) []ReanimatorCPU {
|
||||
Threads: cpu.Threads,
|
||||
FrequencyMHz: cpu.FrequencyMHz,
|
||||
MaxFrequencyMHz: cpu.MaxFreqMHz,
|
||||
SerialNumber: strings.TrimSpace(cpu.SerialNumber),
|
||||
SerialNumber: models.ResolveCPUSerialNumber(cpu.SerialNumber, cpu.PPIN),
|
||||
Firmware: "",
|
||||
Manufacturer: manufacturer,
|
||||
Status: cpuStatus,
|
||||
@@ -2793,4 +2797,3 @@ func inferTargetHost(targetHost, filename string) string {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
@@ -320,6 +320,31 @@ func TestConvertToReanimator_CPUSerialIsNotSynthesizedAndSocketIsDeduped(t *test
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertToReanimator_CPUSerialUsesPPINFallback(t *testing.T) {
|
||||
input := &models.AnalysisResult{
|
||||
Hardware: &models.HardwareConfig{
|
||||
BoardInfo: models.BoardInfo{SerialNumber: "BOARD-001"},
|
||||
Devices: []models.HardwareDevice{{
|
||||
Kind: models.DeviceKindCPU,
|
||||
Slot: "CPU0",
|
||||
Model: "Intel Xeon",
|
||||
Details: map[string]any{
|
||||
"socket": 0,
|
||||
"ppin": "D46E5D6B1D3E40E1",
|
||||
},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
out, err := ConvertToReanimator(input)
|
||||
if err != nil {
|
||||
t.Fatalf("ConvertToReanimator() failed: %v", err)
|
||||
}
|
||||
if len(out.Hardware.CPUs) != 1 || out.Hardware.CPUs[0].SerialNumber != "D46E5D6B1D3E40E1" {
|
||||
t.Fatalf("expected CPU serial fallback from PPIN, got %+v", out.Hardware.CPUs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertToReanimator_ExportsEventLogsAndOmitsPCIeBDFJSON(t *testing.T) {
|
||||
input := &models.AnalysisResult{
|
||||
Filename: "events.json",
|
||||
|
||||
Reference in New Issue
Block a user