Inspur/Kaytus onekeylog dumps only exposed the mechanical carrier FRU serial (component/fru.txt Board Product) as board identity. That serial doesn't change when the actual NVIDIA HGX baseboard (SXM+NVSwitch "delta board") is swapped, causing false "board unchanged" conclusions. Parse the real HGX tray/baseboard Model/PartNumber/SerialNumber triples from HGX_HWInfo_FWVersion.log into a new HardwareConfig.HGX field, and normalize Redfish's NA/N-A placeholders to empty across HGX identity parsing. Closes #21 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
79 lines
3.3 KiB
Go
79 lines
3.3 KiB
Go
package inspur
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestParseHGXIdentity_ExtractsTrayAndBaseboard(t *testing.T) {
|
|
content := []byte(`
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Chassis/HGX_Tray_0/Assembly
|
|
{"Name":"HGX Tray Assembly","Model":"P6612-A04","PartNumber":"699-26612-0000-P00","SerialNumber":"TRAYSN1"}
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Systems/HGX_Baseboard_0
|
|
{"Model":"NVIDIA HGX B200 8 GPU","PartNumber":"935-26287-00A0-000","SerialNumber":"BBSN1"}
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Systems/HGX_Baseboard_0/Processors/GPU_SXM_1
|
|
{"Model":"B200 180GB HBM3e","PartNumber":"692-2G525-0220-501","SerialNumber":"GPUSN1"}
|
|
`)
|
|
|
|
identity := parseHGXIdentity(content)
|
|
if identity == nil {
|
|
t.Fatal("expected non-nil identity")
|
|
}
|
|
if identity.Tray.Model != "P6612-A04" || identity.Tray.PartNumber != "699-26612-0000-P00" || identity.Tray.SerialNumber != "TRAYSN1" {
|
|
t.Fatalf("unexpected tray identity: %+v", identity.Tray)
|
|
}
|
|
if identity.Baseboard.Model != "NVIDIA HGX B200 8 GPU" || identity.Baseboard.PartNumber != "935-26287-00A0-000" || identity.Baseboard.SerialNumber != "BBSN1" {
|
|
t.Fatalf("unexpected baseboard identity: %+v", identity.Baseboard)
|
|
}
|
|
// The per-GPU Processors path must never leak into baseboard/tray identity.
|
|
if identity.Baseboard.SerialNumber == "GPUSN1" || identity.Tray.SerialNumber == "GPUSN1" {
|
|
t.Fatalf("GPU serial leaked into baseboard/tray identity: %+v", identity)
|
|
}
|
|
}
|
|
|
|
func TestParseHGXIdentity_DetectsBaseboardSwapAcrossDumps(t *testing.T) {
|
|
dumpA := []byte(`
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Chassis/HGX_Tray_0/Assembly
|
|
{"Name":"HGX Tray Assembly","Model":"P6612-A04","PartNumber":"699-26612-0000-P00","SerialNumber":"TRAY-1"}
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Systems/HGX_Baseboard_0
|
|
{"Model":"NVIDIA HGX B200 8 GPU","PartNumber":"935-26287-00A0-000","SerialNumber":"BB-1"}
|
|
`)
|
|
dumpC := []byte(`
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Chassis/HGX_Tray_0/Assembly
|
|
{"Name":"HGX Tray Assembly","Model":"P6612-A04","PartNumber":"699-26612-0000-P00","SerialNumber":"TRAY-2"}
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Systems/HGX_Baseboard_0
|
|
{"Model":"NVIDIA HGX B200 8 GPU","PartNumber":"935-26287-00A0-000","SerialNumber":"BB-2"}
|
|
`)
|
|
|
|
a := parseHGXIdentity(dumpA)
|
|
c := parseHGXIdentity(dumpC)
|
|
if a == nil || c == nil {
|
|
t.Fatal("expected identity from both dumps")
|
|
}
|
|
if a.Baseboard.SerialNumber == c.Baseboard.SerialNumber {
|
|
t.Fatal("expected baseboard serial to differ across dumps that recorded a swap")
|
|
}
|
|
if a.Tray.SerialNumber == c.Tray.SerialNumber {
|
|
t.Fatal("expected tray serial to differ across dumps that recorded a swap")
|
|
}
|
|
}
|
|
|
|
func TestParseHGXIdentity_TreatsNAAsAbsent(t *testing.T) {
|
|
content := []byte(`
|
|
# curl -X GET http://127.0.0.1/redfish/v1/Systems/HGX_Baseboard_0
|
|
{"Model":"NA","PartNumber":"NA","SerialNumber":"NA"}
|
|
`)
|
|
|
|
if identity := parseHGXIdentity(content); identity != nil {
|
|
t.Fatalf("expected nil identity when all fields are NA, got %+v", identity)
|
|
}
|
|
}
|
|
|
|
func TestParseHGXIdentity_NoHGXContentReturnsNil(t *testing.T) {
|
|
if identity := parseHGXIdentity(nil); identity != nil {
|
|
t.Fatalf("expected nil identity for empty content, got %+v", identity)
|
|
}
|
|
if identity := parseHGXIdentity([]byte("no redfish paths here")); identity != nil {
|
|
t.Fatalf("expected nil identity when no HGX paths present, got %+v", identity)
|
|
}
|
|
}
|