feat(hardware): collect and export licenses via Dell iDRAC10 Redfish walk
Implements the hardware.licenses[] contract section (v2.12, refreshed from reanimator/core's hardware-ingest-contract.md — was v2.11 locally). - models.License / HardwareConfig.Licenses mirror the contract field set. - collector.collectLicenses() reads the standard DMTF /redfish/v1/LicenseService/Licenses collection during Redfish-walk replay; it's a generic DMTF resource, not Dell-specific, so any future vendor's Redfish walk gets license collection for free through ReplayRedfishFromRawPayloads. - vendors/dell merges replayed Licenses like every other category. - exporter.convertLicenses/dedupeLicenses wire hw.Licenses into the reanimator export directly (no canonical-devices merge — licenses have no physical identity to merge on), setting Present on every record from the start (per the ADL-049 round-trip lesson). - chart viewer renders a licenses section in /chart/current. Verified end-to-end on the PowerEdge R7715 (1TVFYL4) TSR: 3 system-level licenses extracted and correctly exported/rendered. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
eb6cc207ce
commit
eaaf5c09d3
@@ -1310,3 +1310,46 @@ given the field it needs from a re-imported export.
|
||||
`parseUploadedSnapshot` must actually be populated by its `convert*FromDevices` function — the struct
|
||||
declaring the field is not enough. `Storage` was the only category doing this correctly before this fix;
|
||||
worth auditing PCIe/NIC/GPU conversion the same way if a similar round-trip gap is reported for them.
|
||||
|
||||
---
|
||||
|
||||
## ADL-050 — 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
|
||||
v2.12 (2026-08-11) for software/firmware licenses and feature-on-demand activations (BMC advanced
|
||||
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
|
||||
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:**
|
||||
- `models.License` (`internal/models/models.go`) added, mirroring the contract's field set 1:1
|
||||
(`name`, `license_key`, `vendor`, `type`, `feature`, `component_ref`, `activated_at`, `expires_at`,
|
||||
`present`, status fields). `HardwareConfig.Licenses []License` added.
|
||||
- `internal/collector/redfish_replay_licenses.go`: `collectLicenses()` reads the standard DMTF
|
||||
`/redfish/v1/LicenseService/Licenses` collection (`License.v1_x` schema) via the existing
|
||||
`redfishSnapshotReader.getCollectionMembers` helper — no Dell-specific parsing needed, this is a
|
||||
generic DMTF resource, so any future vendor whose Redfish walk includes it gets license collection
|
||||
for free through `ReplayRedfishFromRawPayloads`. `AuthorizationScope: "Device"` licenses get
|
||||
`component_ref` from `Links.AuthorizedDevices[0]`; `Service`-scoped licenses stay system-level (no
|
||||
`component_ref`). `LicenseOrigin != "Installed"` maps to `Present: false`.
|
||||
- `internal/parser/vendors/dell/redfish_walk.go`'s `mergeRedfishReplay` appends replayed `Licenses`
|
||||
into `result.Hardware.Licenses` like every other category.
|
||||
- `internal/exporter/reanimator_converter.go`: `convertLicenses` + `dedupeLicenses` (dedup key:
|
||||
`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
|
||||
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.
|
||||
**Consequences:**
|
||||
- Verified end-to-end on the PowerEdge R7715 (1TVFYL4) TSR archive: 3 licenses extracted from
|
||||
`redfishidracwalk.tar.gz` ("Secure Enterprise Key Manager", "Secured Component Verification",
|
||||
"iDRAC10 17G Enterprise License"), all system-level (`AuthorizationScope: "Service"`), correctly
|
||||
exported with `present: true` and visible in the live `/chart/current` page.
|
||||
- No other vendor parser populates `Hardware.Licenses` yet. If a future TSR/log source carries license
|
||||
data outside a Redfish walk (e.g. embedded in a vendor-specific XML/JSON file), it needs its own
|
||||
parsing — `collectLicenses()` only covers the generic Redfish `LicenseService` path.
|
||||
|
||||
Reference in New Issue
Block a user