feat: add standalone server topology view
This commit is contained in:
+35
-1
@@ -11,7 +11,7 @@ import (
|
||||
"git.mchus.pro/mchus/logpile/internal/parser"
|
||||
)
|
||||
|
||||
const parserVersion = "1.0"
|
||||
const parserVersion = "1.1"
|
||||
|
||||
func init() {
|
||||
parser.Register(&Parser{})
|
||||
@@ -126,6 +126,7 @@ func (p *Parser) Parse(files []parser.ExtractedFile) (*models.AnalysisResult, er
|
||||
PowerSupply: normalizePSUSlots(snapshot.Hardware.PowerSupply),
|
||||
},
|
||||
}
|
||||
result.TopologyEvidence = collectTopologyEvidence(files)
|
||||
|
||||
if pn := chassisProductPartNumber(files, result.Hardware.BoardInfo.ProductName); pn != "" {
|
||||
result.Hardware.BoardInfo.PartNumber = pn
|
||||
@@ -156,6 +157,39 @@ func (p *Parser) Parse(files []parser.ExtractedFile) (*models.AnalysisResult, er
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func collectTopologyEvidence(files []parser.ExtractedFile) *models.TopologyEvidence {
|
||||
read := func(names ...string) string {
|
||||
for _, name := range names {
|
||||
for _, f := range files {
|
||||
if strings.EqualFold(pathBase(f.Path), name) {
|
||||
return string(f.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
e := &models.TopologyEvidence{
|
||||
DIMMType17: read("dmidecode-type17.txt"),
|
||||
StorageMap: read("storage-controllers.txt"),
|
||||
NVIDIAQueryCSV: read("nvidia-smi-query-fresh.csv", "nvidia-smi-query.csv"),
|
||||
NVIDIATopology: read("nvidia-smi-topo-fresh.txt", "nvidia-smi-topo.txt"),
|
||||
NVLinkStatus: read("nvidia-smi-nvlink-status-fresh.txt", "nvidia-smi-nvlink-status.txt"),
|
||||
NVLinkErrors: read("nvidia-smi-nvlink-errors-fresh.txt", "nvidia-smi-nvlink-errors.txt"),
|
||||
}
|
||||
if e.DIMMType17 == "" && e.StorageMap == "" && e.NVIDIAQueryCSV == "" && e.NVIDIATopology == "" && e.NVLinkStatus == "" && e.NVLinkErrors == "" {
|
||||
return nil
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func pathBase(path string) string {
|
||||
path = strings.ReplaceAll(strings.TrimSpace(path), `\`, "/")
|
||||
if i := strings.LastIndexByte(path, '/'); i >= 0 {
|
||||
return path[i+1:]
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
type beeSnapshot struct {
|
||||
SourceType string `json:"source_type,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
|
||||
+17
@@ -30,6 +30,23 @@ func TestDetectBeeSupportArchive(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectTopologyEvidenceSupportsCategorizedBundleAndPrefersFresh(t *testing.T) {
|
||||
files := []parser.ExtractedFile{
|
||||
{Path: "bundle/export/memory/dmidecode-type17.txt", Content: []byte("memory")},
|
||||
{Path: "bundle/export/storage/storage-controllers.txt", Content: []byte("storage")},
|
||||
{Path: "bundle/export/gpu/nvidia-smi-query.csv", Content: []byte("query")},
|
||||
{Path: "bundle/export/gpu/nvidia-smi-topo.txt", Content: []byte("old")},
|
||||
{Path: "bundle/export/gpu/nvidia-smi-topo-fresh.txt", Content: []byte("fresh")},
|
||||
}
|
||||
got := collectTopologyEvidence(files)
|
||||
if got == nil {
|
||||
t.Fatal("expected topology evidence")
|
||||
}
|
||||
if got.DIMMType17 != "memory" || got.StorageMap != "storage" || got.NVIDIAQueryCSV != "query" || got.NVIDIATopology != "fresh" {
|
||||
t.Fatalf("unexpected topology evidence: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestDetectBeeSupportArchiveV12Layout covers the real bundle layout produced
|
||||
// by bee-support v12.x, where bee-audit.json lives under tasks/_state/ and
|
||||
// runtime-health.json under status/, not export/. See CLAUDE.md memory on
|
||||
|
||||
Reference in New Issue
Block a user