From f2bffc7203a3c33e5b372e4acf9d395ba83a64aa Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Fri, 25 Sep 2026 17:16:22 +0200 Subject: [PATCH] =?UTF-8?q?Welle=201=20=C2=B7=20Nachschliff:=20Proxmox-Kac?= =?UTF-8?q?hel=20z=C3=A4hlt=20die=20G=C3=A4ste=20wie=20die=20Homelab-Karte?= =?UTF-8?q?,=20der=20eigene=20Container=20hei=C3=9Ft=20lesbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit „8 von 8 Gästen an“ neben „7 Gäste“: Die Kachel zählte den eigenen Container (Etikett mc2) mit, die Karte nicht. In „Sicherungen je Gerät“ heißt er „Homelab Orchestrator (dieser Container)“ statt homelab-orchestrator. Co-Authored-By: Claude Opus 5.5 --- backend/services/homelab/kennzahlen.py | 5 ++++- backend/services/homelab/speicher.py | 4 +++- backend/tests/test_kennzahlen.py | 4 +++- backend/tests/test_sicherungs_abdeckung.py | 8 +++++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/backend/services/homelab/kennzahlen.py b/backend/services/homelab/kennzahlen.py index 6c1bf45..41e30b1 100644 --- a/backend/services/homelab/kennzahlen.py +++ b/backend/services/homelab/kennzahlen.py @@ -13,6 +13,7 @@ höchstens alle zwei Minuten gefragt. import logging from services.homelab import adguard, apps, arcane, zertifikate +from services.homelab.inventar import EIGENES_ETIKETT log = logging.getLogger(__name__) NPM = {"npmplus", "nginxproxymanager"} @@ -36,7 +37,9 @@ def _npm(vmid: int) -> dict | None: def fuer_bericht(bericht: dict) -> dict[str, dict]: """Ziel-ID → Kennzahl. Ein Fehler bei einem Gerät kostet nur dessen Zahl.""" zahlen: dict[str, dict] = {} - gaeste = [g for g in bericht.get("gaeste") or [] if isinstance(g, dict) and "vmid" in g] + # Der eigene Container (Etikett „mc2“) zählt nicht mit — wie überall, wo die Geräte des Homelabs stehen. + gaeste = [g for g in bericht.get("gaeste") or [] if isinstance(g, dict) and "vmid" in g + and EIGENES_ETIKETT not in (g.get("etiketten") or [])] if gaeste: laufend = sum(1 for g in gaeste if g.get("status") == "running") zahlen["pve"] = {"text": f"{laufend} von {len(gaeste)} Gästen an"} diff --git a/backend/services/homelab/speicher.py b/backend/services/homelab/speicher.py index 3e52c96..18a0f29 100644 --- a/backend/services/homelab/speicher.py +++ b/backend/services/homelab/speicher.py @@ -375,8 +375,10 @@ def _je_geraet(bericht: dict, ziele: dict, fehlend: set[str], ohne: set[int], pr zuletzt = max([t for z in ziele.values() if (t := (z.get("neueste") or {}).get(vmid))], default=None) pruefungen = [d["geprueft"] for d in details if d.get("geprueft")] eigene_probe = ((probe or {}).get("gaeste") or {}).get(vmid) + eigener = EIGENES_ETIKETT in (g.get("etiketten") or []) zeilen.append({ - "ziel": _zid(g), "name": _name(g), "vmid": g["vmid"], "auftrag": g["vmid"] not in ohne, + "ziel": _zid(g), "name": "Homelab Orchestrator (dieser Container)" if eigener else _name(g), + "vmid": g["vmid"], "auftrag": g["vmid"] not in ohne, "zuletzt": zuletzt, "frisch": bool(zuletzt) and g["vmid"] not in ohne and _zid(g) not in fehlend, "geprueft": max(pruefungen, key=lambda p: (p["zeit"], p["sicherung"]), default=None), "defekt": sorted({t for d in details for t in d.get("defekt") or []}), diff --git a/backend/tests/test_kennzahlen.py b/backend/tests/test_kennzahlen.py index 762c026..f3a9232 100644 --- a/backend/tests/test_kennzahlen.py +++ b/backend/tests/test_kennzahlen.py @@ -38,7 +38,9 @@ def test_zahlen_je_geraet(monkeypatch): monkeypatch.setattr(zertifikate, "lage", lambda jetzt=None: {"zertifikate": [npm] * 10}) monkeypatch.setattr(arcane, "container_zahlen", lambda url: {"laufend": 11, "gesamt": 12}) monkeypatch.setattr(adguard, "geblockt", lambda: {"anfragen": 84_211, "geblockt": 10_523, "anteil": 12.5}) - zahlen = kennzahlen.fuer_bericht(_bericht()) + b = _bericht() + b["gaeste"].append({"vmid": 107, "art": "lxc", "status": "running", "etiketten": ["mc2"]}) # der eigene zählt nicht + zahlen = kennzahlen.fuer_bericht(b) laufend = sum(1 for g in BERICHT["gaeste"] if g["status"] == "running") assert zahlen["pve"] == {"text": f"{laufend} von {len(BERICHT['gaeste'])} Gästen an"} assert zahlen["ct-105"] == {"text": "letzte Sicherung", "zeit": 1790296281} diff --git a/backend/tests/test_sicherungs_abdeckung.py b/backend/tests/test_sicherungs_abdeckung.py index 859e8d1..d5b6e36 100644 --- a/backend/tests/test_sicherungs_abdeckung.py +++ b/backend/tests/test_sicherungs_abdeckung.py @@ -121,7 +121,7 @@ def _bericht(**host) -> dict: "neueste": {k: v["zeit"] for k, v in details.items()}, "schaetzung": {"voll_am": 1887231717, "belegt": 1_517_685_571_584, "gesamt": 3_847_503_609_856}}}, - "nicht_gesichert": [104], + "nicht_gesichert": [104], # 107 (der eigene) ist gesichert "sicherung_probe": {"zeit": 1790330000, "gaeste": { "102": {"speicher": "pbs-qnap", "sicherung": 1790296227, "ok": True, "fehler": None}, "106": {"speicher": "pbs-qnap", "sicherung": 1790296281, "ok": False, @@ -130,7 +130,8 @@ def _bericht(**host) -> dict: return {"host": {**basis, **host}, "gaeste": [ {"vmid": 102, "art": "lxc", "name": "netbird", "app": {"kennung": "netbird"}}, {"vmid": 104, "art": "lxc", "name": "gitea", "app": {"kennung": "gitea"}}, - {"vmid": 106, "art": "qemu", "name": "arcane"}]} + {"vmid": 106, "art": "qemu", "name": "arcane"}, + {"vmid": 107, "art": "lxc", "name": "homelab-orchestrator", "etiketten": ["mc2"]}]} def test_abdeckung_je_geraet(): @@ -144,6 +145,7 @@ def test_abdeckung_je_geraet(): "probe": {"speicher": "pbs-qnap", "sicherung": 1790296227, "ok": True, "fehler": None, "zeit": 1790330000}} assert zeilen["vm-106"]["defekt"] == [1789864278] and zeilen["vm-106"]["probe"]["ok"] is False + assert zeilen["ct-107"]["name"] == "Homelab Orchestrator (dieser Container)" # Die letzte Prüfung von Arcane fand Beschädigtes: rot, auch wenn alles frisch gesichert ist. assert (s["stufe_frische"], s["stufe"]) == ("ok", "rot") assert s["pruefung"] == {"zuletzt": GEPRUEFT, "noetig": False} # älteste Sicherung erst 5,5 Tage alt @@ -194,7 +196,7 @@ def test_aelterer_ausfuehrer_ohne_neue_angaben(): b["host"].pop(schluessel) b["host"]["sicherungsziele"]["pbs-qnap"].pop("details") s = speicher.sicherungen(b, JETZT) - assert [g["ziel"] for g in s["ohne_auftrag"]] == ["ct-104"] # selbst ausgerechnet aus den Aufträgen + assert [g["ziel"] for g in s["ohne_auftrag"]] == ["ct-104", "ct-107"] # selbst ausgerechnet aus den Aufträgen assert s["stufe"] == "gelb" and s["probe"] is None assert all(g["geprueft"] is None and g["probe"] is None for g in s["geraete"])