Merge remote-tracking branch 'origin/main'

# Conflicts:
#	bible-local/10-decisions.md
#	internal/chart
#	internal/models/models.go
This commit is contained in:
Mikhail Chusavitin
2026-08-11 12:12:03 +03:00
17 changed files with 1709 additions and 2044 deletions
+98 -6
View File
@@ -1232,7 +1232,99 @@ later content-free duplicate cannot blank out an earlier real reading.
---
## ADL-048 — Dell iDRAC10 TSR bundles ship inventory as a raw Redfish walk, not DCIM-XML
## ADL-048 — Inspur HGX `dump_<serial>_<timestamp>/` layout: ipmitool-output FRU/sensors, diagnose-json PCIe, commer-comp events
**Date:** 2026-07-29
**Context:** A field dump from an HGX B200 / KR9288-X3 (`dump_23DB01633_20260727-1359.tar.gz`)
uses yet another onekeylog variant that has no `devicefrusdr.log` at all (unlike ADL-047's
per-file D-Bus layout, which is missing only `component.log`). FRU and sensors come from raw
`ipmitool fru print` / `ipmitool sensor list` / `ipmitool sdr elist` output under
`component/{fru,sensor,sdr}.txt`. Without a fallback the parser returned `fru: 0, sensors: 0` on
an otherwise well-detected archive (`Detect()` still scored via `onekeylog_dreport.log`), silently
dropping inventory a diagnostic case (intermittent GPU PCIe dropout) depended on.
**Decision:**
- `component/fru.txt` uses the exact same `FRU Device Description :` block format as the FRU
section of `devicefrusdr.log`, so it's parsed with the existing `ParseFRU` unchanged.
- `component/sensor.txt` (`ipmitool sensor list`, has value+unit+status per line) is the primary
sensor fallback; `component/sdr.txt` (`ipmitool sdr elist`, no value on disabled sensors) is used
only if `sensor.txt` is absent. New parsers in `component_fallback.go`
(`ParseSensorList`, `ParseSDRElist`).
- `log/bmc/diagnose/OtrdDiagnoseComponent.json`'s `"Pcie Device Info"` array is a structural,
point-in-time PCIe snapshot (independent of SEL/IDL alarm history) — parsed by
`ParseOtrdDiagnosePCIe` in `diagnose.go` into `models.PCIeDevice` (using the existing
`Present *bool` field) and merged via the existing `MergePCIeDevices`. A device present but
running below its negotiated max link speed/width gets `Status = "Link Degraded"` and a
matching Warning event (`BuildPCIeLinkDegradationEvents`), independent of GPU-fault SEL/IDL
parsing in `gpu_status.go`.
- `log/sel.csv` is textually identical to `selelist.csv` (`ipmitool sel elist -c -Z` output with
the same 6-column CSV body) and is now a fallback source when `selelist.csv` is absent, reusing
`ParseSELListWithLocation` unchanged.
- `log/bmc/commer-comp/<commerslot|commerhmc|commerswvr|commerswcpld>/` component logs (plus
rotated `*.tar.gz.N` parts, decoded in-memory) share one line format
(`[timestamp][file, line][level] message`); `ParseCommerCompEvents` in `commercomp.go` emits an
event per line that looks like a real failure, after dropping a fixed noise list (`Invalid Comp
Data`, `Error in update redis`, `MutexTimeout = 0`).
- Fixed two long-standing `ParseFRU` bugs surfaced by this archive: `Board Serial`/`Board Part
Number` values were overwritten by a later, placeholder `Product Serial : 0` / `Product Part
Number : NULL` line within the same FRU block (e.g. `SCM_FRU`, which has no product-level FRU
fields). Placeholder values (`"0"`, `"NULL"`) no longer overwrite an already-set real value.
- Since duplicate SEL entries can now surface through more than one source file (`sel.csv` +
IDL/BMC logs) for the same moment, `Parse()` runs a final `dedupSELEvents` pass collapsing
`Source == "SEL"` events with identical `(timestamp, event_type, description)`. This is
deliberately narrower than IDL's own timestamp-inclusive dedup in `idl.go`, which must keep
distinct occurrences of a recurring alarm.
- When `Parse()` still ends up with `len(FRU) == 0 || len(Sensors) == 0` after all fallbacks, it
appends a `CollectionError{Section: "inventory"}` so the gap is visible in the API response
instead of silently returning an empty inventory.
**Consequences:**
- `stats.fru`/`stats.sensors` are non-zero on this dump class; GPU presence/link state is
available from a source independent of SEL/IDL alarm parsing.
- BIOS-change-settings context (`biosChangedSettings/Bios_change_settings*.json`) and BIOS POST
codes (`log/server/progress_log/host0/*`) from the same issue are not yet parsed — deferred,
no acceptance case depended on them yet.
- Any future ipmitool-text-output fallback (FRU/sensor/sdr) should extend
`component_fallback.go` rather than adding another one-off parser.
---
## ADL-049 — HGX tray/baseboard identity is a distinct entity from the vendor mechanical-carrier FRU
**Date:** 2026-07-29
**Context:** Issue #21 (Inspur/Kaytus HGX B200 dumps). `hw.BoardInfo`/vendor FRU (`component/fru.txt`
`Board Product : CA`, a `YZCA-*` part) identifies the mechanical carrier/tray shipped by Inspur —
it's bolted to the chassis and does not change when the actual NVIDIA HGX baseboard ("delta
board", SXM+NVSwitch) is swapped. Three dumps from the same server showed the CA carrier serial
constant across all three while the NVIDIA-assigned tray (`699-26612-*`) and baseboard
(`935-26287-*`) serials — read from `log/bmc/oem-commer-log/HGX_HWInfo_FWVersion.log` — stayed
identical between dumps A/B (~4 weeks apart) and both changed together in dump C, i.e. only
`HGX_HWInfo_FWVersion.log` actually reflects a baseboard swap.
**Decision:**
- Added `models.HGXIdentity` (`Tray`, `Baseboard`, each a `Model`/`PartNumber`/`SerialNumber`
triple) as `HardwareConfig.HGX`, populated by `parseHGXIdentity` in
`internal/parser/vendors/inspur/hgx_hwinfo.go` from the same `HGX_HWInfo_FWVersion.log` file
already used for GPU assembly/firmware enrichment.
- The log is a sequence of `# curl ... <redfish-path>` comment lines each followed by that
request's JSON response; `splitCurlBlocks` chunks on the comment lines so fields are attributed
to the path that produced them (classified by `tray`/`baseboard` substring, order-independent
field regexes — unlike the existing fixed-order `reHGXGPUBlock` regex for GPU assembly). Paths
containing `gpu_sxm` or `/processors/` are explicitly excluded so a per-GPU triple can never be
misattributed to the tray/baseboard entity.
- `hgxValue()` normalizes Redfish's `NA`/`N/A` placeholder (seen when GPUs are unpowered but the
baseboard itself still responds) to empty string, applied to both the new identity parser and
the existing per-GPU assembly parser, so `"NA"` never leaks into a serial/model/part field.
- Deliberately left `hw.BoardInfo`/vendor FRU parsing (`fru.go`) unchanged — it is not wrong, just
a different entity (mechanical carrier). Consumers that need "did the actual GPU board change"
must compare `HardwareConfig.HGX`, not `BoardInfo`.
**Consequences:**
- Dump-to-dump baseboard/tray swap detection (issue #21's P2) is now possible by comparing two
`HardwareConfig.HGX` values; not yet wired into any diff/comparison UI.
- GPU-status "baseboard responds, GPU not readable" surfacing (P1) is a natural follow-on now that
GPU fields normalize through the same `NA`-aware path, but no dedicated event/diagnostic was
added yet — deferred, no acceptance case depended on it.
---
## ADL-050 — Dell iDRAC10 TSR bundles ship inventory as a raw Redfish walk, not DCIM-XML
**Date:** 2026-08-11
**Context:** A TSR from a PowerEdge R7715 (`TSR20260721231613_1TVFYL4.zip`, iDRAC10-generation
@@ -1273,10 +1365,10 @@ of raw Redfish walk is picked up automatically without a dedicated parser.
---
## ADL-049 — Reanimator export/re-import round trip silently dropped Memory and PSUs
## ADL-051 — Reanimator export/re-import round trip silently dropped Memory and PSUs
**Date:** 2026-08-11
**Context:** After ADL-048 fixed Dell iDRAC10 inventory parsing, the same PowerEdge R7715 archive
**Context:** After ADL-050 fixed Dell iDRAC10 inventory parsing, the same PowerEdge R7715 archive
still showed no Memory or Power Supplies sections in the `/chart/current` web view, even though
`internal/exporter.ConvertToReanimator` produced both correctly from a fresh TSR upload (verified via
direct API calls against the running server). The web view *did* break identically after re-uploading
@@ -1313,7 +1405,7 @@ given the field it needs from a re-imported export.
---
## ADL-050 — Added `hardware.licenses[]` collection/export (contract v2.12), Dell iDRAC10 first
## ADL-052 — Added `hardware.licenses[]` collection/export (contract v2.12), Dell iDRAC10 first
**Date:** 2026-08-11
**Context:** Reanimator's hardware ingest contract added an optional `hardware.licenses[]` section in
@@ -1321,7 +1413,7 @@ v2.12 (2026-08-11) for software/firmware licenses and feature-on-demand activati
licenses, vGPU, CPU FoD, RAID feature unlocks, etc). LOGPile's local copy of
`bible-local/docs/hardware-ingest-contract.md` was still v2.11 and was refreshed from
`reanimator/core/bible-local/docs/hardware-ingest-contract.md`. Scoped the first implementation to the
Dell iDRAC10 Redfish-walk path (`vendors/dell` + `vendors/redfishwalk`, see ADL-048/049), since that's
Dell iDRAC10 Redfish-walk path (`vendors/dell` + `vendors/redfishwalk`, see ADL-050/051), since that's
the only resolver currently producing a full captured Redfish tree with a `LicenseService` collection
in it — other vendor parsers have no comparable source for this data yet.
**Decision:**
@@ -1341,7 +1433,7 @@ in it — other vendor parsers have no comparable source for this data yet.
`license_key`, falling back to `component_ref|name`) added, wired into `ConvertToReanimator`
directly from `hw.Licenses` — licenses don't go through the canonical-devices merge/dedup pipeline
used for PCIe/GPU/NIC, since they carry no physical identity to merge on. `ReanimatorLicense.Present`
is set on every emitted record (learned from ADL-049 — declaring the field isn't enough, it must
is set on every emitted record (learned from ADL-051 — declaring the field isn't enough, it must
actually be populated for the reanimator round-trip to survive).
- `internal/chart/viewer/render.go`: added a `licenses` section (between `power_supplies` and
`sensors`) so licenses show up in the `/chart/current` web view like every other hardware category.