feat(exporter): collect and export storage.vendor_id/device_id (contract v2.13)

Add PCI Vendor ID / Device ID to hardware.storage[] per the updated Reanimator
ingest contract, mirroring the existing pcie_devices[] fields. Populated for
Redfish-collected NVMe drives (live + TSR replay, via linked PCIeFunctions)
and for Inspur (from asset.json's own PcieInfo[], joined by PcieSlot). Also
fixes canonicalDevicesForExport dropping the fields when converting Storage
into the canonical HardwareDevice list used by the actual export path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-08-11 16:04:54 +03:00
co-authored by Claude Sonnet 5
parent 063587958e
commit 399eca5f49
11 changed files with 221 additions and 4 deletions
+19
View File
@@ -162,6 +162,23 @@ func ParseAssetJSON(content []byte, pcieSlotDeviceNames map[int]string, pcieSlot
}
}
// Build a PcieSlot -> (VendorId, DeviceId) map from asset.json's own PcieInfo section,
// used below to enrich NVMe HddInfo entries (BMC does not populate vendor/device IDs
// directly on HddInfo).
pcieSlotVendorID := make(map[int]int, len(asset.PcieInfo))
pcieSlotDeviceID := make(map[int]int, len(asset.PcieInfo))
for _, pcie := range asset.PcieInfo {
if pcie.PcieSlot <= 0 {
continue
}
if pcie.VendorId > 0 {
pcieSlotVendorID[pcie.PcieSlot] = pcie.VendorId
}
if pcie.DeviceId > 0 {
pcieSlotDeviceID[pcie.PcieSlot] = pcie.DeviceId
}
}
// Parse storage info
for _, hdd := range asset.HddInfo {
slot := normalizeAssetHDDSlot(hdd.LocationString, hdd.Location, hdd.DiskInterfaceType)
@@ -207,6 +224,8 @@ func ParseAssetJSON(content []byte, pcieSlotDeviceNames map[int]string, pcieSlot
Slot: slot,
Type: storageType,
Model: modelName,
VendorID: pcieSlotVendorID[hdd.PcieSlot],
DeviceID: pcieSlotDeviceID[hdd.PcieSlot],
SizeGB: hdd.Capacity,
SerialNumber: serial,
Manufacturer: manufacturer,