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
+7
View File
@@ -26,10 +26,17 @@ internal/analyzer/ shared analysis helpers
internal/parser/ archive extraction and parser dispatch
internal/exporter/ CSV and Reanimator conversion
internal/chart/ vendored `reanimator/chart` viewer submodule
internal/topology/ standalone topology.json builder and static SVG renderer
internal/models/ stable data contracts
web/ embedded UI assets
```
The topology view is owned by LOGPile, not by the chart submodule. The main UI
opens `GET /topology/current` in a separate browser tab. The renderer consumes a
standalone `topology.json` document built from the normalized Reanimator
projection plus optional static evidence imported from Bee support bundles. It
does not poll telemetry or execute host commands.
## Server state
`internal/server.Server` stores:
+12
View File
@@ -201,6 +201,17 @@ The server first converts the current result to Reanimator JSON, then passes tha
Serves embedded `reanimator/chart` static assets.
### `GET /topology/current`
Renders the current server topology as a standalone static HTML/SVG page in a
separate browser tab. Rich Bee bundles add DIMM, storage-controller, and NVLink
edges from persisted diagnostic files. No live commands or polling are used.
### `GET /api/topology`
Returns the versioned semantic `topology.json` document. It contains nodes and
relationships, not SVG coordinates.
## Export endpoints
### `GET /api/export/csv`
@@ -215,6 +226,7 @@ Current implementation emits a ZIP bundle containing:
- `collect.log`
- `parser_fields.json`
- `privacy_report.json` (only when the customer-data scan produced findings)
- `topology.json` (when topology nodes are available)
### `GET /api/export/reanimator`
+11
View File
@@ -58,6 +58,17 @@ Required rules:
3. UI/export mismatches are bugs, not accepted divergence
4. New shared device fields belong in `HardwareDevice` first
### NUMA affinity
NUMA affinity is nullable throughout the internal and Reanimator export path.
In Go it is represented as `*int`: `nil` means not reported / not applicable,
while a pointer to `0` means the real NUMA node 0. Numeric zero must never be
used as an absence sentinel.
Topology relationships outside the Reanimator ingest contract live in the
separate versioned `topology.json` document and are not added to
`reanimator.json`.
Deduplication priority:
| Priority | Key |
+1 -1
View File
@@ -59,7 +59,7 @@ serial from its socket, model, board serial, or another component; reject source
| Vendor ID | Input family | Notes |
|-----------|--------------|-------|
| `dell` | TSR ZIP archives | Broad hardware, firmware, sensors, lifecycle events |
| `easy_bee` | `bee-support-*.tar.gz` | Imports embedded `export/bee-audit.json` snapshot from reanimator-easy-bee bundles |
| `easy_bee` | `bee-support-*.tar.gz` | Imports the embedded hardware snapshot and static DIMM/storage/NVIDIA evidence used to build `topology.json` |
| `h3c_g5` | H3C SDS G5 bundles | INI/XML/CSV-driven hardware and event parsing |
| `h3c_g6` | H3C SDS G6 bundles | Similar flow with G6-specific files |
| `hpe_ilo_ahs` | HPE iLO Active Health System (`.ahs`) | Proprietary `ABJR` container with gzip-compressed `zbb` members; parser combines SMBIOS-style inventory strings and embedded Redfish storage JSON |
+37
View File
@@ -572,6 +572,8 @@ both CPUs or have no CPU affinity). This data is needed for topology-aware diagn
provide CPUAffinity at all.
- `TestParseDellCPUAffinity` verifies numeric values parsed correctly and "Not Applicable"→0.
The zero-as-absence representation in this decision is superseded by ADL-068.
---
## ADL-023 — Reanimator export must match ingest contract exactly
@@ -1983,3 +1985,38 @@ with **same-length neutral fillers**, in place.
`TestSanitize_Zip_*`, `TestSanitize_BinaryMemberFlagged`,
`TestNeutralZonesAreValidAndSameLength`, `TestTZFiller`),
`internal/server` (`TestHandleSanitize_*`).
---
## ADL-068 — Standalone topology document and nullable NUMA affinity
**Date:** 2026-09-14
**Context:** A server topology cannot distinguish the real NUMA node 0 from an
unknown affinity while the Go model uses numeric zero as its absence sentinel.
Bee support bundles also contain useful relationships (DIMM-to-socket,
disk-to-controller, and GPU/NVLink links) which are not part of the Reanimator
hardware ingest schema. Adding those relationships to `reanimator.json` would
couple a standard inventory document to one viewer.
**Decision:**
- Represent `numa_node` as `*int` throughout LOGPile's PCIe, network, canonical
device, and Reanimator projection models. `nil` means absent/N/A; `&0` means
NUMA node 0.
- Keep `reanimator.json` schema-preserving. Store semantic topology as a
separate, versioned `topology.json` document containing nodes and edges, but
no presentation coordinates.
- Render `/topology/current` as a LOGPile-owned, static SVG page opened in a
separate browser tab. Do not modify the `internal/chart` submodule.
- The Easy Bee parser may retain the small static evidence files required to
enrich topology. Rendering must never execute commands, poll metrics, or
depend on live state.
**Consequences:**
- JSON can round-trip both an absent NUMA affinity and the real value 0.
- Ordinary inputs get the topology supported by their normalized inventory;
rich Bee bundles additionally get memory, storage-controller, and NVLink
relationships.
- Raw-export ZIP bundles include `topology.json` separately from
`reanimator.json`.
- Fan RPM animation, PSU live load, and other Bee live-only presentation are
intentionally out of scope.
@@ -477,6 +477,9 @@ GET /ingest/hardware/jobs/{job_id}
| + общие поля статуса | | | см. раздел выше |
`numa_node` передавайте для NIC / InfiniBand / RAID / GPU, когда источник знает CPU/NUMA affinity. Поле сохраняется в snapshot-атрибутах PCIe-компонента и дублируется в telemetry для topology use cases.
`numa_node: 0` is a valid affinity value. Unknown or not-applicable affinity is
represented by an absent field, never by numeric zero.
Поля `temperature_c` и `power_w` используйте для device-level telemetry GPU / accelerator / smart PCIe devices. Они не влияют на идентификацию компонента.
`vendor_id`/`device_id` используются в первую очередь при разрешении канонического вендора/модели устройства (см. аналогичное примечание в разделе `storage`).