fix(station): RuntimeDirectory-Race, Statusphase, off/ap_switch-Nachpruefung, Pi-Bestandskonfiguration

Fixrunde 1 zu Task 4:

- C1 (kritisch): die Unit leerte /run/ninlight-station bei jedem
  systemctl restart, weil RuntimeDirectoryPreserve fehlte - genau der
  Neustart, mit dem migrate/recovery on den Dienst hochfahren, wischte
  die eben geschriebene Modus-/Steuerdatei wieder weg, und der Server
  fiel still auf den Recovery-Default zurueck. Unit bekommt
  RuntimeDirectoryPreserve=restart, und start_and_verify() prueft nach
  dem Neustart zusaetzlich ausdruecklich nach, dass Modus und Phase noch
  stimmen.
- I1: status las die Phase aus status.json, die arm/listen (die den
  Dienst bewusst nicht neu starten) nie aktualisieren - jetzt kommt sie
  aus control.json.
- I2: off pruefte nach dem Herunterfahren nichts nach und konnte
  "Station aus" melden, waehrend ein Profil wegen haengendem
  NetworkManager weiterhin aktiv war - ap_switch() verifiziert das jetzt
  auch im Aus-Fall.
- I3: der Fehlerzweig von ap_switch (Mismatch nach dem Umschalten) war
  im bisherigen Test nie erreichbar; der nmcli-Stub kann das jetzt
  erzwingen.
- I4: neue Pflichtschluessel blockierten jeden Unterbefehl auf einem
  bereits eingerichteten Pi. setup_pi.sh ergaenzt fehlende Schluessel in
  einer bestehenden Konfiguration jetzt einzeln, statt sie unangetastet
  zu lassen; dafuer musste das Skript per bash-s-Heredocs und
  ueberschreibbaren Pfadvariablen erst testbar gemacht werden (neuer
  test_setup_pi.sh).

Dazu vier kleinere Punkte aus derselben Review: grep -Fqx statt grep -qx
fuer Profilnamen, install-Stub durch tee+chmod ersetzt (POSIX, kein
Sonderfall mehr fuer macOS), Rechtepruefung auf control.json in den
arm/listen-Testfaellen, stderr sauber von stdout getrennt in den
Warnungs-/Fehlerfaellen.
This commit is contained in:
Michael Sauer
2026-09-13 19:04:23 +02:00
parent 1d3627bacd
commit 1c077a15d0
6 changed files with 550 additions and 90 deletions
+12
View File
@@ -32,6 +32,18 @@ ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
RuntimeDirectory=ninlight-station
# Ohne dies leert systemd /run/ninlight-station bei JEDEM Stop und Neustart, nicht
# nur beim allerersten Start - und ninlight-station (das CLI) schreibt mode/
# control.json immer VOR dem "systemctl restart", mit dem migrate/recovery on den
# Dienst (neu) starten. Ohne RuntimeDirectoryPreserve=restart wischt genau dieser
# Neustart die beiden gerade geschriebenen Dateien wieder weg, bevor der neue
# Serverprozess sie lesen kann - der Dienst faellt dann still auf den
# Recovery-Default zurueck (server.py resolve_mode()/read_control()), und ein
# ausdrueckliches "migrate on --listen" wird zu "Rettungsmodus" bzw. "auto"
# (Fixrunde 1, C1). "restart" (nicht "yes") reicht: das Verzeichnis muss nur einen
# Neustart ueberleben, nicht dauerhaft bestehen bleiben, wenn der Dienst regulaer
# gestoppt wird.
RuntimeDirectoryPreserve=restart
ReadWritePaths=/run/ninlight-station
RestrictAddressFamilies=AF_INET AF_UNIX
MemoryMax=128M