Improve Redfish raw replay recovery and GUI diagnostics

This commit is contained in:
Mikhail Chusavitin
2026-02-25 12:16:31 +03:00
parent 66fb90233f
commit a4a1a19a94
5 changed files with 231 additions and 39 deletions
+61 -9
View File
@@ -2,6 +2,8 @@ package collector
import (
"fmt"
"sort"
"strings"
"git.mchus.pro/mchus/logpile/internal/models"
)
@@ -64,12 +66,10 @@ func ReplayRedfishFromRawPayloads(rawPayloads map[string]any, emit ProgressFn) (
networkProtocolDoc, _ := r.getJSON(joinPath(primaryManager, "/NetworkProtocol"))
result := &models.AnalysisResult{
Events: make([]models.Event, 0),
FRU: make([]models.FRUInfo, 0),
Sensors: make([]models.SensorReading, 0),
RawPayloads: map[string]any{
"redfish_tree": tree,
},
Events: make([]models.Event, 0),
FRU: make([]models.FRUInfo, 0),
Sensors: make([]models.SensorReading, 0),
RawPayloads: cloneRawPayloads(rawPayloads),
Hardware: &models.HardwareConfig{
BoardInfo: parseBoardInfo(systemDoc),
CPUs: parseCPUs(processors),
@@ -115,11 +115,11 @@ func (r redfishSnapshotReader) getJSON(requestPath string) (map[string]interface
func (r redfishSnapshotReader) getCollectionMembers(collectionPath string) ([]map[string]interface{}, error) {
collection, err := r.getJSON(collectionPath)
if err != nil {
return nil, err
return r.fallbackCollectionMembers(collectionPath, err)
}
refs, ok := collection["Members"].([]interface{})
if !ok || len(refs) == 0 {
return []map[string]interface{}{}, nil
return r.fallbackCollectionMembers(collectionPath, nil)
}
out := make([]map[string]interface{}, 0, len(refs))
for _, refAny := range refs {
@@ -137,9 +137,61 @@ func (r redfishSnapshotReader) getCollectionMembers(collectionPath string) ([]ma
}
out = append(out, doc)
}
if len(out) == 0 {
return r.fallbackCollectionMembers(collectionPath, nil)
}
return out, nil
}
func (r redfishSnapshotReader) fallbackCollectionMembers(collectionPath string, originalErr error) ([]map[string]interface{}, error) {
prefix := strings.TrimSuffix(normalizeRedfishPath(collectionPath), "/") + "/"
if prefix == "/" {
if originalErr != nil {
return nil, originalErr
}
return []map[string]interface{}{}, nil
}
paths := make([]string, 0)
for key := range r.tree {
p := normalizeRedfishPath(key)
if !strings.HasPrefix(p, prefix) {
continue
}
rest := strings.TrimPrefix(p, prefix)
if rest == "" || strings.Contains(rest, "/") {
continue
}
paths = append(paths, p)
}
if len(paths) == 0 {
if originalErr != nil {
return nil, originalErr
}
return []map[string]interface{}{}, nil
}
sort.Strings(paths)
out := make([]map[string]interface{}, 0, len(paths))
for _, p := range paths {
doc, err := r.getJSON(p)
if err != nil {
continue
}
out = append(out, doc)
}
return out, nil
}
func cloneRawPayloads(src map[string]any) map[string]any {
if len(src) == 0 {
return nil
}
dst := make(map[string]any, len(src))
for k, v := range src {
dst[k] = v
}
return dst
}
func (r redfishSnapshotReader) discoverMemberPaths(collectionPath, fallbackPath string) []string {
collection, err := r.getJSON(collectionPath)
if err == nil {
@@ -482,7 +534,7 @@ func (r redfishSnapshotReader) collectPCIeDevices(systemPaths, chassisPaths []st
for _, doc := range memberDocs {
functionDocs := r.getLinkedPCIeFunctions(doc)
dev := parsePCIeDevice(doc, functionDocs)
key := firstNonEmpty(dev.SerialNumber, dev.BDF, dev.Slot+"|"+dev.DeviceClass)
key := firstNonEmpty(dev.BDF, dev.SerialNumber, dev.Slot+"|"+dev.DeviceClass)
if key == "" {
continue
}