// Package supermicro provides parser for Supermicro BMC crashdump archives // Tested with: Supermicro SYS-821GE-TNHR (Crashdump format) // // IMPORTANT: Increment parserVersion when modifying parser logic! // This helps track which version was used to parse specific logs. package supermicro import ( "strings" "git.mchus.pro/mchus/logpile/internal/models" "git.mchus.pro/mchus/logpile/internal/parser" ) // parserVersion - version of this parser module // IMPORTANT: Increment this version when making changes to parser logic! const parserVersion = "1.0.0" func init() { parser.Register(&Parser{}) } // Parser implements VendorParser for Supermicro servers type Parser struct{} // Name returns human-readable parser name func (p *Parser) Name() string { return "SMC Crash Dump Parser" } // Vendor returns vendor identifier func (p *Parser) Vendor() string { return "supermicro" } // Version returns parser version // IMPORTANT: Update parserVersion constant when modifying parser logic! func (p *Parser) Version() string { return parserVersion } // Detect checks if archive matches Supermicro crashdump format // Returns confidence 0-100 func (p *Parser) Detect(files []parser.ExtractedFile) int { confidence := 0 for _, f := range files { path := strings.ToLower(f.Path) // Strong indicator for Supermicro Crashdump format if strings.HasSuffix(path, "cdump.txt") { // Check if it's really Supermicro crashdump format if containsCrashdumpMarkers(f.Content) { confidence += 80 } } // Cap at 100 if confidence >= 100 { return 100 } } return confidence } // containsCrashdumpMarkers checks if content has Supermicro crashdump markers func containsCrashdumpMarkers(content []byte) bool { s := string(content) // Check for typical Supermicro Crashdump structure return strings.Contains(s, "crash_data") && strings.Contains(s, "METADATA") && (strings.Contains(s, "bmc_fw_ver") || strings.Contains(s, "crashdump_ver")) } // Parse parses Supermicro crashdump archive func (p *Parser) Parse(files []parser.ExtractedFile) (*models.AnalysisResult, error) { result := &models.AnalysisResult{ Events: make([]models.Event, 0), FRU: make([]models.FRUInfo, 0), Sensors: make([]models.SensorReading, 0), } // Initialize hardware config result.Hardware = &models.HardwareConfig{ CPUs: make([]models.CPU, 0), } // Parse CDump.txt (JSON crashdump) if f := parser.FindFileByName(files, "CDump.txt"); f != nil { if err := ParseCrashDump(f.Content, result); err != nil { // Log error but continue parsing other files _ = err // Ignore error for now } } return result, nil }