package inspur import ( "encoding/json" "fmt" "regexp" "strings" "time" "git.mchus.pro/mchus/logpile/internal/models" ) // ParseComponentLog parses component.log file and extracts PSU and other info func ParseComponentLog(content []byte, hw *models.HardwareConfig) { if hw == nil { return } text := string(content) // Parse RESTful PSU info parsePSUInfo(text, hw) } // ParseComponentLogEvents extracts events from component.log (memory errors, etc.) func ParseComponentLogEvents(content []byte) []models.Event { var events []models.Event text := string(content) // Parse RESTful Memory info for Warning/Error status memEvents := parseMemoryEvents(text) events = append(events, memEvents...) return events } // PSUInfo represents the RESTful PSU info structure type PSUInfo struct { PowerSupplies []struct { ID int `json:"id"` Present int `json:"present"` VendorID string `json:"vendor_id"` Model string `json:"model"` SerialNum string `json:"serial_num"` FwVer string `json:"fw_ver"` RatedPower int `json:"rated_power"` Status string `json:"status"` } `json:"power_supplies"` } func parsePSUInfo(text string, hw *models.HardwareConfig) { // Find RESTful PSU info section re := regexp.MustCompile(`RESTful PSU info:\s*(\{[\s\S]*?\})\s*(?:RESTful|BMC|$)`) match := re.FindStringSubmatch(text) if match == nil { return } jsonStr := match[1] // Clean up the JSON (it might have newlines) jsonStr = strings.ReplaceAll(jsonStr, "\n", "") var psuInfo PSUInfo if err := json.Unmarshal([]byte(jsonStr), &psuInfo); err != nil { return } // Clear existing PSU data and populate with RESTful data hw.PowerSupply = nil for _, psu := range psuInfo.PowerSupplies { if psu.Present != 1 { continue } hw.PowerSupply = append(hw.PowerSupply, models.PSU{ Slot: formatPSUSlot(psu.ID), Model: psu.Model, WattageW: psu.RatedPower, SerialNumber: psu.SerialNum, Status: psu.Status, }) } } func formatPSUSlot(id int) string { return fmt.Sprintf("PSU%d", id) } // MemoryInfo represents the RESTful Memory info structure type MemoryInfo struct { MemModules []struct { MemModID int `json:"mem_mod_id"` MemModSlot string `json:"mem_mod_slot"` MemModSize int `json:"mem_mod_size"` MemModVendor string `json:"mem_mod_vendor"` MemModPartNum string `json:"mem_mod_part_num"` MemModSerial string `json:"mem_mod_serial_num"` Status string `json:"status"` } `json:"mem_modules"` } func parseMemoryEvents(text string) []models.Event { var events []models.Event // Find RESTful Memory info section re := regexp.MustCompile(`RESTful Memory info:\s*(\{[\s\S]*?\})\s*RESTful HDD`) match := re.FindStringSubmatch(text) if match == nil { return events } jsonStr := match[1] jsonStr = strings.ReplaceAll(jsonStr, "\n", "") var memInfo MemoryInfo if err := json.Unmarshal([]byte(jsonStr), &memInfo); err != nil { return events } // Generate events for memory modules with Warning or Error status for _, mem := range memInfo.MemModules { if mem.Status == "Warning" || mem.Status == "Error" || mem.Status == "Critical" { severity := models.SeverityWarning if mem.Status == "Error" || mem.Status == "Critical" { severity = models.SeverityCritical } description := fmt.Sprintf("Memory module %s: %s", mem.MemModSlot, mem.Status) if mem.MemModSize == 0 { description = fmt.Sprintf("Memory module %s not detected (capacity 0GB)", mem.MemModSlot) } events = append(events, models.Event{ ID: fmt.Sprintf("mem_%d", mem.MemModID), Timestamp: time.Now(), // No timestamp in source, use current Source: "Memory", SensorType: "memory", SensorName: mem.MemModSlot, EventType: "Memory Status", Severity: severity, Description: description, RawData: fmt.Sprintf("Slot: %s, Vendor: %s, P/N: %s, S/N: %s", mem.MemModSlot, mem.MemModVendor, mem.MemModPartNum, mem.MemModSerial), }) } } return events }