homelab: eigener Container nicht in der Geraeteliste, Geheimnis beim Einrichten richtig anstossen, Deploy zieht den Homelab-Teil mit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-24 19:01:20 +02:00
co-authored by Claude Opus 5.5
parent b452b5e672
commit 39320b446d
5 changed files with 37 additions and 4 deletions
+3 -1
View File
@@ -24,6 +24,7 @@ from services.homelab import apps, arcane, kanal
BERICHT_ALT_S = 30 * 60 BERICHT_ALT_S = 30 * 60
LISTEN_ALT_S = 14 * 24 * 3600 LISTEN_ALT_S = 14 * 24 * 3600
EIGENES_ETIKETT = "mc2"
ERREICHBAR_CACHE_S = 60 ERREICHBAR_CACHE_S = 60
_erreichbar_cache: dict[str, tuple[float, bool]] = {} _erreichbar_cache: dict[str, tuple[float, bool]] = {}
@@ -217,7 +218,8 @@ def ziele() -> dict:
return {"ziele": [], "bericht": None, "ausfuehrer": ausfuehrer} return {"ziele": [], "bericht": None, "ausfuehrer": ausfuehrer}
b = eingang["bericht"] b = eingang["bericht"]
liste = [_host_ziel(b.get("host") or {})] liste = [_host_ziel(b.get("host") or {})]
liste += [_gast_ziel(g, jetzt) for g in b.get("gaeste") or []] # Der Container des Orchestrators selbst (Etikett „mc2“) ist kein Gerät, das er pflegt.
liste += [_gast_ziel(g, jetzt) for g in b.get("gaeste") or [] if EIGENES_ETIKETT not in (g.get("etiketten") or [])]
for z in liste: for z in liste:
z.geprueft = eingang["empfangen"] z.geprueft = eingang["empfangen"]
return {"ziele": [z.als_dict() for z in liste], return {"ziele": [z.als_dict() for z in liste],
+8
View File
@@ -289,3 +289,11 @@ def test_ausfuehrer_nur_lesen(monkeypatch):
assert antwort["code"] == 2 and "Nur-Lesen" in antwort["text"] and ausgefuehrt == [] assert antwort["code"] == 2 and "Nur-Lesen" in antwort["text"] and ausgefuehrt == []
monkeypatch.setattr(a, "bericht", lambda: {"gaeste": []}) monkeypatch.setattr(a, "bericht", lambda: {"gaeste": []})
assert a.ausfuehren({"aktion": "bericht", "parameter": {}})["code"] == 0 assert a.ausfuehren({"aktion": "bericht", "parameter": {}})["code"] == 0
def test_eigener_container_erscheint_nicht(daten):
bericht = json.loads(json.dumps(BERICHT))
bericht["gaeste"].append({"vmid": 107, "art": "lxc", "name": "homelab-orchestrator", "status": "running",
"etiketten": ["mc2"], "erlaubt": False, "ip": "192.168.178.31"})
kanal.bericht_speichern(bericht)
assert "ct-107" not in {z["id"] for z in inventar.ziele()["ziele"]}
+19
View File
@@ -174,6 +174,25 @@ stufe2() {
trap - ERR trap - ERR
echo "$(date -Is) $neu (vorher ${vorher:0:7})" >> "$DEPLOY_LOG" 2>/dev/null || true echo "$(date -Is) $neu (vorher ${vorher:0:7})" >> "$DEPLOY_LOG" 2>/dev/null || true
echo "✅ Deploy $neu ist live (vorher ${vorher:0:7})." echo "✅ Deploy $neu ist live (vorher ${vorher:0:7})."
homelab_mitziehen
}
# 8. Den Homelab-Teil gleich mitziehen (seit 24.09.2026): Ist ein Partner eingerichtet (box-partner.sh legt
# partner.conf an), bekommt sein Container denselben Stand — sonst liefen beide Instanzen auseinander.
# Scheitert das, bleibt die Box trotzdem live; es gibt eine dringende Meldung. MC_DEPLOY_OHNE_HOMELAB=1 lässt es aus.
homelab_mitziehen() {
local conf="$HOME/.config/systemd/user/mission-control-2.service.d/partner.conf" ziel
[ "${MC_DEPLOY_OHNE_HOMELAB:-0}" = "1" ] && return 0
ziel="$(grep -o 'MC_PARTNER_URL=http://[0-9.]*' "$conf" 2>/dev/null | head -n 1 | cut -d/ -f3)"
[ -n "$ziel" ] || return 0
echo "Ziehe den Homelab-Teil ($ziel) nach…"
if bash deploy/homelab/ausrollen.sh "$ziel" > /tmp/mc2-homelab-ausrollen.log 2>&1; then
echo "✅ Homelab-Teil ($ziel) hat denselben Stand."
else
echo "✗ Homelab-Teil ($ziel) ließ sich nicht aktualisieren (/tmp/mc2-homelab-ausrollen.log)."
bash deploy/notify.sh -d -s "[Alarm] Deploy" \
"Die Box ist auf dem neuen Stand, der Homelab-Teil ($ziel) aber nicht — Protokoll: /tmp/mc2-homelab-ausrollen.log." || true
fi
} }
# Beides in Funktionen und ein exit direkt dahinter: bash liest ein Skript häppchenweise, und # Beides in Funktionen und ein exit direkt dahinter: bash liest ein Skript häppchenweise, und
+3 -2
View File
@@ -31,6 +31,7 @@ for _ in $(seq 1 20); do
sleep 1 sleep 1
done done
curl -sf -m 3 http://127.0.0.1:9001/api/health && echo curl -sf -m 3 http://127.0.0.1:9001/api/health && echo
# Das gemeinsame Geheimnis für den Ausführer entsteht beim ersten Abruf (0600, Nutzer mc2). # Das gemeinsame Geheimnis für den Ausführer entsteht beim ersten Zugriff mit Kopfzeile (0600, Nutzer mc2);
curl -sf -m 5 http://127.0.0.1:9001/api/homelab/ausfuehrer >/dev/null || true # die Antwort ist 403, gewollt.
curl -s -o /dev/null -m 5 -H 'X-MC2-Ausfuehrer: erzeugen' http://127.0.0.1:9001/api/homelab/ausfuehrer/auftrag || true
echo "✅ Homelab-Teil läuft." echo "✅ Homelab-Teil läuft."
+4 -1
View File
@@ -127,7 +127,10 @@ systemd-Einheiten und überleben den Neustart von MC2. Dann den alten Stand merk
7. Neustart von `mc2-gateway`, `mission-control-2` und `mc2-steward`, dann bis zu 60 s Nachprüfung: `/api/health`, 7. Neustart von `mc2-gateway`, `mission-control-2` und `mc2-steward`, dann bis zu 60 s Nachprüfung: `/api/health`,
`/gw/health`, Steward aktiv. `/gw/health`, Steward aktiv.
Erfolg: eine Zeile in `/srv/models/mc2-deploy.log` und „Deploy <commit> ist live". Scheitert ein Schritt: Erfolg: eine Zeile in `/srv/models/mc2-deploy.log` und „Deploy <commit> ist live". Danach (Schritt 8) zieht der Deploy den
Homelab-Teil mit, sobald `box-partner.sh` einen Partner eingerichtet hat: `deploy/homelab/ausrollen.sh` mit der IP aus
`partner.conf`. Scheitert das, bleibt die Box live und es kommt „[Alarm] Deploy"; `MC_DEPLOY_OHNE_HOMELAB=1` lässt
den Schritt aus. Scheitert ein Schritt:
`git reset --hard` auf den alten Stand, llama-swap-Config zurück (falls ersetzt), Dienste neu, Zeile `GESCHEITERT` im `git reset --hard` auf den alten Stand, llama-swap-Config zurück (falls ersetzt), Dienste neu, Zeile `GESCHEITERT` im
Log und die dringende Meldung „[Alarm] Deploy". Log und die dringende Meldung „[Alarm] Deploy".