feat: add standalone server topology view

This commit is contained in:
Mikhail Chusavitin
2026-09-14 10:29:36 +03:00
parent 5b8be0e464
commit 9ac38c2914
28 changed files with 1287 additions and 31 deletions
+35 -1
View File
@@ -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
View File
@@ -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