Später · 18 Plattengesundheit: Proxmox-Host, NAS über SNMP, NVMe der KI-Box

- kern/platten.py: SMART aus pvesh, smartctl und SNMP in einer Form; rot bei SMART FAILED, kritischer Warnung,
  aufgebrauchter Reserve, ≥ 90 % verbraucht; gelb bei ≥ 80 %, Hitze, gewachsenen Fehlerzählern (Ausgangslage je
  Platte, „Zur Kenntnis genommen“ setzt sie neu)
- Ausführer: stündlich disks/list + disks/smart im Bericht (nur lesend)
- services/homelab/nas_snmp.py: kleiner SNMPv2c-GetBulk-Leser ohne neue Abhängigkeit, QNAP hdTable/diskTable,
  Zugang 0600, Einstellungen „Verbindung testen und speichern“
- services/platten.py: NVMe der KI-Box über sudo smartctl (smartmontools am 26.09. nachinstalliert)
- Wächter beider Rollen, Plattenfeld in beiden Cockpits, Doku

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-26 09:54:38 +02:00
co-authored by Claude Opus 5.5
parent 5325544d89
commit 904598031a
46 changed files with 1212 additions and 41 deletions
+34
View File
@@ -1115,10 +1115,44 @@ def bericht() -> dict:
host["netz"] = _netz_stand()
except Exception as exc:
host["netz_fehler"] = str(exc)[:200]
try:
host["platten"] = _platten_stand()
except Exception as exc:
host["platten_fehler"] = str(exc)[:200]
return {"zeit": datetime.now(timezone.utc).isoformat(timespec="seconds"), "host": host,
"gaeste": sorted(gaeste, key=lambda g: g["vmid"])}
# --- Plattengesundheit (seit 26.09.2026, nur lesend) ------------------------------------------------------
# Was Proxmox selbst über seine Platten weiß (Rechenzentrum → Knoten → Disks): Liste mit Gesundheit und Verschleiß,
# dazu je Platte die SMART-Werte. Ausgewertet wird auf dem Server (backend/kern/platten.py); höchstens stündlich.
PLATTEN_ALLE_S = 3600
_platten: dict = {"zeit": 0.0, "stand": None}
def platten() -> list[dict]:
ergebnis = []
for disk in _pvesh(f"/nodes/{NODE}/disks/list") or []:
if not isinstance(disk, dict) or not disk.get("devpath"):
continue
try:
smart = _pvesh(f"/nodes/{NODE}/disks/smart", "--disk", str(disk["devpath"]))
except Exception as exc:
smart = {"fehler": str(exc)[:200]}
ergebnis.append({"disk": {k: disk.get(k) for k in ("devpath", "model", "serial", "type", "size", "health",
"wearout", "rpm")},
"smart": smart if isinstance(smart, dict) else None})
return ergebnis
def _platten_stand() -> list[dict]:
if _platten["stand"] is None or time.time() - _platten["zeit"] >= PLATTEN_ALLE_S:
_platten["stand"] = platten()
_platten["zeit"] = time.time()
return _platten["stand"]
# --- Geräte im Heimnetz (seit 26.09.2026, nur lesend) ----------------------------------------------------
# AdGuard sieht in diesem Netz fast nur die Fritzbox (sie reicht die Anfragen der meisten Geräte weiter). Wer im
# Heimnetz ist, verrät deshalb die Nachbartabelle dieses Hosts: Alle NETZ_ALLE_S ein Ping an jede Adresse des Netzes