pro-4gain-inventory) на fireflyregistry.4gain.pro/forgain/applications/inventory-dashboard:latestsm2c-cloud-inventoryservice-inventory-bootstrap.yml/mnt/compose/pro-4gain-inventory/{data,repo,ssh}forgain/applications/inventory-dashboard/ — список физических хостовКарточки firefly / hatanga / sarva / zilim (и т.д.) с полями:
X+Y где X — диски физ.хоста, Y — проброшенные в VM за RAID),/host/<fqdn> — детали▢ system или ▣ RAID:aacraid/megaraid/cciss/areca),<details>./summary — сводка по парку/vms — VM-таблицаВсе VM с proxmox-кластера (через pvesh get /cluster/resources): node / vmid / name / status / cpu / mem / disk / uptime.
GET /api/v1/hosts — список (fqdn, last_seen, staleness)GET /api/v1/host/<fqdn> — full JSON snapshotPOST /api/v1/push — приём от collector'а, auth через Bearer $INVENTORY_PUSH_TOKEN┌─ APScheduler (внутри dashboard, persist в той же sqlite) ─┐
│ cron `*:07` ежечасно: │
│ 1. git pull /repo/ansible/{playbooks,inventory,roles/ │
│ sm2c-inventory-collect} │
│ 2. ansible-playbook -c ssh │
│ /repo/ansible/playbooks/inventory-collect.yml │
└────────────────────────┬───────────────────────────────────┘
│ ssh root@<host>
▼
┌─ Роль sm2c-inventory-collect (на каждом хосте) ───────────┐
│ a. install-deps (jq, dmidecode, lshw, smartmontools, │
│ lm-sensors, ipmitool, pciutils, nvme-cli, ethtool) │
│ b. /usr/local/sbin/sm2c-inventory-collect (bash) │
│ → DMI (mb/cpu/dimms/bios) │
│ → smartctl --scan-open + aacraid/megaraid pd-probe │
│ → ipmitool sdr (per-DIMM/CPU/PSU temps) │
│ → lspci -vmmnnk (без системных мостов) │
│ → nvidia-smi (если есть) │
│ → pvesh /cluster/resources (на pve-нодах) │
│ → одиночный JSON │
│ c. inject `passthrough_owner` из inventory hostvars │
│ d. POST $JSON → http://10.19.1.150:8092/api/v1/push │
│ (LAN-IP — потому что proxmox-ноды не в AWG-mesh) │
└────────────────────────┬───────────────────────────────────┘
│
▼
┌─ /api/v1/push (Flask) ────────────────────────────────────┐
│ 1. Bearer-проверка │
│ 2. ingest_payload(): │
│ - upsert Host(fqdn, last_seen, passthrough_for) │
│ - INSERT Snapshot (полный JSON, 30 дней retention) │
│ - если payload.proxmox_vms — replace VM-таблицу │
│ для node==self │
│ 3. cleanup-job ежедневно 03:15 — drop snapshots > 30d │
└────────────────────────────────────────────────────────────┘
smartctl --scan-open для megaraid возвращает физ. диски сразу. Для Adaptec aacraid —
только logical drives, поэтому collect.sh дополнительно перебирает физ. слоты:
smartctl -i -d sat+aacraid,0,0,$ID /dev/sda # ID=0..31
smartctl -i -d aacraid,0,0,$ID /dev/sda # fallback для SAS
Найденные физ. диски добавляются с smart_type=sat+aacraid,0,0,N. Logical drives
(model="Adaptec…") скрываются в пост-фильтре, если за тем же контроллером
найден хоть один физический диск — иначе двойной счёт.
Аналогичная логика для megaraid (model "MR..."/"Avago"/"LSI"/"Broadcom") и
cciss (HP Smart Array).
Если в inventory hosts.yml у хоста задано:
inventory_passthrough_owner: sarva.e1.4gain.pro
то это VM, чьё железо проброшено через vfio-pci с указанного physical-host.
Роль инжектит поле passthrough_owner в JSON. Dashboard:
/ (отфильтрован по Host.passthrough_for IS NULL),sarva справа от disk count появляется +N (диски за RAID),/host/sarva показывается оранжевая секция ▣ passed-through hardware с дисками за RAID-контроллером, прокинутым в VM (виртуальные QEMU/virtio OS-диски VM скрыты).ipmitool sdr type Temperature парсится awk-ом: locator (P1-DIMMA1) → temp °C.
Маппинг по locator'у с DIMM-ом из dmidecode → выводится в колонке temp на странице хоста.
Поддерживается на firefly (Supermicro X11DAi-N IPMI). На hatanga (Dell iDRAC) IPMI
доступен только если поднят kernel-модуль ipmi_devintf — иначе секция пустая.
CI: forgain/applications/inventory-dashboard/.gitlab-ci.yml собирает в registry.
Сейчас runner-ы 14.x на firefly не работают (Docker API mismatch, см. security-todo
#2). Пока — ручной билд:
ssh -p 21150 root@firefly.e1.4gain.pro
cd /tmp/inv-build && git pull
docker build -f docker/Dockerfile -t registry.4gain.pro/forgain/applications/inventory-dashboard:latest .
docker push registry.4gain.pro/forgain/applications/inventory-dashboard:latest
cd ansible/playbooks
INVENTORY_PUSH_TOKEN=$(openssl rand -hex 32) \
GITLAB_RO_TOKEN=<gitlab-pat> \
ansible-playbook -c ssh service-inventory-bootstrap.yml
Что делает:
/mnt/compose/pro-4gain-inventory/{data,repo,ssh}.id_ed25519 (раз) для контейнерного ансибла.docker compose up -d./mnt/swarm/traefik_data/custom/pro-4gain-inventory.yml./healthz.inventory.vpn.4gain.pro → 10.9.0.191 через DO API.После первого деплоя — раскатать pubkey на хосты:
ansible-playbook -c ssh /tmp/inv-key.yml
# где /tmp/inv-key.yml — добавляет cat /mnt/compose/pro-4gain-inventory/ssh/id_ed25519.pub
# в authorized_keys на cloud + proxmox + аннотированных VM
ssh -p 21150 root@firefly.e1.4gain.pro
docker exec pro-4gain-inventory bash -c \
"cd /repo/ansible/playbooks && \
ansible-playbook -c ssh -i /repo/inventory/hosts.yml inventory-collect.yml"
vpn-only middleware. Защищает от ipAllowList-обхода частично — см. security-todo #1 (та же проблема что у llama)./api/v1/push принимает push по LAN-IP firefly — proxmox-ноды без AWG-mesh могут пушить, но это значит токен по plaintext HTTP. Допустимо в LAN.INVENTORY_PUSH_TOKEN в env стека = в hostvars при сборе. При смене обновлять оба места.Changelog