homelab: Arcane und Docker (eigene Version oeffentlich, Images mit Schluessel, Updates zuerst als Probelauf); Datei-Sperren gegen Windows-Wettlauf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5e9227c4a3
commit
209549f0f3
@@ -20,7 +20,7 @@ from kern.github import neueste_version
|
||||
from kern.zeit import LOCAL_TZ
|
||||
from kern.ziele import Aktion, BausteinStand, ZielStand
|
||||
|
||||
from services.homelab import apps, kanal
|
||||
from services.homelab import apps, arcane, kanal
|
||||
|
||||
BERICHT_ALT_S = 30 * 60
|
||||
LISTEN_ALT_S = 14 * 24 * 3600
|
||||
@@ -117,6 +117,42 @@ def _os_baustein(gast: dict, zid: str, jetzt: float) -> BausteinStand:
|
||||
return stand
|
||||
|
||||
|
||||
def _arcane_bausteine(basis: str | None, zid: str) -> list[BausteinStand]:
|
||||
"""Arcane selbst (öffentliche Version) und die Docker-Images (mit API-Schlüssel)."""
|
||||
app = arcane.app_version(basis) if basis else None
|
||||
selbst = BausteinStand(id="arcane", name="Arcane", zustand="unbekannt",
|
||||
installiert=app["installiert"] if app else None, verfuegbar=app["neu"] if app else None)
|
||||
if not app:
|
||||
selbst.grund = "Arcane antwortet nicht."
|
||||
elif app["update"]:
|
||||
selbst.zustand, selbst.kurz = "neu", f"{app['installiert']} → {app['neu']}"
|
||||
selbst.grund = "Arcane spielt sein eigenes Update über die eigene Oberfläche ein (Einstellungen)."
|
||||
else:
|
||||
selbst.zustand = "aktuell"
|
||||
docker = BausteinStand(id="docker", name="Docker-Images", zustand="unbekannt")
|
||||
if not arcane.schluessel():
|
||||
docker.grund = ("Es fehlt ein Arcane-API-Schlüssel (MC_ARCANE_KEY): ohne ihn sieht der Orchestrator "
|
||||
"die Images nicht.")
|
||||
elif basis:
|
||||
try:
|
||||
images = arcane.images_mit_update(basis)
|
||||
except Exception:
|
||||
docker.grund = "Arcane verweigert die Auskunft oder antwortet nicht (Schlüssel prüfen)."
|
||||
else:
|
||||
if images:
|
||||
docker.zustand, docker.kurz = "neu", f"{len(images)} Images"
|
||||
docker.grund = ", ".join(i["name"] for i in images[:6]) + (" …" if len(images) > 6 else "")
|
||||
probe = not arcane.echt()
|
||||
docker.aktion = Aktion(
|
||||
"POST", f"/api/homelab/ziele/{zid}/docker",
|
||||
("Arcane prüft im Probelauf, welche Container es aktualisieren würde — geändert wird noch nichts."
|
||||
if probe else "Arcane aktualisiert jetzt die Container mit neuen Images; Daten-Volumes bleiben."),
|
||||
label="Probelauf" if probe else "Jetzt updaten")
|
||||
else:
|
||||
docker.zustand = "aktuell"
|
||||
return [selbst, docker]
|
||||
|
||||
|
||||
def _gast_ziel(gast: dict, jetzt: float) -> ZielStand:
|
||||
art = "container" if gast["art"] == "lxc" else "vm"
|
||||
zid = f"{'ct' if art == 'container' else 'vm'}-{gast['vmid']}"
|
||||
@@ -131,6 +167,10 @@ def _gast_ziel(gast: dict, jetzt: float) -> ZielStand:
|
||||
ziel.bausteine.append(BausteinStand(id="status", name="Status", zustand="unbekannt",
|
||||
grund=f"Der Gast ist {gast.get('status') or 'unbekannt'}."))
|
||||
return ziel
|
||||
if app and app.kennung == "arcane":
|
||||
# Arcane läuft über seine eigene Schnittstelle, nicht über den Ausführer: kein Etikett nötig.
|
||||
ziel.bausteine += _arcane_bausteine(url.rstrip("/") if url else None, zid)
|
||||
return ziel
|
||||
if not gast.get("erlaubt"):
|
||||
ziel.bausteine.append(BausteinStand(
|
||||
id="freigabe", name="Freigabe", zustand="unbekannt",
|
||||
|
||||
Reference in New Issue
Block a user