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:
Mikhail Chusavitin
2026-08-27 17:05:40 +03:00
co-authored by Claude Sonnet 5
parent 9d701885da
commit 07c270cda2
13 changed files with 122 additions and 19 deletions
@@ -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",