diff --git a/app.py b/app.py index a0e5e49..85eaa86 100644 --- a/app.py +++ b/app.py @@ -64,6 +64,8 @@ SPIEGEL_GIT_TIMEOUT_SECONDS = 120 # Je Stufe ausgelieferte Stände: der aktuelle und zwei vorige - ein Gerät, # das seinen Stand kurz vor einer Freigabe erfahren hat, kann ihn noch holen. SPIEGEL_STAENDE_JE_STUFE = 3 +# Meldung des Agenten, wie er den Stand bezogen hat (Check-in "ansible_weg"). +ANSIBLE_WEGE = ("archiv", "git", "git-rueckfall") # Dateien, die Agent-Wechsel und Neuinstallation aus provisioning-agent holen. AGENT_FASSUNG_DATEIEN = ("agent.py", "firstboot.sh", "tuxflotte-agent.service", "tuxflotte-firstboot.service") ADMIN_TOKEN = os.environ.get("TUXFLOTTE_ADMIN_TOKEN", "") @@ -221,6 +223,10 @@ class AgentCheckinRequest(BaseModel): # ohne Musterprüfung im Modell: ein ungültiger Wert darf den Check-in # nicht ablehnen, er wird in agent_checkin() nur verworfen. agent_sha256: str | None = None + # Weg zum Ansible-Stand (ADR-0046): "archiv", "git" oder "git-rueckfall". + # Wie agent_sha256 ohne Prüfung im Modell, unbekannte Werte verwirft + # agent_checkin(). + ansible_weg: str | None = None class AgentReportEntry(BaseModel): @@ -3018,10 +3024,10 @@ def fetch_device_gruppen(device_id: str): # als Konstante statt zweimal ausgeschrieben. GERAETE_HEALTH_SPALTEN_SQL = """d.debug_mode_until, d.health_disk_used_percent, d.health_ram_used_percent, d.health_uptime_seconds, d.health_load_1m, d.health_load_5m, d.health_load_15m, - d.health_collected_at, d.agent_sha256""" + d.health_collected_at, d.agent_sha256, d.ansible_weg""" -def _health_felder_aus_row(debug_mode_until, disk, ram, uptime, load1, load5, load15, collected_at, agent_sha256) -> dict: +def _health_felder_aus_row(debug_mode_until, disk, ram, uptime, load1, load5, load15, collected_at, agent_sha256, ansible_weg) -> dict: # Live gefunden (11.09.2026): debug_mode_until wird beim Ablaufen nie # in der DB geloescht (agent_checkin() vergleicht nur zur Laufzeit # gegen "jetzt", um das Poll-Intervall zu bestimmen - das bleibt @@ -3034,6 +3040,7 @@ def _health_felder_aus_row(debug_mode_until, disk, ram, uptime, load1, load5, lo return { "debug_mode_until": debug_mode_until.isoformat() if ist_noch_aktiv else None, "agent_sha256": agent_sha256, + "ansible_weg": ansible_weg, "health": { "disk_used_percent": disk, "ram_used_percent": ram, @@ -7350,7 +7357,8 @@ def agent_checkin( health_load_5m = CASE WHEN %(hat_health)s THEN %(load5)s ELSE health_load_5m END, health_load_15m = CASE WHEN %(hat_health)s THEN %(load15)s ELSE health_load_15m END, health_collected_at = CASE WHEN %(hat_health)s THEN %(jetzt)s ELSE health_collected_at END, - agent_sha256 = COALESCE(%(agent_sha256)s, agent_sha256) + agent_sha256 = COALESCE(%(agent_sha256)s, agent_sha256), + ansible_weg = COALESCE(%(ansible_weg)s, ansible_weg) WHERE id = %(device_id)s RETURNING debug_mode_until, hostname """, @@ -7368,6 +7376,7 @@ def agent_checkin( if payload.agent_sha256 and re.fullmatch(r"[0-9a-f]{64}", payload.agent_sha256) else None ), + "ansible_weg": payload.ansible_weg if payload.ansible_weg in ANSIBLE_WEGE else None, "device_id": payload.device_id, }, ) diff --git a/migrations/0068_ansible_weg.sql b/migrations/0068_ansible_weg.sql new file mode 100644 index 0000000..3f35c55 --- /dev/null +++ b/migrations/0068_ansible_weg.sql @@ -0,0 +1,11 @@ +BEGIN; + +-- Weg, über den das Gerät seinen Ansible-Stand bezogen hat (21.10.2026, +-- platform-docs ADR-0046 Schritt 2): "archiv" (von anode), "git" (kein +-- Stand vom Server) oder "git-rueckfall" (Archiv-Weg gescheitert). Vor dem +-- Schließen von Gitea müssen alle Geräte "archiv" melden. NULL = Agent +-- älter als diese Meldung. + +ALTER TABLE devices ADD COLUMN ansible_weg TEXT; + +COMMIT;