homelab: alte Kernel per Knopf entfernen; Systemplatte des Proxmox-Hosts im Blick

User-Wunsch 25.09.: Auf dem Host lagen 25 Kernel (~23 GB), 20 davon hält apt für
entbehrlich (19,7 GB).
- Ausführer: host.kernel_alt/kernel_bleiben aus apt-get -s autoremove (nur
  Kernel, nie laufender, nächster oder festgepinnter), host.systemplatte;
  neue Aktion kernel_aufraeumen bestimmt die Liste selbst und purgt.
- Homelab-Teil: Lauf „kernel“ (Ergebnis aufgeraeumt), POST
  /api/homelab/ziele/pve/kernel-aufraeumen, Vorschlag mit Knopf, Wächter für die
  Systemplatte (80/90 %).
- Oberfläche: Kachel Systemplatte, Knopf „Alte Kernel entfernen“ mit Rückfrage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-25 12:16:14 +02:00
co-authored by Claude Opus 5.5
parent 28888890ec
commit 7a456c8efa
36 changed files with 377 additions and 60 deletions
+15 -3
View File
@@ -316,6 +316,16 @@ def _docker_lauf(lauf: dict, basis: str, gast: dict) -> None:
def _host_lauf(lauf: dict) -> None:
try:
if lauf["baustein"] == "kernel":
# Welche Kernel gehen, bestimmt der Ausführer selbst (nie der laufende oder der nächste).
a = _auftrag(lauf, "kernel_aufraeumen", {}, ZEITLIMIT_SICHERUNG_S)
werte = dict(z.split("=", 1) for z in str(a.get("text") or "").splitlines()[:2] if "=" in z)
anzahl, frei = int(werte.get("entfernt") or 0), int(werte.get("frei") or 0)
_auftrag(lauf, "bericht", {}, 5 * 60)
_ende(lauf, "aufgeraeumt", f"Proxmox-Host: {anzahl} alte Kernel entfernt, "
f"{frei / 1e9:.1f} GB frei geworden.".replace(".", ",", 1)
if anzahl else "Proxmox-Host: kein alter Kernel zu entfernen.")
return
if lauf["baustein"] == "neustart":
_auftrag(lauf, "host_neustart", {}, 60)
_ende(lauf, "neustart", "Der Proxmox-Host startet neu. Die KI-Box meldet, ob alles wiederkommt.")
@@ -324,7 +334,8 @@ def _host_lauf(lauf: dict) -> None:
_auftrag(lauf, "bericht", {}, 5 * 60)
_ende(lauf, "eingespielt", "Proxmox-Host: Pakete eingespielt. Ein Neustart ist ein eigener Knopf.")
except RuntimeError as exc:
_ende(lauf, "fehler", f"Proxmox-Host: Update gescheitert — {exc}", dringend=True)
was = "Kernel aufräumen" if lauf["baustein"] == "kernel" else "Update"
_ende(lauf, "fehler", f"Proxmox-Host: {was} gescheitert — {exc}", dringend=True)
def _ende(lauf: dict, ergebnis: str, text: str, dringend: bool = False) -> None:
@@ -358,7 +369,7 @@ def starten(ziel_id: str, baustein: str, sammellauf: dict | None = None) -> dict
sammellauf ({"id", "start"}) setzt nur „Alle aktualisieren“ (sammellauf.py) für seine Schritte; ohne ihn lehnt
der Knopf ab, solange ein Sammellauf läuft."""
if baustein not in ("app", "os", "pakete", "neustart", "docker"):
if baustein not in ("app", "os", "pakete", "neustart", "docker", "kernel"):
return {"ok": False, "detail": "Unbekannter Baustein."}
with START_SPERRE:
if sammellauf is None and _sammellauf_laeuft():
@@ -368,7 +379,8 @@ def starten(ziel_id: str, baustein: str, sammellauf: dict | None = None) -> dict
if ziel_id == "pve":
name, gast = "Proxmox-Host", None
host = ((kanal.bericht() or {}).get("bericht") or {}).get("host") or {}
mehr = {"pakete": len(host.get("updates") or [])} if baustein == "pakete" else {}
mehr = ({"pakete": len(host.get("updates") or [])} if baustein == "pakete"
else {"kernel": len(host.get("kernel_alt") or [])} if baustein == "kernel" else {})
else:
gast = inventar.gast(ziel_id)
if not gast: