Synthesized from bible-local reviews across bee, logpile, core, chart, PriceForge: - rules/patterns/hardware-ingest-json/contract.md — Reanimator JSON ingest schema v2.10 - rules/patterns/submodule-integration/contract.md — read-only submodule principle - go-database: add driver-level violation symptoms for cursor safety rule Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
15 KiB
Contract: Hardware Ingest JSON
Version: 2.10
Source: bee/bible-local/docs/hardware-ingest-contract.md (canonical upstream)
Стандартный JSON-контракт для передачи данных об аппаратном обеспечении серверов в Reanimator.
Используется в bee, logpile, core и внешних интеграторах (Redfish-коллекторы, CMDB-экспортёры).
Актуальная версия: https://git.mchus.pro/reanimator/core/src/branch/main/bible-local/docs/hardware-ingest-contract.md
Принципы
- Snapshot — JSON описывает состояние сервера на момент сбора. Может включать историю изменений статуса.
- Идемпотентность — повторная отправка идентичного payload не создаёт дублей (дедупликация по хешу).
- Частичность — можно передавать только те секции, данные по которым доступны. Пустой массив и отсутствие секции эквивалентны.
- Строгая схема — endpoint использует строгий JSON-декодер; неизвестные поля приводят к
400 Bad Request. - Event-driven — импорт создаёт события в timeline (LOG_COLLECTED, INSTALLED, REMOVED, FIRMWARE_CHANGED и др.).
- Без синтеза — сборщик передаёт только фактически собранные значения. Запрещено придумывать
serial_number,component_ref,message,message_idили иные идентификаторы, если источник их не предоставил.
Endpoint
POST /ingest/hardware
Content-Type: application/json
Ответ 202 Accepted с job_id. Результат: GET /ingest/hardware/jobs/{job_id}.
Структура верхнего уровня
{
"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": [ ... ],
"sensors": { ... },
"event_logs": [ ... ],
"platform_config": { ... }
}
}
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
collected_at |
string RFC3339 | да | Время сбора данных |
hardware |
object | да | Аппаратный снапшот |
hardware.board.serial_number |
string | да | Серийный номер платы/сервера |
target_host |
string | нет | IP или hostname |
source_type |
string | нет | api, logfile, manual |
protocol |
string | нет | redfish, ipmi, snmp, ssh |
filename |
string | нет | Идентификатор источника |
Общие поля статуса компонентов
Применяются ко всем компонентным секциям (cpus, memory, storage, pcie_devices, power_supplies).
| Поле | Тип | Описание |
|---|---|---|
status |
string | OK, Warning, Critical, Unknown, Empty |
status_checked_at |
string RFC3339 | Время последней проверки |
status_changed_at |
string RFC3339 | Время последнего изменения |
status_history |
array | История переходов (status, changed_at обязательны) |
error_description |
string | Текст ошибки/диагностики |
manufactured_year_week |
string | Дата производства YYYY-Www, например 2024-W07 |
Правила статуса:
- Не включайте записи
status_historyбезchanged_at. status_historyсортировать поchanged_atпо возрастанию.- Все даты — RFC3339, рекомендуется UTC (
Z).
| Статус | Поведение |
|---|---|
OK |
Нормальная обработка |
Warning |
Создаётся событие COMPONENT_WARNING |
Critical |
Создаётся событие COMPONENT_FAILED + запись в failure_events |
Unknown |
Компонент считается рабочим, создаётся событие COMPONENT_UNKNOWN |
Empty |
Компонент не создаётся/не обновляется |
Секции hardware
board (обязательная)
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
serial_number |
string | да | Серийный номер (ключ идентификации Asset) |
manufacturer |
string | нет | Производитель |
product_name |
string | нет | Модель |
part_number |
string | нет | Партномер |
uuid |
string | нет | UUID системы |
Значения "NULL" в строковых полях трактуются как отсутствие данных.
firmware
| Поле | Тип | Обязательно |
|---|---|---|
device_name |
string | да |
version |
string | да |
Записи с пустым device_name или version игнорируются. Изменение версии создаёт событие FIRMWARE_CHANGED.
cpus
| Поле | Тип | Описание |
|---|---|---|
socket |
int | обязательно; используется для генерации serial |
model |
string | Модель процессора |
manufacturer |
string | |
cores / threads |
int | |
frequency_mhz / max_frequency_mhz |
int | |
temperature_c |
float | Telemetry, °C |
power_w |
float | Telemetry, Вт |
throttled |
bool | Thermal/power throttling |
correctable_error_count / uncorrectable_error_count |
int | |
life_remaining_pct / life_used_pct |
float | Health/wear, % |
serial_number |
string | Если доступен |
firmware |
string | Версия микрокода (Microcode level — передавать как есть) |
present |
bool | По умолчанию true |
Генерация serial при отсутствии: {board_serial}-CPU-{socket}
memory
| Поле | Тип | Описание |
|---|---|---|
slot |
string | |
present |
bool | По умолчанию true |
serial_number |
string | Обязателен для создания записи |
part_number |
string | Используется как модель |
manufacturer |
string | |
size_mb |
int | |
type |
string | DDR3, DDR4, DDR5 |
max_speed_mhz / current_speed_mhz |
int | |
temperature_c |
float | Telemetry |
correctable_ecc_error_count / uncorrectable_ecc_error_count |
int | |
life_remaining_pct / life_used_pct / spare_blocks_remaining_pct |
float | |
performance_degraded / data_loss_detected |
bool |
Модуль без serial_number, с present=false или status=Empty игнорируется.
storage
| Поле | Тип | Описание |
|---|---|---|
slot |
string | BDF (0000:18:00.0) для PCIe-подключённых |
serial_number |
string | Обязателен для создания записи |
model / manufacturer |
string | |
type |
string | NVMe, SSD, HDD |
interface |
string | NVMe, SATA, SAS |
size_gb |
int | |
logical_block_size_bytes |
int64 | Логический размер блока, например 512 или 4096 |
physical_block_size_bytes |
int64 | Физический размер блока |
metadata_bytes_per_block |
int64 | Metadata/protection bytes на блок, например 0 или 8 |
temperature_c |
float | Telemetry |
power_on_hours / power_cycles / unsafe_shutdowns |
int64 | |
media_errors / error_log_entries |
int64 | |
written_bytes / read_bytes |
int64 | |
life_used_pct / life_remaining_pct / available_spare_pct |
float | |
reallocated_sectors / current_pending_sectors / offline_uncorrectable |
int64 | |
firmware |
string | Изменение создаёт FIRMWARE_CHANGED |
present |
bool | По умолчанию true |
Формат 512+8 не передаётся строкой — только через logical_block_size_bytes + metadata_bytes_per_block.
Диск без serial_number игнорируется.
pcie_devices
| Поле | Тип | Описание |
|---|---|---|
slot |
string | Канонический адрес (BDF). bdf — deprecated alias, нормализуется при ingest |
vendor_id / device_id |
int | PCI ID (decimal) |
numa_node |
int | NUMA/CPU affinity |
device_class |
string | MassStorageController, StorageController, NetworkController, EthernetController, FibreChannelController, VideoController, ProcessingAccelerator, DisplayController (список открытый) |
manufacturer / model / serial_number / firmware |
string | |
link_width / max_link_width |
int | |
link_speed / max_link_speed |
string | Gen3, Gen4, Gen5 |
mac_addresses |
string[] | MAC-адреса портов |
temperature_c / power_w |
float | Device-level telemetry |
life_remaining_pct / life_used_pct |
float | |
ecc_corrected_total / ecc_uncorrected_total |
int64 | |
hw_slowdown |
bool | |
battery_charge_pct / battery_health_pct / battery_temperature_c / battery_voltage_v |
float | |
battery_replace_required |
bool | |
sfp_temperature_c / sfp_tx_power_dbm / sfp_rx_power_dbm / sfp_voltage_v / sfp_bias_ma |
float | Optical telemetry |
present |
bool | По умолчанию true |
Генерация serial при отсутствии или "N/A": {board_serial}-PCIE-{slot}
power_supplies
| Поле | Тип | Описание |
|---|---|---|
slot |
string | |
present |
bool | По умолчанию true |
serial_number |
string | Обязателен для создания записи |
part_number / model / vendor |
string | |
wattage_w |
int | |
firmware |
string | |
input_type |
string | Например ACWideRange |
input_voltage / input_power_w / output_power_w / temperature_c |
float | Telemetry |
life_remaining_pct / life_used_pct |
float |
PSU без serial_number игнорируется.
sensors (опционально)
Данные хранятся как last-known-value на уровне Asset. Идентификатор: (sensor_type, name).
Поле location передавать не нужно — игнорируется. Сенсоры без name игнорируются.
"sensors": {
"fans": [{ "name": "FAN1", "rpm": 4200, "status": "OK" }],
"power": [{ "name": "12V Rail", "voltage_v": 12.06, "status": "OK" }],
"temperatures": [{ "name": "CPU0 Temp", "celsius": 46.0, "threshold_warning_celsius": 80.0, "threshold_critical_celsius": 95.0, "status": "OK" }],
"other": [{ "name": "System Humidity", "value": 38.5, "unit": "%" }]
}
event_logs (опционально)
Нормализованные операционные логи. Не попадают в history timeline. Дедуплицируются по (asset, source, fingerprint).
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
source |
string | да | host, bmc, redfish |
message |
string | да | Нормализованный текст события |
event_time |
string RFC3339 | нет | |
severity |
string | нет | OK, Info, Warning, Critical, Unknown |
message_id |
string | нет | Код события источника |
component_ref |
string | нет | Ссылка на компонент/слот |
fingerprint |
string | нет | Внешний dedup-key; если нет — система вычисляет свой |
is_active |
bool | нет | Событие всё ещё активно |
raw_payload |
object | нет | Сырой vendor-specific payload |
Запрещено синтезировать message, message_id, component_ref, serial/device identifiers.
platform_config (опционально)
Произвольный объект с настройками платформы (BIOS/Redfish/IPMI) как есть из источника. При каждом импорте хранится latest-snapshot per machine.
Обработка отсутствующих serial_number
Интегратор не подставляет вымышленные значения, хеши или placeholder-идентификаторы. Разрешены только server-side fallback-правила:
| Тип | Поведение |
|---|---|
| CPU | Генерируется: {board_serial}-CPU-{socket} |
| PCIe | Генерируется: {board_serial}-PCIE-{slot} |
| Memory | Компонент игнорируется |
| Storage | Компонент игнорируется |
| PSU | Компонент игнорируется |
Если serial_number не уникален внутри payload для того же model: первое вхождение — оригинальный serial, дубли получают NO_SN-XXXXXXXX.
Минимальный валидный пример
{
"collected_at": "2026-02-10T15:30:00Z",
"target_host": "192.168.1.100",
"hardware": {
"board": {
"serial_number": "SRV-001"
}
}
}
Changelog
| Версия | Дата | Изменения |
|---|---|---|
| 2.10 | 2026-04-29 | hardware.storage[]: добавлены logical_block_size_bytes, physical_block_size_bytes, metadata_bytes_per_block |
| 2.9 | 2026-03-19 | Добавлена секция hardware.platform_config |
| 2.8 | 2026-03-15 | Поле location удалено из всех sensors.* |
| 2.7 | 2026-03-15 | Явно запрещён синтез данных в event_logs |
| 2.6 | 2026-03-15 | Добавлена секция event_logs |
| 2.5 | 2026-03-15 | Добавлено manufactured_year_week для всех компонентов |
| 2.4 | 2026-03-15 | Component telemetry: health/life поля для всех секций |
| 2.0 | 2026-02-01 | status_history, status_changed_at; async job response |
| 1.0 | 2026-01-01 | Начальная версия |