Improve Redfish raw replay recovery and GUI diagnostics
This commit is contained in:
@@ -23,8 +23,8 @@ import (
|
||||
)
|
||||
|
||||
type RedfishConnector struct {
|
||||
timeout time.Duration
|
||||
debug bool
|
||||
timeout time.Duration
|
||||
debug bool
|
||||
debugSnapshot bool
|
||||
}
|
||||
|
||||
@@ -88,15 +88,19 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
emit(Progress{Status: "running", Progress: 90, Message: "Redfish: сбор расширенного snapshot..."})
|
||||
}
|
||||
c.debugSnapshotf("snapshot crawl start host=%s port=%d", req.Host, req.Port)
|
||||
rawTree := c.collectRawRedfishTree(ctx, client, req, baseURL, redfishSnapshotPrioritySeeds(systemPaths, chassisPaths, managerPaths), emit)
|
||||
rawTree, fetchErrors := c.collectRawRedfishTree(ctx, client, req, baseURL, redfishSnapshotPrioritySeeds(systemPaths, chassisPaths, managerPaths), emit)
|
||||
c.debugSnapshotf("snapshot crawl done docs=%d", len(rawTree))
|
||||
if emit != nil {
|
||||
emit(Progress{Status: "running", Progress: 99, Message: "Redfish: анализ raw snapshot..."})
|
||||
}
|
||||
// Unified tunnel: live collection and raw import go through the same analyzer over redfish_tree.
|
||||
return ReplayRedfishFromRawPayloads(map[string]any{
|
||||
rawPayloads := map[string]any{
|
||||
"redfish_tree": rawTree,
|
||||
}, nil)
|
||||
}
|
||||
if len(fetchErrors) > 0 {
|
||||
rawPayloads["redfish_fetch_errors"] = fetchErrors
|
||||
}
|
||||
// Unified tunnel: live collection and raw import go through the same analyzer over redfish_tree.
|
||||
return ReplayRedfishFromRawPayloads(rawPayloads, nil)
|
||||
}
|
||||
|
||||
func (c *RedfishConnector) httpClient(req Request) *http.Client {
|
||||
@@ -444,7 +448,7 @@ func (c *RedfishConnector) collectPCIeDevices(ctx context.Context, client *http.
|
||||
for _, doc := range memberDocs {
|
||||
functionDocs := c.getLinkedPCIeFunctions(ctx, client, req, baseURL, 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
|
||||
}
|
||||
@@ -506,12 +510,13 @@ func (c *RedfishConnector) discoverMemberPaths(ctx context.Context, client *http
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *http.Client, req Request, baseURL string, seedPaths []string, emit ProgressFn) map[string]interface{} {
|
||||
func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *http.Client, req Request, baseURL string, seedPaths []string, emit ProgressFn) (map[string]interface{}, []map[string]interface{}) {
|
||||
maxDocuments := redfishSnapshotMaxDocuments()
|
||||
const workers = 6
|
||||
const heartbeatInterval = 5 * time.Second
|
||||
|
||||
out := make(map[string]interface{}, maxDocuments)
|
||||
fetchErrors := make(map[string]string)
|
||||
seen := make(map[string]struct{}, maxDocuments)
|
||||
rootCounts := make(map[string]int)
|
||||
var mu sync.Mutex
|
||||
@@ -602,15 +607,20 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
enqueue(ref)
|
||||
}
|
||||
}
|
||||
n := atomic.AddInt32(&processed, 1)
|
||||
if err != nil {
|
||||
c.debugSnapshotf("worker=%d fetch error path=%s err=%v", workerID, current, err)
|
||||
if emit != nil && shouldReportSnapshotFetchError(err) {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 92 + int(minInt32(n/200, 6)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: ошибка на %s", compactProgressPath(current)),
|
||||
})
|
||||
n := atomic.AddInt32(&processed, 1)
|
||||
if err != nil {
|
||||
mu.Lock()
|
||||
if _, ok := fetchErrors[current]; !ok {
|
||||
fetchErrors[current] = err.Error()
|
||||
}
|
||||
mu.Unlock()
|
||||
c.debugSnapshotf("worker=%d fetch error path=%s err=%v", workerID, current, err)
|
||||
if emit != nil && shouldReportSnapshotFetchError(err) {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 92 + int(minInt32(n/200, 6)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: ошибка на %s", compactProgressPath(current)),
|
||||
})
|
||||
}
|
||||
}
|
||||
if emit != nil && n%40 == 0 {
|
||||
@@ -677,7 +687,18 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
})
|
||||
}
|
||||
|
||||
return out
|
||||
errorList := make([]map[string]interface{}, 0, len(fetchErrors))
|
||||
for p, msg := range fetchErrors {
|
||||
errorList = append(errorList, map[string]interface{}{
|
||||
"path": p,
|
||||
"error": msg,
|
||||
})
|
||||
}
|
||||
sort.Slice(errorList, func(i, j int) bool {
|
||||
return asString(errorList[i]["path"]) < asString(errorList[j]["path"])
|
||||
})
|
||||
|
||||
return out, errorList
|
||||
}
|
||||
|
||||
func (c *RedfishConnector) probeSupermicroNVMeDiskBays(ctx context.Context, client *http.Client, req Request, baseURL, backplanePath string) []map[string]interface{} {
|
||||
|
||||
Reference in New Issue
Block a user