feat(host_agent): each drive's health, read with smartctl, alertable (#5789)
The root helper gains one read-only action, `drives`: it finds the drives itself (smartctl --scan-open), reads each as JSON, and writes a summary the agent carries on every sample (agent 1.20.0). Steward judges the figures in drives.py (failing / worn / watch / ok / no SMART / unreadable), records them per drive and as host roll-ups for covering rules, keeps the newest report on the registration and lists it on the host page. install-deps.sh installs smartmontools with apt, dnf, yum, zypper, pacman or apk, run by install.sh and every agent playbook; one it can't install is reported, never fatal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -119,6 +119,41 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# ── Drive health (#5789): each drive as the root helper read it with
|
||||
smartctl, hourly; what needs attention first (drives.py judges them). ──── #}
|
||||
{% set drive_badge = {"failing": ("crit", "Failing"), "unreadable": ("warn", "Unreadable"),
|
||||
"worn": ("warn", "Worn"), "watch": ("warn", "Watch"), "ok": ("ok", "OK"),
|
||||
"unavailable": ("inactive", "No SMART")} %}
|
||||
{% if drives or drives_error %}
|
||||
<div class="card">
|
||||
<div class="section-title" style="margin-bottom:0.5rem;display:flex;justify-content:space-between;gap:0.75rem;">
|
||||
<span>Drive health</span>
|
||||
{% if drives_at %}<span style="font-weight:400;color:var(--text-dim);font-size:0.72rem;">read {{ drives_at|ago }}</span>{% endif %}
|
||||
</div>
|
||||
{% if drives_error %}
|
||||
<p class="field-hint" style="margin:0;">Not read: {{ drives_error }}.</p>
|
||||
{% endif %}
|
||||
{% for d in drives %}
|
||||
{% set tone, label = drive_badge[d.state] %}
|
||||
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:0.75rem;font-size:0.8rem;padding:0.2rem 0;">
|
||||
<span style="min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" title="{{ d.model }}">
|
||||
{{ status_badge(tone, label) }}
|
||||
<span style="font-family:ui-monospace,monospace;">{{ d.device }}</span>
|
||||
{% if d.model %}<span style="color:var(--text-dim);">{{ d.model }}{% if d.capacity_bytes %} · {{ d.capacity_bytes|bytes }}{% endif %}</span>{% endif %}
|
||||
{% if d.why %}<span style="color:var(--text-muted);"> — {{ d.why }}</span>{% endif %}
|
||||
</span>
|
||||
<span style="color:var(--text-muted);font-variant-numeric:tabular-nums;white-space:nowrap;">
|
||||
{%- set parts = [] -%}
|
||||
{%- if d.get("life_used_pct") is not none %}{% set _ = parts.append("%d%% life used"|format(d.life_used_pct)) %}{% endif -%}
|
||||
{%- if d.get("bad_sectors") is not none %}{% set _ = parts.append("%d bad sectors"|format(d.bad_sectors)) %}{% endif -%}
|
||||
{%- if d.get("temp_c") is not none %}{% set _ = parts.append("%d°C"|format(d.temp_c)) %}{% endif -%}
|
||||
{{ parts|join(" · ") if parts else "—" }}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# ── Interfaces / disks (short panels, side by side at natural height) ─────── #}
|
||||
{% if nets or disks_io %}
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:1rem;align-items:start;">
|
||||
|
||||
@@ -63,6 +63,12 @@ chmod 0640 "$CONF_FILE"
|
||||
curl -fsSL "${FILES_URL}/maint.py" -o "$AGENT_DIR/maint.py"
|
||||
chmod 0755 "$AGENT_DIR/maint.py"
|
||||
chown root:root "$AGENT_DIR/maint.py"
|
||||
# Its packages (smartctl for drive health, #5789), with whichever package
|
||||
# manager this host has; one that can't be installed is said, never fatal.
|
||||
curl -fsSL "${FILES_URL}/install-deps.sh" -o "$AGENT_DIR/install-deps.sh"
|
||||
chmod 0755 "$AGENT_DIR/install-deps.sh"
|
||||
chown root:root "$AGENT_DIR/install-deps.sh"
|
||||
"$AGENT_DIR/install-deps.sh" || true
|
||||
install -d -o root -g root -m 0755 /var/lib/steward-agent /var/lib/steward-maint /var/lib/steward-maint/results
|
||||
install -d -o "$AGENT_USER" -g "$AGENT_USER" -m 0700 /var/lib/steward-agent/requests
|
||||
for u in $UNITS; do
|
||||
|
||||
Reference in New Issue
Block a user