Older AMI-BMC Inspur onekeylog archives (NF5466M5 / NF5280M5 generation)
opened to an empty result: they carry none of the files the inspur parser
keys on (no asset.json, devicefrusdr.log, selelist.csv or component.log).
New package internal/parser/vendors/inspur_legacy (vendor id inspur_legacy),
separate from inspur:
- binary IPMI FRU decode (FRU.bin) -> board identity
- Inspur_AssetInfoInventory.log -> CPU / memory / PCIe / PSU inventory
- events from Inspur_<model>_<serial>_IDL, sel.log, blackbox.log,
MegaRAID raid0.log, and the flat AMI <severity>.log files
- no live sensors in this archive class -> recorded as a collection error
- BMC clock timestamps before 2010 dropped as un-set (1970 / ~2005 RTC)
Registry: add optional PrioritizedParser { DetectPriority() int } so a
confidence tie is broken by specificity. inspur_legacy returns 10 and also
declines (Detect 0) when modern Kaytus markers are present, so the two
Inspur parsers never fight over a newer dump.
Docs: ADL-065, 06-parsers.md, releases/v1.32.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017VL8wLGD6Lnp6hZCpqT6cZ
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package inspurlegacy
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"git.mchus.pro/mchus/logpile/internal/models"
|
|
)
|
|
|
|
const selTimeLayout = "01/02/2006 15:04:05"
|
|
|
|
// criticalSELPhrases escalate an otherwise-Info SEL record to critical.
|
|
var criticalSELPhrases = []string{
|
|
"ac lost", "power supply failure", "redundancy lost", "non-recoverable",
|
|
"uncorrectable", "input under voltage error",
|
|
"processor error", "thermal trip", "asserted - critical",
|
|
}
|
|
|
|
// warningSELPhrases escalate an otherwise-Info SEL record to warning.
|
|
var warningSELPhrases = []string{
|
|
"correctable", "warning", "degraded", "under voltage warning",
|
|
"redundancy degraded", "predictive failure",
|
|
}
|
|
|
|
// ParseSELLog parses the pipe-delimited sel.log. Real records are
|
|
// "id | MM/DD/YYYY | HH:MM:SS | sensor | event | Asserted|Deasserted".
|
|
// "Pre-Init Time-stamp" records have no usable timestamp and are skipped.
|
|
func ParseSELLog(content []byte) []models.Event {
|
|
var events []models.Event
|
|
for _, line := range strings.Split(string(content), "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" {
|
|
continue
|
|
}
|
|
fields := splitTrim(line, "|")
|
|
// Real records have 5 or 6 columns: id | date | time | sensor | event
|
|
// [ | Asserted/Deasserted ]. The direction is folded into the event text
|
|
// on some records (e.g. "Predictive Failure Asserted").
|
|
if len(fields) < 5 {
|
|
continue
|
|
}
|
|
date, tm := fields[1], fields[2]
|
|
if !strings.Contains(date, "/") {
|
|
continue // Pre-Init Time-stamp and similar
|
|
}
|
|
ts, err := time.Parse(selTimeLayout, date+" "+tm)
|
|
if err != nil || bogusYear(ts) {
|
|
continue
|
|
}
|
|
sensor := fields[3]
|
|
event := fields[4]
|
|
direction := ""
|
|
if len(fields) >= 6 {
|
|
direction = fields[5]
|
|
}
|
|
|
|
severity := selSeverity(event, direction)
|
|
|
|
events = append(events, models.Event{
|
|
ID: "sel_" + strings.TrimSpace(fields[0]),
|
|
Timestamp: ts,
|
|
Source: "BMC/SEL",
|
|
SensorType: "sel",
|
|
SensorName: sensor,
|
|
EventType: direction,
|
|
Severity: severity,
|
|
Description: strings.TrimSpace(sensor + ": " + event),
|
|
RawData: line,
|
|
})
|
|
}
|
|
return events
|
|
}
|
|
|
|
func selSeverity(event, direction string) models.Severity {
|
|
if strings.EqualFold(strings.TrimSpace(direction), "Deasserted") {
|
|
return models.SeverityInfo
|
|
}
|
|
low := strings.ToLower(event)
|
|
for _, p := range criticalSELPhrases {
|
|
if strings.Contains(low, p) {
|
|
return models.SeverityCritical
|
|
}
|
|
}
|
|
for _, p := range warningSELPhrases {
|
|
if strings.Contains(low, p) {
|
|
return models.SeverityWarning
|
|
}
|
|
}
|
|
return models.SeverityInfo
|
|
}
|
|
|
|
func splitTrim(s, sep string) []string {
|
|
parts := strings.Split(s, sep)
|
|
for i := range parts {
|
|
parts[i] = strings.TrimSpace(parts[i])
|
|
}
|
|
return parts
|
|
}
|