Files
logpile/docs/bible/07-exporters.md
2026-02-25 12:17:17 +03:00

11 KiB

07 — Exporters & Reanimator Integration

Export endpoints summary

Endpoint Format Filename pattern
GET /api/export/csv CSV — serial numbers YYYY-MM-DD (MODEL) - SN.csv
GET /api/export/json Raw export package (JSON or ZIP bundle) for reopen/re-analysis `YYYY-MM-DD (MODEL) - SN.(json
GET /api/export/reanimator Reanimator hardware JSON YYYY-MM-DD (MODEL) - SN.json

Raw Export (Export Raw Data)

Purpose

Preserve enough source data to reproduce parsing later after parser fixes, without requiring another live collection from the target system.

Format

/api/export/json returns a raw export package:

  • JSON package (machine-readable), or
  • ZIP bundle containing:
    • raw_export.json — machine-readable package
    • collect.log — human-readable collection + parsing summary
    • parser_fields.json — structured parsed field snapshot for diffs between parser versions

Import / reopen behavior

When a raw export package is uploaded back into LOGPile:

  • the app re-analyzes from raw source
  • it does not trust embedded parsed output as source of truth

For Redfish, this means replay from raw_payloads.redfish_tree.

Design rule

Raw export is a re-analysis artifact, not a final report dump. Keep it self-contained and forward-compatible where possible (versioned package format, additive fields only).


Reanimator Export

Purpose

Exports hardware inventory data in the format expected by the Reanimator asset tracking system. Enables one-click push from LOGPile to an external asset management platform.

Implementation files

File Role
internal/exporter/reanimator_models.go Go structs for Reanimator JSON
internal/exporter/reanimator_converter.go ConvertToReanimator() and helpers
internal/server/handlers.go handleExportReanimator() HTTP handler

Conversion rules

  • Source: canonical hardware.devices repository (see 04-data-models.md)
  • CPU manufacturer inferred from model string (Intel / AMD / ARM / Ampere)
  • PCIe serial number generated when absent: {board_serial}-PCIE-{slot}
  • Status values normalized to: OK, Warning, Critical, Unknown (Empty only for memory slots)
  • Timestamps in RFC3339 format
  • target_host derived from filename field (redfish://…, ipmi://…) if not in source; omitted if undeterminable
  • board.manufacturer and board.product_name values of "NULL" treated as absent

LOGPile → Reanimator field mapping

LOGPile type Reanimator section Notes
BoardInfo board Direct mapping
CPU cpus + manufacturer (inferred)
MemoryDIMM memory Direct; empty slots included (present=false)
Storage storage Excluded if no serial_number
PCIeDevice pcie_devices Serial generated if missing
GPU pcie_devices device_class=DisplayController
NetworkAdapter pcie_devices device_class=NetworkController
PSU power_supplies Excluded if no serial or present=false
FirmwareInfo firmware Direct mapping

Inclusion / exclusion rules

Included:

  • Memory slots with present=false (as Empty slots)
  • PCIe devices without serial number (serial is generated)

Excluded:

  • Storage without serial_number
  • PSU without serial_number or with present=false
  • NetworkAdapters with present=false

Reanimator Integration Guide

This section documents the Reanimator receiver-side JSON format (what the Reanimator system expects when it ingests a LOGPile export).

Important: The Reanimator endpoint uses a strict JSON decoder (DisallowUnknownFields). Any unknown field — including nested ones — causes 400 Bad Request. Use only snake_case keys listed here.

Top-level structure

{
  "filename": "redfish://10.10.10.103",
  "source_type": "api",
  "protocol": "redfish",
  "target_host": "10.10.10.103",
  "collected_at": "2026-02-10T15:30:00Z",
  "hardware": {
    "board": {...},
    "firmware": [...],
    "cpus": [...],
    "memory": [...],
    "storage": [...],
    "pcie_devices": [...],
    "power_supplies": [...]
  }
}

Required: collected_at, hardware.board.serial_number Optional: target_host, source_type, protocol, filename

source_type values: api, logfile, manual protocol values: redfish, ipmi, snmp, ssh

Component status fields (all component sections)

Each component may carry:

Field Type Description
status string OK, Warning, Critical, Unknown, Empty
status_checked_at RFC3339 When status was last verified
status_changed_at RFC3339 When status last changed
status_at_collection object { "status": "...", "at": "..." } — snapshot-time status
status_history array [{ "status": "...", "changed_at": "...", "details": "..." }]
error_description string Human-readable error for Warning/Critical

Board

{
  "board": {
    "manufacturer": "Supermicro",
    "product_name": "X12DPG-QT6",
    "serial_number": "21D634101",
    "part_number": "X12DPG-QT6-REV1.01",
    "uuid": "d7ef2fe5-2fd0-11f0-910a-346f11040868"
  }
}

serial_number required. manufacturer / product_name of "NULL" treated as absent.

CPUs

{
  "socket": 0,
  "model": "INTEL(R) XEON(R) GOLD 6530",
  "cores": 32,
  "threads": 64,
  "frequency_mhz": 2100,
  "max_frequency_mhz": 4000,
  "manufacturer": "Intel",
  "status": "OK"
}

socket (int) and model required. Serial generated: {board_serial}-CPU-{socket}.

LOT format: CPU_{VENDOR}_{MODEL_NORMALIZED} → e.g. CPU_INTEL_XEON_GOLD_6530

Memory

{
  "slot": "CPU0_C0D0",
  "location": "CPU0_C0D0",
  "present": true,
  "size_mb": 32768,
  "type": "DDR5",
  "max_speed_mhz": 4800,
  "current_speed_mhz": 4800,
  "manufacturer": "Hynix",
  "serial_number": "80AD032419E17CEEC1",
  "part_number": "HMCG88AGBRA191N",
  "status": "OK"
}

slot and present required. serial_number required when present=true. Empty slots (present=false, status="Empty") are included but no component created.

LOT format: DIMM_{TYPE}_{SIZE_GB}GB → e.g. DIMM_DDR5_32GB

Storage

{
  "slot": "OB01",
  "type": "NVMe",
  "model": "INTEL SSDPF2KX076T1",
  "size_gb": 7680,
  "serial_number": "BTAX41900GF87P6DGN",
  "manufacturer": "Intel",
  "firmware": "9CV10510",
  "interface": "NVMe",
  "present": true,
  "status": "OK"
}

slot, model, serial_number, present required.

LOT format: {TYPE}_{INTERFACE}_{SIZE_TB}TB → e.g. SSD_NVME_07.68TB

Power Supplies

{
  "slot": "0",
  "present": true,
  "model": "GW-CRPS3000LW",
  "vendor": "Great Wall",
  "wattage_w": 3000,
  "serial_number": "2P06C102610",
  "part_number": "V0310C9000000000",
  "firmware": "00.03.05",
  "status": "OK",
  "input_power_w": 137,
  "output_power_w": 104,
  "input_voltage": 215.25
}

slot, present required. serial_number required when present=true. Telemetry fields (input_power_w, output_power_w, input_voltage) stored in observation only.

LOT format: PSU_{WATTAGE}W_{VENDOR_NORMALIZED} → e.g. PSU_3000W_GREAT_WALL

PCIe Devices

{
  "slot": "PCIeCard1",
  "vendor_id": 32902,
  "device_id": 2912,
  "bdf": "0000:18:00.0",
  "device_class": "MassStorageController",
  "manufacturer": "Intel",
  "model": "RAID Controller RSP3DD080F",
  "link_width": 8,
  "link_speed": "Gen3",
  "max_link_width": 8,
  "max_link_speed": "Gen3",
  "serial_number": "RAID-001-12345",
  "firmware": "50.9.1-4296",
  "status": "OK"
}

slot required. Serial generated if absent: {board_serial}-PCIE-{slot}.

device_class values: NetworkController, MassStorageController, DisplayController, etc.

LOT format: PCIE_{DEVICE_CLASS}_{MODEL_NORMALIZED} → e.g. PCIE_NETWORK_CONNECTX5

Firmware

[
  { "device_name": "BIOS", "version": "06.08.05" },
  { "device_name": "BMC",  "version": "5.17.00" }
]

Both fields required. Changes trigger FIRMWARE_CHANGED timeline events.


Import process (Reanimator side)

  1. Validate collected_at (RFC3339) and hardware.board.serial_number.
  2. Find or create Asset by board.serial_numbervendor_serial.
  3. For each component: filter present=false, auto-determine LOT, find or create Component, create Observation, update Installations.
  4. Detect removed components (present in previous snapshot, absent in current) → close Installation.
  5. Generate timeline events: LOG_COLLECTED, INSTALLED, REMOVED, FIRMWARE_CHANGED.

Idempotency: Repeated import of the same snapshot (same content hash) returns 200 OK with "duplicate": true and does not create duplicate records.

Reanimator API endpoint

POST /ingest/hardware
Content-Type: application/json

Success (201):

{
  "status": "success",
  "bundle_id": "lb_01J...",
  "asset_id": "mach_01J...",
  "collected_at": "2026-02-10T15:30:00Z",
  "duplicate": false,
  "summary": {
    "parts_observed": 15,
    "parts_created": 2,
    "installations_created": 2,
    "timeline_events_created": 9
  }
}

Duplicate (200):

{ "status": "success", "duplicate": true, "message": "LogBundle with this content hash already exists" }

Error (400):

{ "status": "error", "error": "validation_failed", "details": { "field": "...", "message": "..." } }

Common 400 causes:

  • Unknown JSON field (strict decoder)
  • Wrong key name (e.g. targetHost instead of target_host)
  • Invalid collected_at format (must be RFC3339)
  • Empty hardware.board.serial_number

LOT normalization rules

  1. Remove special chars ( ) - ® ™; replace spaces with _
  2. Uppercase all
  3. Collapse multiple underscores to one
  4. Strip common prefixes like MODEL:, PN:

Status values

Value Meaning Action
OK Normal
Warning Degraded Create COMPONENT_WARNING event (optional)
Critical Failed Auto-create failure_event, create COMPONENT_FAILED event
Unknown Not determinable Treat as working
Empty Slot unpopulated No component created (memory/PCIe only)

Missing field handling

Field Fallback
CPU serial Generated: {board_serial}-CPU-{socket}
PCIe serial Generated: {board_serial}-PCIE-{slot}
Other serial Component skipped if absent
manufacturer (PCIe) Looked up from vendor_id (8086→Intel, 10de→NVIDIA, 15b3→Mellanox…)
status Treated as Unknown
firmware No FIRMWARE_CHANGED event