fix(inspur): parse CPUs from component.log and fix DIMM present detection
Two bugs in onekeylog archives that lack asset.json: - CPU count was always 0: ParseComponentLog never parsed the "RESTful CPU info" section. Added parseCPUInfo as a fallback when hw.CPUs is empty (asset.json remains the primary source when present). Also worked around a Go JSON case-insensitive collision between "proc_id" (int) and "PROC_ID" (string CPUID) by adding an explicit PROC_ID field with an exact-case tag. - Only 1 of 2 DIMMs shown: Present condition required mem_mod_size > 0, but some BMC firmware reports size=0 for a physically installed module while still providing serial and part number. Now treats a DIMM as present when status=1 and any of size/serial/partnum is non-empty. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
76
internal/parser/vendors/inspur/component.go
vendored
76
internal/parser/vendors/inspur/component.go
vendored
@@ -19,6 +19,11 @@ func ParseComponentLog(content []byte, hw *models.HardwareConfig) {
|
||||
|
||||
text := string(content)
|
||||
|
||||
// Parse RESTful CPU info — fallback when asset.json is absent
|
||||
if len(hw.CPUs) == 0 {
|
||||
parseCPUInfo(text, hw)
|
||||
}
|
||||
|
||||
// Parse RESTful Memory info (detailed memory data)
|
||||
parseMemoryInfo(text, hw)
|
||||
|
||||
@@ -61,6 +66,70 @@ func ParseComponentLogSensors(content []byte) []models.SensorReading {
|
||||
return out
|
||||
}
|
||||
|
||||
// CPURESTInfo represents the RESTful CPU info structure in component.log
|
||||
type CPURESTInfo struct {
|
||||
Processors []struct {
|
||||
ProcID int `json:"proc_id"`
|
||||
CPUID string `json:"PROC_ID"` // uppercase key — prevents case-insensitive collision with proc_id
|
||||
Manufacturer string `json:"Manufacturer"`
|
||||
MaxSpeedMHz int `json:"MaxSpeedMHz"`
|
||||
ConfigStatus int `json:"configStatus"`
|
||||
ProcName string `json:"proc_name"`
|
||||
ProcStatus int `json:"proc_status"`
|
||||
ProcSpeed int `json:"proc_speed"`
|
||||
CoreCount int `json:"proc_core_count"`
|
||||
ThreadCount int `json:"proc_thread_count"`
|
||||
TDP int `json:"proc_tdp"`
|
||||
L1Cache int `json:"proc_l1cache_size"`
|
||||
L2Cache int `json:"proc_l2cache_size"`
|
||||
L3Cache int `json:"proc_l3cache_size"`
|
||||
MicroCode string `json:"micro_code"`
|
||||
PPIN string `json:"ppin"`
|
||||
Status string `json:"status"`
|
||||
} `json:"processors"`
|
||||
}
|
||||
|
||||
func parseCPUInfo(text string, hw *models.HardwareConfig) {
|
||||
re := regexp.MustCompile(`RESTful CPU info:\s*(\{[\s\S]*?\})\s*RESTful Memory`)
|
||||
match := re.FindStringSubmatch(text)
|
||||
if match == nil {
|
||||
return
|
||||
}
|
||||
|
||||
jsonStr := strings.ReplaceAll(match[1], "\n", "")
|
||||
var cpuInfo CPURESTInfo
|
||||
if err := json.Unmarshal([]byte(jsonStr), &cpuInfo); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
seenMicrocode := make(map[string]bool)
|
||||
for _, proc := range cpuInfo.Processors {
|
||||
if proc.ProcStatus != 1 && proc.ConfigStatus != 1 {
|
||||
continue
|
||||
}
|
||||
hw.CPUs = append(hw.CPUs, models.CPU{
|
||||
Socket: proc.ProcID,
|
||||
Model: strings.TrimSpace(proc.ProcName),
|
||||
Cores: proc.CoreCount,
|
||||
Threads: proc.ThreadCount,
|
||||
FrequencyMHz: proc.ProcSpeed,
|
||||
MaxFreqMHz: proc.MaxSpeedMHz,
|
||||
L1CacheKB: proc.L1Cache,
|
||||
L2CacheKB: proc.L2Cache,
|
||||
L3CacheKB: proc.L3Cache,
|
||||
TDP: proc.TDP,
|
||||
PPIN: proc.PPIN,
|
||||
})
|
||||
if proc.MicroCode != "" && !seenMicrocode[proc.MicroCode] {
|
||||
hw.Firmware = append(hw.Firmware, models.FirmwareInfo{
|
||||
DeviceName: fmt.Sprintf("CPU%d Microcode", proc.ProcID),
|
||||
Version: proc.MicroCode,
|
||||
})
|
||||
seenMicrocode[proc.MicroCode] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MemoryRESTInfo represents the RESTful Memory info structure
|
||||
type MemoryRESTInfo struct {
|
||||
MemModules []struct {
|
||||
@@ -112,9 +181,10 @@ func parseMemoryInfo(text string, hw *models.HardwareConfig) {
|
||||
}
|
||||
for _, mem := range memInfo.MemModules {
|
||||
item := models.MemoryDIMM{
|
||||
Slot: mem.MemModSlot,
|
||||
Location: mem.MemModSlot,
|
||||
Present: mem.MemModStatus == 1 && mem.MemModSize > 0,
|
||||
Slot: mem.MemModSlot,
|
||||
Location: mem.MemModSlot,
|
||||
// status=1 with a known serial/part is definitely present even if BMC reports size=0
|
||||
Present: mem.MemModStatus == 1 && (mem.MemModSize > 0 || strings.TrimSpace(mem.MemModSerial) != "" || strings.TrimSpace(mem.MemModPartNum) != ""),
|
||||
SizeMB: mem.MemModSize * 1024, // Convert GB to MB
|
||||
Type: mem.MemModType,
|
||||
Technology: strings.TrimSpace(mem.MemModTechnology),
|
||||
|
||||
Reference in New Issue
Block a user