Files
logpile/internal/parser/vendors/inspur/component_fru_test.go
T
Mikhail ChusavitinandClaude Sonnet 5 2fa0f78f94 fix(inspur): read RESTful FRU info and float fans_power from component.log
Diffing an NF5280M6 BMC dump against its BEE-SP live-CD bundle found two
blind spots in the combined-component.log onekeylog layout (no
devicefrusdr.log / asset.json):

- board manufacturer/product/part/uuid empty and stats.fru 0: the
  "RESTful FRU info:" JSON block was never parsed. New component_fru.go
  (ParseComponentLogFRU) flattens it to []models.FRUInfo, prefers the
  product-area system serial over the board PCB serial, and sets
  BoardInfo.UUID from system_uuid. Wired as a fallback only when
  result.FRU is still empty.
- zero fan sensors: FanRESTInfo.FansPower was int but this firmware
  writes "fans_power": 12.000000, so json.Unmarshal of the whole fan
  block failed. Changed to float64.

Also included: SOL smartd SCSI/SAS device-line parsing and diagnose.go
gofmt from concurrent work on the same live-CD-diff task. See ADL-064.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LffAvostt3uMkiUbVUiyM
2026-09-01 11:58:55 +03:00

62 lines
2.6 KiB
Go

package inspur
import (
"testing"
"git.mchus.pro/mchus/logpile/internal/models"
)
const componentLogFRUBlock = `RESTful FRU info:
[ { "device": { "id": 0, "name": "BMC_FRU", "system_uuid": "4fc4c29c-dfeb-03e6-0010-debf003f9071" },
"chassis": { "version": 1, "type": "Rack Mount Chassis", "part_number": "0", "serial_number": "0" },
"board": { "version": 1, "date": "Wed Dec 27 16:15:00 2023", "manufacturer": "Inspur", "product_name": "NF5280M6", "serial_number": "MBPC16R11762D90", "part_number": "YZMB-01642-102" },
"product": { "version": 1, "manufacturer": "Inspur", "product_name": "NF5280M6", "part_number": "0", "serial_number": "24C319579", "asset_tag": "24C319579" } },
{ "device": { "id": 1, "name": "PSU0_FRU", "system_uuid": "4fc4c29c-dfeb-03e6-0010-debf003f9071" },
"chassis": { "version": 0 }, "board": { "version": 0 },
"product": { "version": 1, "manufacturer": "Great Wall", "product_name": "GW-CRPS1300D2WM", "part_number": "V0310AD000000000", "serial_number": "2O01C174959" } } ]
BMC kernel version:
Linux`
func TestParseComponentLogFRU_BoardIdentityAndUUID(t *testing.T) {
hw := &models.HardwareConfig{}
fru := ParseComponentLogFRU([]byte(componentLogFRUBlock), hw)
if len(fru) != 2 {
t.Fatalf("expected 2 FRU entries, got %d", len(fru))
}
if hw.BoardInfo.UUID != "4fc4c29c-dfeb-03e6-0010-debf003f9071" {
t.Errorf("BoardInfo.UUID = %q, want the system_uuid", hw.BoardInfo.UUID)
}
extractBoardInfo(fru, hw)
if hw.BoardInfo.Manufacturer != "Inspur" {
t.Errorf("Manufacturer = %q, want Inspur", hw.BoardInfo.Manufacturer)
}
if hw.BoardInfo.ProductName != "NF5280M6" {
t.Errorf("ProductName = %q, want NF5280M6", hw.BoardInfo.ProductName)
}
// product-area serial (operator-facing), not the board PCB serial.
if hw.BoardInfo.SerialNumber != "24C319579" {
t.Errorf("SerialNumber = %q, want 24C319579", hw.BoardInfo.SerialNumber)
}
// "0" product part is a placeholder; fall back to the real board part.
if hw.BoardInfo.PartNumber != "YZMB-01642-102" {
t.Errorf("PartNumber = %q, want YZMB-01642-102", hw.BoardInfo.PartNumber)
}
// PSU vendor must not leak into the server manufacturer.
if fru[1].Manufacturer != "Great Wall" || fru[1].SerialNumber != "2O01C174959" {
t.Errorf("PSU FRU not preserved: %+v", fru[1])
}
}
func TestParseComponentLogFRU_AbsentSection(t *testing.T) {
hw := &models.HardwareConfig{}
if fru := ParseComponentLogFRU([]byte("RESTful CPU info:\n{ }\nRESTful Memory info:\n{ }"), hw); fru != nil {
t.Fatalf("expected nil for a log with no FRU section, got %+v", fru)
}
if hw.BoardInfo.UUID != "" {
t.Errorf("BoardInfo.UUID set to %q from a log with no FRU section", hw.BoardInfo.UUID)
}
}