Files
felhom.eu/documentation/audits/SPIKE-smart-coverage-2026-07-25.md
T
admin 770ee5a5f6 docs: SPIKE — SMART coverage on real hw (why the card shows Nincs adat); findings-only
Read-only probes on demo-felhom: both disks (system SSD /dev/sda, USB /dev/sdb) report
PASSED via the exact allowlisted 'smartctl -a -j <dev>'. Card shows Nincs adat because the
agent never reads: 'local' is a dir on LVM pve-root (backing='' + smartDeviceFor has no
dm/LVM branch), and the USB is surfaced via the non-enriched driveTargets.Known union path.
-d sat NOT needed (bridge passes SMART through; sudoers grants only -a -j). Graded fix
directions B(low-risk, USB) > A(system SSD, medium) > C(reject). STOP — no fix implemented.
2026-07-25 07:56:02 +02:00

8.8 KiB

SPIKE — why the v0.169.0 disk-health card shows "Nincs adat" on real hardware, 2026-07-25

Question: the new "Lemezek állapota" card (controller v0.169.x) renders Nincs adat for both physical disks on the live demo host (demo-felhom, a real N100 — NOT virtualized). Is SMART actually unavailable on this hardware, or does the agent fail to read SMART it could read? If the latter, where, and what are the fix directions?

Verdict up front: SMART is fully available on both disks via the exact form the sudoers allowlist already grants (smartctl -a -j <whole-disk>) — the system SSD and the USB HDD both report PASSED. The card says "Nincs adat" because the agent never asks, for two independent reasons:

  1. local (the system SSD) → UNKNOWN: its storage is a dir on pve-root, an LVM logical volume on sda3. The agent leaves backing_device empty for it, and even if it didn't, smartDeviceFor has no device-mapper/LVM handling — so the dir → LV → PV → whole-disk (/dev/sda) chain is never resolved and enrich skips the SMART read.
  2. The USB HDD (/dev/sdb) → ABSENT: it is surfaced only via the driveTargets.Known union path in handleDisks, which sets backing_device=/dev/sdb but never calls enrich (no SMART read at all) → the target's Smart.Health stays "" → the controller (correctly) omits it → "Nincs adat".

Neither disk needs smartctl -d sat — the USB-SATA bridge passes SMART through with plain -a -j. The -d sat candidate is disproven on this hardware, and the sudoers allowlist does not grant it anyway (recorded below). This is findings-only — no fix implemented; the fix gets its own spec.


Topology (Probe 1 — lsblk -o NAME,TYPE,TRAN,MOUNTPOINT,MODEL)

NAME                          TYPE TRAN   MOUNTPOINT MODEL
sda                           disk sata              AirDisk 512GB SSD
|-sda1                        part
|-sda2                        part        /boot/efi
`-sda3                        part                              (LVM PV)
  |-pve-swap                  lvm         [SWAP]
  |-pve-root                  lvm         /                     ← the "local" dir storage
  `-pve-data-tpool  …         lvm                               ← pve-data thin pool (VM disks 9201)
sdb                           disk usb    /mnt/hdd_1 TOSHIBA MQ04ABF100   ← the USB data drive

The customer's OS and every VM disk live on sda (SATA SSD, via LVM). The data drive is sdb (USB). Both are real, SMART-capable disks.

The /disks payload (Probe 2 — controller-side curl to the agent localapi)

local-lvm    | type=lvmthin | backing=''         | mount=''          | smart=UNKNOWN
local        | type=local   | backing=''         | mount=''          | smart=UNKNOWN
felhom-pbs   | type=pbs     | backing=''         | mount=''          | smart=UNKNOWN
47a3361a-…   | type=usb     | backing='/dev/sdb' | mount='/mnt/hdd_1' | smart=ABSENT

(The controller v0.169.1 already excludes pbs/lvmthin from the card, so only local and the USB render — both "Nincs adat".)

readlink -f /dev/sdb  → /dev/sdb           (already a clean whole-disk path; NOT a symlink)
readlink -f /dev/sda  → /dev/sda
/dev/disk/by-uuid/47a3361a-… → ../../sdb   (the durable_id's symlink; the payload already carries the resolved /dev/sdb)

The "USB backing is a by-uuid symlink the regex can't match" hypothesis does NOT apply here — the payload's backing_device is already the resolved /dev/sdb.

SMART actually works on both (Probe 4 — the EXACT allowlisted form)

# smartctl -a -j /dev/sda   (system SSD)
model: AirDisk 512GB SSD
smart_status.passed: True
messages: []

# smartctl -a -j /dev/sdb   (USB TOSHIBA, behind its USB-SATA bridge)
model: TOSHIBA MQ04ABF100
smart_status.passed: True
messages: ['Warning: This result is based on an Attribute check.']

Both return PASSED with the plain -a -j form — no -d sat needed. (The USB result is attribute-based, which is normal for a HDD behind a bridge; still a valid PASSED verdict.)

Sudoers / capability-manifest (Part 5.4 recording)

  • capability/manifest.go:94 probes with {"/usr/sbin/smartctl", ["-a","-j","/dev/sda"]}.
  • /etc/sudoers.d/felhom-agent grants only the -a -j form:
    /usr/sbin/smartctl -a -j /dev/sd[a-z]*,
    /usr/sbin/smartctl -a -j /dev/nvme[0-9]*n[0-9]*,
    /usr/sbin/smartctl -a -j /dev/vd[a-z]*,
    /usr/sbin/smartctl -a -j /dev/hd[a-z]*,
    
    /dev/sda and /dev/sdb are both permitted (the agent CAN read both today). -d sat is NOT granted — a -d sat invocation would be denied by sudoers, so any -d sat fix needs a sudoers and manifest widening.

Per-disk table — why the card says what it says

storage backing (payload) whole disk smartctl -a -j agent read path card root cause
local (dir/pve-root) '' sda (via /pve-rootsda3, unresolved) PASSED enrich: catDir but backing_device=='' → SMART skipped Nincs adat (UNKNOWN) dir-on-LVM backing never resolved; smartDeviceFor has no dm/LVM branch
USB 47a3361a /dev/sdb sdb PASSED driveTargets.Known union path — enrich never called Nincs adat (ABSENT) union path sets backing but runs no SMART read; smartDeviceFor('/dev/sdb') would resolve it
felhom-pbs / local-lvm '' — (logical/network) n/a not catDir (excluded, v0.169.1) correct — not physical disks

smartDeviceFor (source): maps …/nvme0n1pN → …/nvme0n1 and …/sdbN → …/sdb, then ValidateSMARTDevice. A whole disk /dev/sdb passes through unchanged and validates → it would resolve fine if enrich were ever called on the union path. There is no branch for /dev/mapper/* or /dev/dm-*, which is why an LVM-backed dir can never resolve.


Fix directions (graded — DO NOT IMPLEMENT; each needs its own spec)

A — Resolve dm/LVM → whole disk (reaches the SYSTEM SSD local)

Resolve the dir's mount → LV → PV → whole disk (e.g. lsblk -s -no pkname <dev>, or /sys/block/dm-*/slaves), set backing_device accordingly, and add a dm/LVM branch to smartDeviceFor.

  • Reach: HIGH — the system SSD holds the OS and all VM data; it is the single most important disk to monitor. Also covers any other dir-on-LVM storage.
  • Risk: MEDIUM — an LVM VG can span multiple PVs (a dir → N disks, not one); the resolver must handle the multi-slave/RAID case (probe each, report per-disk) rather than assume one. Must not mis-resolve stacked dm (thin pools). Needs a focused test over single-PV and multi-PV shapes.

B — Enrich the driveTargets.Known union path (reaches the USB / felhom data drives)

Run the same SMART read on handleDisks' union branch when backing_device != "".

  • Reach: GOOD — the felhom-enrolled data drives (the USB here), which is exactly what a customer cares about most for a health card.
  • Risk: LOW — the backing path is already a clean whole disk, smartDeviceFor already resolves it, and sudoers already grants /dev/sd[a-z]*. Care points: the union path lives in localapi while enrich/SMART lives in storage (reuse the o.ops.SMART seam or a small helper, no duplication), and don't pay smartctl on every /disks call — the controller's 60s TTL cache already blunts the storm, but consider a short agent-side memo if /disks is hit hard. Cheapest win; do this first.

C — smartctl -d sat retry (+ sudoers/manifest widening) — REJECT for now

  • Reach: NONE on this hardware — the USB bridge already returns PASSED with plain -a -j (disproven above). Would only matter for a future bridge that yields UNKNOWN with -a -j.
  • Risk: HIGH-relative — requires adding smartctl -d sat -a -j /dev/sd[a-z]* (+ nvme/vd/hd) to both /etc/sudoers.d/felhom-agent and capability/manifest.go (widening the root-command allowlist — a privilege-surface change), plus a retry loop. Keep as a documented fallback, gated on an actual UNKNOWN-with--a -j disk appearing in the field.

Not needed here (backing_device is already /dev/sdb), but cheap insurance for a future payload that carries a /dev/disk/by-* symlink. Low priority, fold into A/B if convenient.

Recommended order (for the follow-up spec): B (low-risk, covers the data drive) → A (higher value, medium risk, covers the system disk) → skip C until a bridge demands it.


STOP. No agent code, sudoers, or capability-manifest change was made in this spike (read-only probes only). The fix is a separate task.