package inspur import ( "bufio" "regexp" "strings" "git.mchus.pro/mchus/logpile/internal/models" ) var ( fruDeviceRegex = regexp.MustCompile(`^FRU Device Description\s*:\s*(.+)$`) fruFieldRegex = regexp.MustCompile(`^\s+(.+?)\s*:\s*(.*)$`) platformIdRegex = regexp.MustCompile(`(?i)PlatformId\s*=\s*(\S+)`) ) // ParseFRU parses BMC FRU (Field Replaceable Unit) output func ParseFRU(content []byte) []models.FRUInfo { var fruList []models.FRUInfo var current *models.FRUInfo scanner := bufio.NewScanner(strings.NewReader(string(content))) for scanner.Scan() { line := scanner.Text() // Check for new FRU device if matches := fruDeviceRegex.FindStringSubmatch(line); matches != nil { if current != nil && current.Description != "" { fruList = append(fruList, *current) } current = &models.FRUInfo{ Description: strings.TrimSpace(matches[1]), } continue } // Skip if no current FRU device if current == nil { continue } // Skip "Device not present" entries if strings.Contains(line, "Device not present") { current = nil continue } // Parse FRU fields if matches := fruFieldRegex.FindStringSubmatch(line); matches != nil { fieldName := strings.TrimSpace(matches[1]) fieldValue := strings.TrimSpace(matches[2]) switch fieldName { case "Chassis Type": current.ChassisType = fieldValue case "Chassis Part Number": if fieldValue != "0" { current.PartNumber = fieldValue } case "Chassis Serial": if fieldValue != "0" { current.SerialNumber = fieldValue } case "Board Mfg Date": current.MfgDate = fieldValue case "Board Mfg", "Product Manufacturer": if fieldValue != "NULL" { current.Manufacturer = fieldValue } case "Board Product", "Product Name": if fieldValue != "NULL" { current.ProductName = fieldValue } case "Board Serial", "Product Serial": current.SerialNumber = fieldValue case "Board Part Number", "Product Part Number": if fieldValue != "0" { current.PartNumber = fieldValue } case "Product Version": if fieldValue != "0" { current.Version = fieldValue } case "Product Asset Tag": if fieldValue != "NULL" { current.AssetTag = fieldValue } } } } // Don't forget the last one if current != nil && current.Description != "" { fruList = append(fruList, *current) } return fruList } // extractBoardInfo extracts main board/chassis information from FRU data func extractBoardInfo(fruList []models.FRUInfo, hw *models.HardwareConfig) { if hw == nil || len(fruList) == 0 { return } // Look for the main board/chassis FRU entry. // Keep the first non-empty serial as the server serial and avoid overwriting it // with module-specific serials (e.g., SCM_FRU). for _, fru := range fruList { // Skip empty entries if fru.ProductName == "" && fru.SerialNumber == "" { continue } // Prioritize entries that look like main board info desc := strings.ToLower(fru.Description) isMainBoard := strings.Contains(desc, "builtin") || strings.Contains(desc, "fru device") || strings.Contains(desc, "chassis") || strings.Contains(desc, "board") if fru.SerialNumber != "" && hw.BoardInfo.SerialNumber == "" { hw.BoardInfo.SerialNumber = fru.SerialNumber } if fru.ProductName != "" && (hw.BoardInfo.ProductName == "" || isMainBoard) { hw.BoardInfo.ProductName = fru.ProductName } // Manufacturer from non-main FRU entries (e.g. PSU vendor) should not become server vendor. if fru.Manufacturer != "" && isMainBoard && hw.BoardInfo.Manufacturer == "" { hw.BoardInfo.Manufacturer = fru.Manufacturer } if fru.PartNumber != "" && (hw.BoardInfo.PartNumber == "" || isMainBoard) { hw.BoardInfo.PartNumber = fru.PartNumber } // Main board entry with complete data is good enough to stop. if isMainBoard && hw.BoardInfo.ProductName != "" && hw.BoardInfo.SerialNumber != "" { break } } } // extractPlatformId extracts server model from ThermalConfig (PlatformId) func extractPlatformId(content []byte, hw *models.HardwareConfig) { if hw == nil { return } if match := platformIdRegex.FindSubmatch(content); match != nil { platformId := strings.TrimSpace(string(match[1])) if platformId != "" { // Set as ProductName (server model) - this takes priority over FRU data hw.BoardInfo.ProductName = platformId // Also set manufacturer as Inspur if not already set if hw.BoardInfo.Manufacturer == "" { hw.BoardInfo.Manufacturer = "Inspur" } } } }