fix: dedup GPUs across multiple chassis PCIeDevice trees in Redfish collector
Supermicro HGX exposes each GPU under both Chassis/1/PCIeDevices and a dedicated Chassis/HGX_GPU_SXM_N/PCIeDevices. gpuDocDedupKey was keying by @odata.id path, so identical GPUs with the same serial were not deduplicated across sources. Now stable identifiers (serial → BDF → slot+model) take priority over path. Also includes Inspur parser improvements: NVMe model/serial enrichment from devicefrusdr.log and audit.log, RAID drive slot normalization to BP notation, PSU slot normalization, BMC/CPLD/VR firmware from RESTful version info section, and parser version bump to 1.8. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
57
internal/parser/vendors/inspur/component.go
vendored
57
internal/parser/vendors/inspur/component.go
vendored
@@ -713,6 +713,63 @@ func extractComponentFirmware(text string, hw *models.HardwareConfig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract BMC, CPLD and VR firmware from RESTful version info section.
|
||||
// The JSON is a flat array: [{"id":N,"dev_name":"...","dev_version":"..."}, ...]
|
||||
reVer := regexp.MustCompile(`RESTful version info:\s*(\[[\s\S]*?\])\s*RESTful`)
|
||||
if match := reVer.FindStringSubmatch(text); match != nil {
|
||||
type verEntry struct {
|
||||
DevName string `json:"dev_name"`
|
||||
DevVersion string `json:"dev_version"`
|
||||
}
|
||||
var entries []verEntry
|
||||
if err := json.Unmarshal([]byte(match[1]), &entries); err == nil {
|
||||
for _, e := range entries {
|
||||
name := normalizeVersionInfoName(e.DevName)
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
version := strings.TrimSpace(e.DevVersion)
|
||||
if version == "" {
|
||||
continue
|
||||
}
|
||||
if existingFW[name] {
|
||||
continue
|
||||
}
|
||||
hw.Firmware = append(hw.Firmware, models.FirmwareInfo{
|
||||
DeviceName: name,
|
||||
Version: version,
|
||||
})
|
||||
existingFW[name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeVersionInfoName converts RESTful version info dev_name to a clean label.
|
||||
// Returns "" for entries that should be skipped (inactive BMC, PSU slots).
|
||||
func normalizeVersionInfoName(name string) string {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return ""
|
||||
}
|
||||
// Skip PSU_N entries — firmware already extracted from PSU info section.
|
||||
if regexp.MustCompile(`(?i)^PSU_\d+$`).MatchString(name) {
|
||||
return ""
|
||||
}
|
||||
// Skip the inactive BMC partition.
|
||||
if strings.HasPrefix(strings.ToLower(name), "inactivate(") {
|
||||
return ""
|
||||
}
|
||||
// Active BMC: "Activate(BMC1)" → "BMC"
|
||||
if strings.HasPrefix(strings.ToLower(name), "activate(") {
|
||||
return "BMC"
|
||||
}
|
||||
// Strip trailing "Version" suffix (case-insensitive), e.g. "MainBoard0CPLDVersion" → "MainBoard0CPLD"
|
||||
if strings.HasSuffix(strings.ToLower(name), "version") {
|
||||
name = name[:len(name)-len("version")]
|
||||
}
|
||||
return strings.TrimSpace(name)
|
||||
}
|
||||
|
||||
// DiskBackplaneRESTInfo represents the RESTful diskbackplane info structure
|
||||
|
||||
Reference in New Issue
Block a user