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
@@ -678,6 +678,9 @@ func mergeCanonicalDevice(primary, secondary models.HardwareDevice) models.Hardw
fillString(&primary.LinkSpeed, secondary.LinkSpeed)
fillInt(&primary.MaxLinkWidth, secondary.MaxLinkWidth)
fillString(&primary.MaxLinkSpeed, secondary.MaxLinkSpeed)
if primary.NUMANode == nil && secondary.NUMANode != nil {
primary.NUMANode = secondary.NUMANode
}
fillInt(&primary.WattageW, secondary.WattageW)
fillString(&primary.InputType, secondary.InputType)
fillInt(&primary.InputPowerW, secondary.InputPowerW)
+29 -2
View File
@@ -9,6 +9,33 @@ import (
"git.mchus.pro/mchus/logpile/internal/models"
)
func intPtr(v int) *int { return &v }
func TestReanimatorExportPreservesNUMAZeroAndOmitsUnknown(t *testing.T) {
result := &models.AnalysisResult{Hardware: &models.HardwareConfig{
BoardInfo: models.BoardInfo{SerialNumber: "SN-NUMA"},
Devices: []models.HardwareDevice{
{ID: "gpu:0", Kind: models.DeviceKindGPU, Slot: "0000:01:00.0", DeviceClass: "VideoController", Model: "GPU 0", NUMANode: intPtr(0)},
{ID: "gpu:unknown", Kind: models.DeviceKindGPU, Slot: "0000:02:00.0", DeviceClass: "VideoController", Model: "GPU unknown"},
},
}}
out, err := ConvertToReanimator(result)
if err != nil {
t.Fatal(err)
}
body, err := json.Marshal(out)
if err != nil {
t.Fatal(err)
}
text := string(body)
if !strings.Contains(text, `"slot":"0000:01:00.0","numa_node":0`) {
t.Fatalf("NUMA zero was lost: %s", text)
}
if strings.Contains(text, `"slot":"0000:02:00.0","numa_node"`) {
t.Fatalf("unknown NUMA was serialized: %s", text)
}
}
func TestConvertToReanimator(t *testing.T) {
tests := []struct {
name string
@@ -1786,7 +1813,7 @@ func TestConvertToReanimator_ExportsContractV24Telemetry(t *testing.T) {
Slot: "PCIeCard2",
SerialNumber: "NIC-001",
DeviceClass: "EthernetController",
NUMANode: 1,
NUMANode: intPtr(1),
Details: map[string]any{
"temperature_c": 48.5,
"power_w": 18.2,
@@ -1828,7 +1855,7 @@ func TestConvertToReanimator_ExportsContractV24Telemetry(t *testing.T) {
if got := out.Hardware.Storage[0]; got.TemperatureC != 38.5 || got.PowerOnHours != 12450 || got.LifeRemainingPct != 91.0 {
t.Fatalf("unexpected storage telemetry: %#v", got)
}
if got := out.Hardware.PCIeDevices[0]; got.NUMANode != 1 || got.TemperatureC != 48.5 || got.PowerW != 18.2 || got.SFPTemperatureC != 36.2 {
if got := out.Hardware.PCIeDevices[0]; got.NUMANode == nil || *got.NUMANode != 1 || got.TemperatureC != 48.5 || got.PowerW != 18.2 || got.SFPTemperatureC != 36.2 {
t.Fatalf("unexpected PCIe telemetry: %#v", got)
}
if got := out.Hardware.PowerSupplies[0]; got.TemperatureC != 39 || got.LifeRemainingPct != 97.0 || got.LifeUsedPct != 3.0 {
+1 -1
View File
@@ -145,7 +145,7 @@ type ReanimatorPCIe struct {
Slot string `json:"slot"`
VendorID int `json:"vendor_id,omitempty"`
DeviceID int `json:"device_id,omitempty"`
NUMANode int `json:"numa_node,omitempty"`
NUMANode *int `json:"numa_node,omitempty"`
IOMMUGroup *int `json:"iommu_group,omitempty"`
TemperatureC float64 `json:"temperature_c,omitempty"`
PowerW float64 `json:"power_w,omitempty"`