feat(station): Tasterdienst per deploy.sh/setup_pi.sh ausliefern
This commit is contained in:
@@ -56,9 +56,10 @@ Bedienzustand nach `/run/ninlight-button/ui.json`; der Anzeigedienst liest ihn u
|
|||||||
zeichnet. Ausgeführt wird ausschließlich über das CLI.
|
zeichnet. Ausgeführt wird ausschließlich über das CLI.
|
||||||
|
|
||||||
Dienst und Unit liegen in `tools/station/button/` bzw.
|
Dienst und Unit liegen in `tools/station/button/` bzw.
|
||||||
`tools/station/ninlight-button.service` — das Ausliefern und Einrichten (`deploy.sh`,
|
`tools/station/ninlight-button.service`. `setup_pi.sh` installiert, aktiviert und startet
|
||||||
`setup_pi.sh`) kommt in einem eigenen Durchgang, bis dahin installiert der Aufsetzweg den
|
den Tasterdienst wie den Anzeigedienst; `deploy.sh` liefert `button/` bei jedem Deploy mit
|
||||||
Tasterdienst noch nicht.
|
aus. Ein fehlgeschlagenes Aktivieren/Starten ist dabei nur eine Warnung — eine Station
|
||||||
|
ohne Taster muss vollständig benutzbar bleiben.
|
||||||
|
|
||||||
SSID und Passwort stehen in `/etc/ninlight-station.conf` auf dem Pi und müssen zu den
|
SSID und Passwort stehen in `/etc/ninlight-station.conf` auf dem Pi und müssen zu den
|
||||||
Build-Parametern `NINLIGHT_RECOVERY_SSID` und `NINLIGHT_RECOVERY_PASSWORD` aus
|
Build-Parametern `NINLIGHT_RECOVERY_SSID` und `NINLIGHT_RECOVERY_PASSWORD` aus
|
||||||
|
|||||||
+23
-2
@@ -203,13 +203,17 @@ echo "== uebertragen =="
|
|||||||
# -e: rsync soll fuer den Transport zum Pi denselben ssh wie oben benutzen.
|
# -e: rsync soll fuer den Transport zum Pi denselben ssh wie oben benutzen.
|
||||||
rsync -a -c --delete -e "$SSH_BIN" "$STAGE/" "$HOST:/tmp/ninlight-images/"
|
rsync -a -c --delete -e "$SSH_BIN" "$STAGE/" "$HOST:/tmp/ninlight-images/"
|
||||||
rsync -a -e "$SSH_BIN" "$HERE/server.py" "$HERE/products.py" "$HERE/ninlight-station" \
|
rsync -a -e "$SSH_BIN" "$HERE/server.py" "$HERE/products.py" "$HERE/ninlight-station" \
|
||||||
"$HERE/ninlight-station.service" "$HERE/ninlight-display.service" "$HOST:/tmp/"
|
"$HERE/ninlight-station.service" "$HERE/ninlight-display.service" "$HERE/ninlight-button.service" \
|
||||||
|
"$HOST:/tmp/"
|
||||||
# Das Anzeigeverzeichnis als Ganzes (render.py, display.py, epdconfig.py, die beiden
|
# Das Anzeigeverzeichnis als Ganzes (render.py, display.py, epdconfig.py, die beiden
|
||||||
# uebernommenen Panel-Treiber und HERKUNFT.md - der Herkunftsnachweis gehoert mit auf
|
# uebernommenen Panel-Treiber und HERKUNFT.md - der Herkunftsnachweis gehoert mit auf
|
||||||
# den Pi, nicht nur ins Repo). --delete gilt hier nur fuer die fluechtige Ablage unter
|
# den Pi, nicht nur ins Repo). --delete gilt hier nur fuer die fluechtige Ablage unter
|
||||||
# /tmp; __pycache__ bleibt draussen, sonst landen die .pyc dieses Rechners (andere
|
# /tmp; __pycache__ bleibt draussen, sonst landen die .pyc dieses Rechners (andere
|
||||||
# Python-Version als auf dem Pi) im Zielverzeichnis und bleiben dort liegen.
|
# Python-Version als auf dem Pi) im Zielverzeichnis und bleiben dort liegen.
|
||||||
rsync -a -c --delete --exclude=__pycache__ -e "$SSH_BIN" "$HERE/display/" "$HOST:/tmp/ninlight-display/"
|
rsync -a -c --delete --exclude=__pycache__ -e "$SSH_BIN" "$HERE/display/" "$HOST:/tmp/ninlight-display/"
|
||||||
|
# Das Tasterverzeichnis genauso wie das Anzeigeverzeichnis: als Ganzes, ohne
|
||||||
|
# __pycache__ dieses Rechners.
|
||||||
|
rsync -a -c --delete --exclude=__pycache__ -e "$SSH_BIN" "$HERE/button/" "$HOST:/tmp/ninlight-button/"
|
||||||
# Pfade als Variablen mit Default: so kann ein Test die Installation gegen
|
# Pfade als Variablen mit Default: so kann ein Test die Installation gegen
|
||||||
# ein Sandbox-Verzeichnis statt gegen echte Systempfade laufen lassen.
|
# ein Sandbox-Verzeichnis statt gegen echte Systempfade laufen lassen.
|
||||||
"$SSH_BIN" "$HOST" bash -s -- "$FULL_SYNC" "$MIGRATE_COMPLETE" <<'REMOTE'
|
"$SSH_BIN" "$HOST" bash -s -- "$FULL_SYNC" "$MIGRATE_COMPLETE" <<'REMOTE'
|
||||||
@@ -220,6 +224,7 @@ ROOT_DIR=${NINLIGHT_STATION_ROOT:-/opt/ninlight-station}
|
|||||||
BIN_PATH=${NINLIGHT_STATION_BIN:-/usr/local/bin/ninlight-station}
|
BIN_PATH=${NINLIGHT_STATION_BIN:-/usr/local/bin/ninlight-station}
|
||||||
UNIT_PATH=${NINLIGHT_STATION_UNIT:-/etc/systemd/system/ninlight-station.service}
|
UNIT_PATH=${NINLIGHT_STATION_UNIT:-/etc/systemd/system/ninlight-station.service}
|
||||||
DISPLAY_UNIT_PATH=${NINLIGHT_DISPLAY_UNIT:-/etc/systemd/system/ninlight-display.service}
|
DISPLAY_UNIT_PATH=${NINLIGHT_DISPLAY_UNIT:-/etc/systemd/system/ninlight-display.service}
|
||||||
|
BUTTON_UNIT_PATH=${NINLIGHT_BUTTON_UNIT:-/etc/systemd/system/ninlight-button.service}
|
||||||
|
|
||||||
sudo install -d -m 0755 "$ROOT_DIR/images"
|
sudo install -d -m 0755 "$ROOT_DIR/images"
|
||||||
if [ "$FULL_SYNC" -eq 1 ]; then
|
if [ "$FULL_SYNC" -eq 1 ]; then
|
||||||
@@ -347,8 +352,13 @@ sudo install -m 0644 /tmp/ninlight-station.service "$UNIT_PATH"
|
|||||||
sudo install -d -m 0755 "$ROOT_DIR/display"
|
sudo install -d -m 0755 "$ROOT_DIR/display"
|
||||||
sudo rsync -a -c --delete /tmp/ninlight-display/ "$ROOT_DIR/display/"
|
sudo rsync -a -c --delete /tmp/ninlight-display/ "$ROOT_DIR/display/"
|
||||||
sudo install -m 0644 /tmp/ninlight-display.service "$DISPLAY_UNIT_PATH"
|
sudo install -m 0644 /tmp/ninlight-display.service "$DISPLAY_UNIT_PATH"
|
||||||
|
# Taster: dieselbe Begruendung wie bei der Anzeige - button/ ist reiner Code aus dem
|
||||||
|
# Repo, es gibt keinen Bestand, der einen Deploy ueberleben muesste.
|
||||||
|
sudo install -d -m 0755 "$ROOT_DIR/button"
|
||||||
|
sudo rsync -a -c --delete /tmp/ninlight-button/ "$ROOT_DIR/button/"
|
||||||
|
sudo install -m 0644 /tmp/ninlight-button.service "$BUTTON_UNIT_PATH"
|
||||||
rm -rf /tmp/ninlight-images /tmp/server.py /tmp/products.py /tmp/ninlight-station /tmp/ninlight-station.service \
|
rm -rf /tmp/ninlight-images /tmp/server.py /tmp/products.py /tmp/ninlight-station /tmp/ninlight-station.service \
|
||||||
/tmp/ninlight-display /tmp/ninlight-display.service
|
/tmp/ninlight-display /tmp/ninlight-display.service /tmp/ninlight-button /tmp/ninlight-button.service
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
if systemctl is-active --quiet ninlight-station; then
|
if systemctl is-active --quiet ninlight-station; then
|
||||||
if sudo systemctl restart ninlight-station; then
|
if sudo systemctl restart ninlight-station; then
|
||||||
@@ -374,6 +384,17 @@ if systemctl is-active --quiet ninlight-display; then
|
|||||||
else
|
else
|
||||||
echo " Anzeigedienst laeuft nicht"
|
echo " Anzeigedienst laeuft nicht"
|
||||||
fi
|
fi
|
||||||
|
# Taster: dieselbe weiche Behandlung wie die Anzeige (siehe deren Begruendung oben) - er
|
||||||
|
# ist nirgends Voraussetzung fuer eine Migration, ein Deploy darf daran nicht scheitern.
|
||||||
|
if systemctl is-active --quiet ninlight-button; then
|
||||||
|
if sudo systemctl restart ninlight-button; then
|
||||||
|
echo " Tasterdienst neu gestartet"
|
||||||
|
else
|
||||||
|
echo " Warnung: Tasterdienst lief, Neustart ist fehlgeschlagen - journalctl -u ninlight-button" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " Tasterdienst laeuft nicht"
|
||||||
|
fi
|
||||||
REMOTE
|
REMOTE
|
||||||
|
|
||||||
echo "fertig."
|
echo "fertig."
|
||||||
|
|||||||
@@ -921,6 +921,9 @@ usage() {
|
|||||||
echo " display off Anzeigedienst dauerhaft stoppen und das Panel leeren. 'on'/'off'" >&2
|
echo " display off Anzeigedienst dauerhaft stoppen und das Panel leeren. 'on'/'off'" >&2
|
||||||
echo " der Station brauchen das nicht - der Anzeigedienst laeuft" >&2
|
echo " der Station brauchen das nicht - der Anzeigedienst laeuft" >&2
|
||||||
echo " unabhaengig davon durch und zeichnet den Zustand selbst." >&2
|
echo " unabhaengig davon durch und zeichnet den Zustand selbst." >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo " Taster (GPIO23): kurzer Druck oeffnet am Geraet ein Menue ueber genau diese" >&2
|
||||||
|
echo " Unterbefehle, 3 s gehalten brechen eine laufende Migration/Rettung ab." >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
_cmd=${1:-}
|
_cmd=${1:-}
|
||||||
|
|||||||
@@ -90,15 +90,20 @@ echo "== Server, CLI und Units installieren =="
|
|||||||
"$SSH_BIN" "$HOST" bash -s <<'REMOTE'
|
"$SSH_BIN" "$HOST" bash -s <<'REMOTE'
|
||||||
set -e
|
set -e
|
||||||
STAGE_DIR=${NINLIGHT_STAGE_DIR:-/tmp}
|
STAGE_DIR=${NINLIGHT_STAGE_DIR:-/tmp}
|
||||||
rm -rf "$STAGE_DIR/ninlight-display"
|
rm -rf "$STAGE_DIR/ninlight-display" "$STAGE_DIR/ninlight-button"
|
||||||
REMOTE
|
REMOTE
|
||||||
"$SCP_BIN" -q "$HERE/server.py" "$HERE/products.py" "$HERE/ninlight-station" \
|
"$SCP_BIN" -q "$HERE/server.py" "$HERE/products.py" "$HERE/ninlight-station" \
|
||||||
"$HERE/ninlight-station.service" "$HERE/ninlight-display.service" "$HOST:$STAGE_DIR/"
|
"$HERE/ninlight-station.service" "$HERE/ninlight-display.service" "$HERE/ninlight-button.service" \
|
||||||
|
"$HOST:$STAGE_DIR/"
|
||||||
# Das Anzeigeverzeichnis als Ganzes: render.py, display.py, epdconfig.py, die beiden
|
# Das Anzeigeverzeichnis als Ganzes: render.py, display.py, epdconfig.py, die beiden
|
||||||
# uebernommenen Panel-Treiber und HERKUNFT.md (der Herkunftsnachweis gehoert mit auf den
|
# uebernommenen Panel-Treiber und HERKUNFT.md (der Herkunftsnachweis gehoert mit auf den
|
||||||
# Pi). "scp -r" statt rsync, weil setup_pi.sh - anders als deploy.sh - ausdruecklich nur
|
# Pi). "scp -r" statt rsync, weil setup_pi.sh - anders als deploy.sh - ausdruecklich nur
|
||||||
# ssh/scp voraussetzt; __pycache__ wird auf der Gegenseite weggeraeumt (unten).
|
# ssh/scp voraussetzt; __pycache__ wird auf der Gegenseite weggeraeumt (unten).
|
||||||
"$SCP_BIN" -q -r "$HERE/display" "$HOST:$STAGE_DIR/ninlight-display"
|
"$SCP_BIN" -q -r "$HERE/display" "$HOST:$STAGE_DIR/ninlight-display"
|
||||||
|
# Das Tasterverzeichnis genauso: als Ganzes, mit demselben "vorher aufraeumen"-Schutz
|
||||||
|
# gegen ein "scp -r" auf ein bereits vorhandenes Ziel (siehe Kommentar oben zu
|
||||||
|
# ninlight-display).
|
||||||
|
"$SCP_BIN" -q -r "$HERE/button" "$HOST:$STAGE_DIR/ninlight-button"
|
||||||
# Pfade als Variablen mit Default (wie in deploy.sh): so kann ein Test die
|
# Pfade als Variablen mit Default (wie in deploy.sh): so kann ein Test die
|
||||||
# Installation gegen ein Sandbox-Verzeichnis statt gegen echte Systempfade laufen
|
# Installation gegen ein Sandbox-Verzeichnis statt gegen echte Systempfade laufen
|
||||||
# lassen.
|
# lassen.
|
||||||
@@ -109,6 +114,7 @@ ROOT_DIR=${NINLIGHT_STATION_ROOT:-/opt/ninlight-station}
|
|||||||
BIN_PATH=${NINLIGHT_STATION_BIN:-/usr/local/bin/ninlight-station}
|
BIN_PATH=${NINLIGHT_STATION_BIN:-/usr/local/bin/ninlight-station}
|
||||||
UNIT_PATH=${NINLIGHT_STATION_UNIT:-/etc/systemd/system/ninlight-station.service}
|
UNIT_PATH=${NINLIGHT_STATION_UNIT:-/etc/systemd/system/ninlight-station.service}
|
||||||
DISPLAY_UNIT_PATH=${NINLIGHT_DISPLAY_UNIT:-/etc/systemd/system/ninlight-display.service}
|
DISPLAY_UNIT_PATH=${NINLIGHT_DISPLAY_UNIT:-/etc/systemd/system/ninlight-display.service}
|
||||||
|
BUTTON_UNIT_PATH=${NINLIGHT_BUTTON_UNIT:-/etc/systemd/system/ninlight-button.service}
|
||||||
|
|
||||||
# Die Ablage wird in JEDEM Fall abgeraeumt, auch wenn dieser Block vorzeitig aussteigt
|
# Die Ablage wird in JEDEM Fall abgeraeumt, auch wenn dieser Block vorzeitig aussteigt
|
||||||
# (Task 6b F2, N1). Vorher stand das "rm -rf" nur am Blockende und wurde beim Abbruch
|
# (Task 6b F2, N1). Vorher stand das "rm -rf" nur am Blockende und wurde beim Abbruch
|
||||||
@@ -117,11 +123,12 @@ DISPLAY_UNIT_PATH=${NINLIGHT_DISPLAY_UNIT:-/etc/systemd/system/ninlight-display.
|
|||||||
cleanup_stage() {
|
cleanup_stage() {
|
||||||
rm -rf "$STAGE_DIR/server.py" "$STAGE_DIR/products.py" "$STAGE_DIR/ninlight-station" \
|
rm -rf "$STAGE_DIR/server.py" "$STAGE_DIR/products.py" "$STAGE_DIR/ninlight-station" \
|
||||||
"$STAGE_DIR/ninlight-station.service" "$STAGE_DIR/ninlight-display.service" \
|
"$STAGE_DIR/ninlight-station.service" "$STAGE_DIR/ninlight-display.service" \
|
||||||
"$STAGE_DIR/ninlight-display"
|
"$STAGE_DIR/ninlight-display" "$STAGE_DIR/ninlight-button.service" \
|
||||||
|
"$STAGE_DIR/ninlight-button"
|
||||||
}
|
}
|
||||||
trap cleanup_stage EXIT
|
trap cleanup_stage EXIT
|
||||||
|
|
||||||
rm -rf "$STAGE_DIR/ninlight-display/__pycache__"
|
rm -rf "$STAGE_DIR/ninlight-display/__pycache__" "$STAGE_DIR/ninlight-button/__pycache__"
|
||||||
# Harte Vorbedingung, und zwar VOR dem ersten "sudo install" (Task 6b F2, N1): ohne
|
# Harte Vorbedingung, und zwar VOR dem ersten "sudo install" (Task 6b F2, N1): ohne
|
||||||
# display.py in der Ablage hat das scp nicht geliefert, was es sollte - abgebrochen,
|
# display.py in der Ablage hat das scp nicht geliefert, was es sollte - abgebrochen,
|
||||||
# falsch verschachtelt oder gar nicht gelaufen. Die Installationsschleife weiter unten
|
# falsch verschachtelt oder gar nicht gelaufen. Die Installationsschleife weiter unten
|
||||||
@@ -134,11 +141,19 @@ rm -rf "$STAGE_DIR/ninlight-display/__pycache__"
|
|||||||
# den diese Pruefung gedacht ist, log das Skript den Bediener an. Jetzt stimmt der Satz.
|
# den diese Pruefung gedacht ist, log das Skript den Bediener an. Jetzt stimmt der Satz.
|
||||||
if [ ! -f "$STAGE_DIR/ninlight-display/display.py" ]; then
|
if [ ! -f "$STAGE_DIR/ninlight-display/display.py" ]; then
|
||||||
echo "Fehler: $STAGE_DIR/ninlight-display/display.py fehlt - die Uebertragung des Anzeigeverzeichnisses ist fehlgeschlagen." >&2
|
echo "Fehler: $STAGE_DIR/ninlight-display/display.py fehlt - die Uebertragung des Anzeigeverzeichnisses ist fehlgeschlagen." >&2
|
||||||
echo " Nichts installiert: $ROOT_DIR, $BIN_PATH und beide Units sind unveraendert. Ablage aufgeraeumt, Lauf einfach wiederholen." >&2
|
echo " Nichts installiert: $ROOT_DIR, $BIN_PATH und alle drei Units sind unveraendert. Ablage aufgeraeumt, Lauf einfach wiederholen." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Dieselbe harte Vorbedingung wie bei display.py, aus demselben Grund: ohne button.py in
|
||||||
|
# der Ablage hat das scp nicht geliefert, was es sollte, und die Installationsschleife
|
||||||
|
# unten wuerde das stillschweigend als "nichts zu tun" verbuchen.
|
||||||
|
if [ ! -f "$STAGE_DIR/ninlight-button/button.py" ]; then
|
||||||
|
echo "Fehler: $STAGE_DIR/ninlight-button/button.py fehlt - die Uebertragung des Tasterverzeichnisses ist fehlgeschlagen." >&2
|
||||||
|
echo " Nichts installiert: $ROOT_DIR, $BIN_PATH und alle drei Units sind unveraendert. Ablage aufgeraeumt, Lauf einfach wiederholen." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo install -d -m 0755 "$ROOT_DIR" "$ROOT_DIR/images" "$ROOT_DIR/display"
|
sudo install -d -m 0755 "$ROOT_DIR" "$ROOT_DIR/images" "$ROOT_DIR/display" "$ROOT_DIR/button"
|
||||||
sudo install -m 0755 "$STAGE_DIR/server.py" "$ROOT_DIR/server.py"
|
sudo install -m 0755 "$STAGE_DIR/server.py" "$ROOT_DIR/server.py"
|
||||||
sudo install -m 0644 "$STAGE_DIR/products.py" "$ROOT_DIR/products.py"
|
sudo install -m 0644 "$STAGE_DIR/products.py" "$ROOT_DIR/products.py"
|
||||||
sudo install -m 0755 "$STAGE_DIR/ninlight-station" "$BIN_PATH"
|
sudo install -m 0755 "$STAGE_DIR/ninlight-station" "$BIN_PATH"
|
||||||
@@ -165,6 +180,25 @@ for f in "$ROOT_DIR"/display/*; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
sudo install -m 0644 "$STAGE_DIR/ninlight-display.service" "$DISPLAY_UNIT_PATH"
|
sudo install -m 0644 "$STAGE_DIR/ninlight-display.service" "$DISPLAY_UNIT_PATH"
|
||||||
|
# Taster: dieselbe Behandlung wie die Anzeige - button.py ist ausfuehrbar (die Unit ruft
|
||||||
|
# es zwar ueber /usr/bin/python3 auf, von Hand pruefen laesst es sich trotzdem), der Rest
|
||||||
|
# (aktuell nichts weiter) waere importierter Code.
|
||||||
|
for f in "$STAGE_DIR"/ninlight-button/*; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
case "$(basename "$f")" in
|
||||||
|
button.py) sudo install -m 0755 "$f" "$ROOT_DIR/button/$(basename "$f")" ;;
|
||||||
|
*) sudo install -m 0644 "$f" "$ROOT_DIR/button/$(basename "$f")" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
# Dasselbe Argument wie bei display/: button/ ist reiner Code aus dem Repo.
|
||||||
|
for f in "$ROOT_DIR"/button/*; do
|
||||||
|
[ -e "$f" ] || continue
|
||||||
|
if [ ! -e "$STAGE_DIR/ninlight-button/$(basename "$f")" ]; then
|
||||||
|
sudo rm -rf "$f"
|
||||||
|
echo " veraltete Datei entfernt: button/$(basename "$f")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
sudo install -m 0644 "$STAGE_DIR/ninlight-button.service" "$BUTTON_UNIT_PATH"
|
||||||
# Das Aufraeumen der Ablage macht der EXIT-Trap oben - auf beiden Wegen aus diesem Block.
|
# Das Aufraeumen der Ablage macht der EXIT-Trap oben - auf beiden Wegen aus diesem Block.
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
echo " installiert"
|
echo " installiert"
|
||||||
@@ -335,6 +369,21 @@ sudo systemctl restart ninlight-display.service >/dev/null 2>&1 || \
|
|||||||
echo " Anzeigedienst aktiviert"
|
echo " Anzeigedienst aktiviert"
|
||||||
REMOTE
|
REMOTE
|
||||||
|
|
||||||
|
echo "== Tasterdienst aktivieren =="
|
||||||
|
# Dieselbe weiche Behandlung wie die Anzeige, aus demselben Grund: der Taster ist
|
||||||
|
# nirgends Voraussetzung. Fehlt gpiozero, fehlt der Taster oder ist GPIO23 belegt,
|
||||||
|
# beendet sich button.py still mit 0 (siehe dessen Modul-Docstring) - ein
|
||||||
|
# fehlgeschlagenes enable/start darf setup_pi.sh trotzdem nicht abbrechen, denn eine
|
||||||
|
# Station ohne Taster muss vollstaendig benutzbar bleiben.
|
||||||
|
"$SSH_BIN" "$HOST" bash -s <<'REMOTE'
|
||||||
|
set -e
|
||||||
|
sudo systemctl enable ninlight-button.service >/dev/null 2>&1 || \
|
||||||
|
echo " Warnung: 'systemctl enable ninlight-button' fehlgeschlagen - der Taster startet nach einem Neustart des Pi nicht von allein mit" >&2
|
||||||
|
sudo systemctl restart ninlight-button.service >/dev/null 2>&1 || \
|
||||||
|
echo " Warnung: 'systemctl restart ninlight-button' fehlgeschlagen - journalctl -u ninlight-button" >&2
|
||||||
|
echo " Tasterdienst aktiviert"
|
||||||
|
REMOTE
|
||||||
|
|
||||||
echo "== NetworkManager-Profile =="
|
echo "== NetworkManager-Profile =="
|
||||||
# Zwei Dinge, die man an einer echten Lampenstation nicht falsch machen darf:
|
# Zwei Dinge, die man an einer echten Lampenstation nicht falsch machen darf:
|
||||||
# - /etc/ninlight-station.conf ist 0600 root:root (das Passwort soll nicht
|
# - /etc/ninlight-station.conf ist 0600 root:root (das Passwort soll nicht
|
||||||
@@ -486,4 +535,7 @@ Naechste Schritte:
|
|||||||
tools/station/deploy.sh <pi-host> Images ausliefern
|
tools/station/deploy.sh <pi-host> Images ausliefern
|
||||||
ssh <pi-host> ninlight-station on Station einschalten
|
ssh <pi-host> ninlight-station on Station einschalten
|
||||||
ssh <pi-host> ninlight-station off wieder ausschalten (nicht vergessen)
|
ssh <pi-host> ninlight-station off wieder ausschalten (nicht vergessen)
|
||||||
|
|
||||||
|
Der Taster auf GPIO23 ist mit eingerichtet: kurzer Druck oeffnet das Menue am Geraet,
|
||||||
|
3 s gehalten brechen eine laufende Migration/Rettung ab.
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ setup_sandbox() {
|
|||||||
echo "# dummy" >"$sandbox/tools/station/ninlight-station"
|
echo "# dummy" >"$sandbox/tools/station/ninlight-station"
|
||||||
echo "# dummy" >"$sandbox/tools/station/ninlight-station.service"
|
echo "# dummy" >"$sandbox/tools/station/ninlight-station.service"
|
||||||
echo "# dummy" >"$sandbox/tools/station/ninlight-display.service"
|
echo "# dummy" >"$sandbox/tools/station/ninlight-display.service"
|
||||||
|
echo "# dummy" >"$sandbox/tools/station/ninlight-button.service"
|
||||||
# display/ wird ECHT kopiert, nicht durch Attrappen ersetzt: die Zusage aus Task 6b
|
# display/ wird ECHT kopiert, nicht durch Attrappen ersetzt: die Zusage aus Task 6b
|
||||||
# ist, dass die beiden uebernommenen Panel-Treiber UND der Herkunftsnachweis
|
# ist, dass die beiden uebernommenen Panel-Treiber UND der Herkunftsnachweis
|
||||||
# HERKUNFT.md mit auf den Pi gehen. Mit selbst erfundenen Dateinamen im Sandbox-Repo
|
# HERKUNFT.md mit auf den Pi gehen. Mit selbst erfundenen Dateinamen im Sandbox-Repo
|
||||||
@@ -62,6 +63,11 @@ setup_sandbox() {
|
|||||||
# darf nicht mit uebertragen werden.
|
# darf nicht mit uebertragen werden.
|
||||||
mkdir -p "$sandbox/tools/station/display/__pycache__"
|
mkdir -p "$sandbox/tools/station/display/__pycache__"
|
||||||
echo "pyc-muell" >"$sandbox/tools/station/display/__pycache__/render.cpython-999.pyc"
|
echo "pyc-muell" >"$sandbox/tools/station/display/__pycache__/render.cpython-999.pyc"
|
||||||
|
# button/ ebenso echt kopiert, gleiches Argument wie bei display/ oben.
|
||||||
|
cp -R "$STATION_DIR/button" "$sandbox/tools/station/button"
|
||||||
|
rm -rf "$sandbox/tools/station/button/__pycache__"
|
||||||
|
mkdir -p "$sandbox/tools/station/button/__pycache__"
|
||||||
|
echo "pyc-muell" >"$sandbox/tools/station/button/__pycache__/button.cpython-999.pyc"
|
||||||
|
|
||||||
# Fake nl_mkimage.py --verify: verhaelt sich wie das echte Tool (eine Zeile
|
# Fake nl_mkimage.py --verify: verhaelt sich wie das echte Tool (eine Zeile
|
||||||
# "<geraet> <version> <bytes>" auf stdout bei Erfolg, Exit 0; eine Zeile auf
|
# "<geraet> <version> <bytes>" auf stdout bei Erfolg, Exit 0; eine Zeile auf
|
||||||
@@ -137,6 +143,13 @@ case "\$*" in
|
|||||||
*) exit 0 ;;
|
*) exit 0 ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
*ninlight-button*)
|
||||||
|
case "\$1" in
|
||||||
|
is-active) exit "\${FAKE_BUTTON_ACTIVE_EXIT:-1}" ;;
|
||||||
|
restart) exit "\${FAKE_BUTTON_RESTART_EXIT:-0}" ;;
|
||||||
|
*) exit 0 ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
case "\$1" in
|
case "\$1" in
|
||||||
is-active) exit "\${FAKE_SYSTEMCTL_ACTIVE_EXIT:-1}" ;;
|
is-active) exit "\${FAKE_SYSTEMCTL_ACTIVE_EXIT:-1}" ;;
|
||||||
@@ -171,6 +184,7 @@ run_deploy() {
|
|||||||
NINLIGHT_STATION_BIN="$SANDBOX_STATE/usr/local/bin/ninlight-station" \
|
NINLIGHT_STATION_BIN="$SANDBOX_STATE/usr/local/bin/ninlight-station" \
|
||||||
NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \
|
NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \
|
||||||
NINLIGHT_DISPLAY_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-display.service" \
|
NINLIGHT_DISPLAY_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-display.service" \
|
||||||
|
NINLIGHT_BUTTON_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-button.service" \
|
||||||
NINLIGHT_SIGN_DIR="$sign_dir" \
|
NINLIGHT_SIGN_DIR="$sign_dir" \
|
||||||
"$sandbox/tools/station/deploy.sh" "$@"
|
"$sandbox/tools/station/deploy.sh" "$@"
|
||||||
}
|
}
|
||||||
@@ -1056,6 +1070,48 @@ RC=$?
|
|||||||
set -e
|
set -e
|
||||||
[ "$RC" -ne 0 ] && pass "Exit-Code != 0 beim Hauptdienst" || fail "Exit-Code 0 - ein toter Hauptdienst ginge unbemerkt durch: $OUT"
|
[ "$RC" -ne 0 ] && pass "Exit-Code != 0 beim Hauptdienst" || fail "Exit-Code 0 - ein toter Hauptdienst ginge unbemerkt durch: $OUT"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 26: deploy.sh liefert das Tasterverzeichnis und die Taster-Unit mit aus ==="
|
||||||
|
SANDBOX="$TMPROOT/s26"; STUBBIN="$TMPROOT/bin26"; LOG="$TMPROOT/s26.log"; SANDBOX_STATE="$TMPROOT/s26-state"
|
||||||
|
setup_sandbox "$SANDBOX"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
mkdir -p "$SANDBOX/build/foo"
|
||||||
|
echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img"
|
||||||
|
# Bestand auf dem "Pi": eine Datei, die es im Repo nicht mehr gibt - muss beim Deploy
|
||||||
|
# verschwinden (dasselbe Argument wie bei display/ in Szenario 22).
|
||||||
|
mkdir -p "$SANDBOX_STATE/opt/ninlight-station/button"
|
||||||
|
echo "alt" >"$SANDBOX_STATE/opt/ninlight-station/button/veraltet.py"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(run_deploy "$SANDBOX" pi-test 2>&1)
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
|
||||||
|
BTN="$SANDBOX_STATE/opt/ninlight-station/button"
|
||||||
|
[ -f "$BTN/button.py" ] && pass "button/button.py ausgeliefert" || fail "button/button.py fehlt unter $BTN"
|
||||||
|
[ -f "$SANDBOX_STATE/etc/systemd/system/ninlight-button.service" ] && pass "ninlight-button.service ausgeliefert" || fail "Taster-Unit fehlt - sie waere weiter toter Text im Repo"
|
||||||
|
[ ! -f "$BTN/veraltet.py" ] && pass "im Repo geloeschte Datei verschwindet auch auf dem Pi (--delete)" || fail "veraltet.py blieb im Zielverzeichnis liegen"
|
||||||
|
[ ! -d "$BTN/__pycache__" ] && pass "kein __pycache__ dieses Rechners auf dem Pi gelandet" || fail "__pycache__ wurde mit uebertragen: $(ls "$BTN/__pycache__")"
|
||||||
|
echo "$OUT" | grep -q "Tasterdienst laeuft nicht" && pass "Deploy meldet, dass der Tasterdienst nicht laeuft" || fail "Ausgabe erwaehnt den Tasterdienst nicht: $OUT"
|
||||||
|
[ ! -d /tmp/ninlight-button ] && pass "die fluechtige Ablage /tmp/ninlight-button wurde aufgeraeumt" || fail "/tmp/ninlight-button blieb liegen"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 27: ein fehlgeschlagener Neustart des TASTERdienstes ist kein Deploy-Fehler ==="
|
||||||
|
SANDBOX="$TMPROOT/s27"; STUBBIN="$TMPROOT/bin27"; LOG="$TMPROOT/s27.log"; SANDBOX_STATE="$TMPROOT/s27-state"
|
||||||
|
setup_sandbox "$SANDBOX"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
mkdir -p "$SANDBOX/build/foo"
|
||||||
|
echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(FAKE_BUTTON_ACTIVE_EXIT=0 FAKE_BUTTON_RESTART_EXIT=1 run_deploy "$SANDBOX" pi-test 2>"$TMPROOT/s27.err")
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
ERR=$(cat "$TMPROOT/s27.err")
|
||||||
|
[ "$RC" -eq 0 ] && pass "Exit-Code 0 trotz fehlgeschlagenem Taster-Neustart" || fail "Exit-Code $RC - der Deploy wurde wegen des Tasters rot: $ERR"
|
||||||
|
echo "$ERR" | grep -q "Warnung" && pass "Warnung (keine Fehlermeldung) auf stderr" || fail "keine Warnung auf stderr: $ERR"
|
||||||
|
[ -f "$SANDBOX_STATE/opt/ninlight-station/server.py" ] && pass "der Deploy selbst lief vollstaendig durch" || fail "server.py fehlt - der Deploy brach ab"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
if [ "$FAILED" -eq 0 ]; then
|
if [ "$FAILED" -eq 0 ]; then
|
||||||
echo "Alle Tests bestanden."
|
echo "Alle Tests bestanden."
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ echo "STUB scp \$*" >>"$log"
|
|||||||
for a in "\$@"; do
|
for a in "\$@"; do
|
||||||
case "\$a" in
|
case "\$a" in
|
||||||
*ninlight-display) [ -n "\${FAKE_SCP_SKIP_DIR:-}" ] && exit 0 ;;
|
*ninlight-display) [ -n "\${FAKE_SCP_SKIP_DIR:-}" ] && exit 0 ;;
|
||||||
|
*ninlight-button) [ -n "\${FAKE_SCP_SKIP_BUTTON_DIR:-}" ] && exit 0 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
args=()
|
args=()
|
||||||
@@ -141,7 +142,19 @@ EOF
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
echo "STUB systemctl \$*" >>"$log"
|
echo "STUB systemctl \$*" >>"$log"
|
||||||
# Testschalter: laesst "enable"/"restart" scheitern (beides darf setup_pi.sh nur
|
# Testschalter: laesst "enable"/"restart" scheitern (beides darf setup_pi.sh nur
|
||||||
# warnen lassen, nie abbrechen).
|
# warnen lassen, nie abbrechen). Der Taster hat eigene Schalter (FAKE_BUTTON_*), damit
|
||||||
|
# ein Szenario NUR ihn scheitern lassen kann, ohne die Anzeige mitzureissen - sonst
|
||||||
|
# liesse sich nicht zeigen, dass ein fehlgeschlagenes enable/start des Tasters fuer
|
||||||
|
# sich genommen keinen Abbruch ausloest.
|
||||||
|
case "\$*" in
|
||||||
|
*ninlight-button*)
|
||||||
|
case "\$1" in
|
||||||
|
enable) exit "\${FAKE_BUTTON_ENABLE_EXIT:-0}" ;;
|
||||||
|
restart) exit "\${FAKE_BUTTON_RESTART_EXIT:-0}" ;;
|
||||||
|
*) exit 0 ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
case "\$1" in
|
case "\$1" in
|
||||||
enable) exit "\${FAKE_SYSTEMCTL_ENABLE_EXIT:-0}" ;;
|
enable) exit "\${FAKE_SYSTEMCTL_ENABLE_EXIT:-0}" ;;
|
||||||
restart) exit "\${FAKE_SYSTEMCTL_RESTART_EXIT:-0}" ;;
|
restart) exit "\${FAKE_SYSTEMCTL_RESTART_EXIT:-0}" ;;
|
||||||
@@ -202,6 +215,7 @@ run_setup() {
|
|||||||
NINLIGHT_STATION_BIN="$state/usr/local/bin/ninlight-station" \
|
NINLIGHT_STATION_BIN="$state/usr/local/bin/ninlight-station" \
|
||||||
NINLIGHT_STATION_UNIT="$state/etc/systemd/system/ninlight-station.service" \
|
NINLIGHT_STATION_UNIT="$state/etc/systemd/system/ninlight-station.service" \
|
||||||
NINLIGHT_DISPLAY_UNIT="$state/etc/systemd/system/ninlight-display.service" \
|
NINLIGHT_DISPLAY_UNIT="$state/etc/systemd/system/ninlight-display.service" \
|
||||||
|
NINLIGHT_BUTTON_UNIT="$state/etc/systemd/system/ninlight-button.service" \
|
||||||
NINLIGHT_NM_DIR="$state/etc/NetworkManager/system-connections" \
|
NINLIGHT_NM_DIR="$state/etc/NetworkManager/system-connections" \
|
||||||
NINLIGHT_BOOT_CONFIG_NEW="$state/boot/firmware/config.txt" \
|
NINLIGHT_BOOT_CONFIG_NEW="$state/boot/firmware/config.txt" \
|
||||||
NINLIGHT_BOOT_CONFIG_OLD="$state/boot/config.txt" \
|
NINLIGHT_BOOT_CONFIG_OLD="$state/boot/config.txt" \
|
||||||
@@ -906,6 +920,133 @@ grep -Fqx "dtparam=spi=on" "$CONFIG27" && pass "die Zeile wurde trotzdem aktivie
|
|||||||
[ "$(cat "${CONFIG27}.bak-ninlight")" = "urspruenglicher-originalzustand" ] && pass "die bestehende Sicherung blieb unangetastet" || fail "die Sicherung wurde ueberschrieben: $(cat "${CONFIG27}.bak-ninlight")"
|
[ "$(cat "${CONFIG27}.bak-ninlight")" = "urspruenglicher-originalzustand" ] && pass "die bestehende Sicherung blieb unangetastet" || fail "die Sicherung wurde ueberschrieben: $(cat "${CONFIG27}.bak-ninlight")"
|
||||||
echo "$OUT" | grep -q "existiert bereits - wird nicht ueberschrieben" && pass "Ausgabe erwaehnt, dass die Sicherung nicht ueberschrieben wurde" || fail "keine entsprechende Meldung: $OUT"
|
echo "$OUT" | grep -q "existiert bereits - wird nicht ueberschrieben" && pass "Ausgabe erwaehnt, dass die Sicherung nicht ueberschrieben wurde" || fail "keine entsprechende Meldung: $OUT"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 28 (Task 8b): Taster wird ausgeliefert, installiert und aktiviert ==="
|
||||||
|
STATE="$TMPROOT/s28-state"; STUBBIN="$TMPROOT/bin28"; LOG="$TMPROOT/s28.log"
|
||||||
|
setup_state "$STATE"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
|
||||||
|
BTN28="$STATE/opt/ninlight-station/button"
|
||||||
|
[ -f "$BTN28/button.py" ] && pass "button/button.py ausgeliefert" || fail "button/button.py fehlt unter $BTN28"
|
||||||
|
[ -x "$BTN28/button.py" ] && pass "button.py ist ausfuehrbar" || fail "button.py ist nicht ausfuehrbar"
|
||||||
|
[ ! -d "$BTN28/__pycache__" ] && pass "kein __pycache__ auf dem Pi gelandet" || fail "__pycache__ wurde mitkopiert"
|
||||||
|
[ -f "$STATE/etc/systemd/system/ninlight-button.service" ] && pass "ninlight-button.service installiert" || fail "Taster-Unit fehlt - sie waere weiter toter Text im Repo"
|
||||||
|
grep -Fq "systemctl enable ninlight-button.service" "$LOG" && pass "Tasterdienst wurde aktiviert" || fail "kein 'systemctl enable ninlight-button' im Log"
|
||||||
|
grep -Fq "systemctl restart ninlight-button.service" "$LOG" && pass "Tasterdienst wurde gestartet" || fail "kein 'systemctl restart ninlight-button' im Log"
|
||||||
|
# Die Station selbst bleibt weiterhin aus - derselbe Sicherheitsfehler waere hier
|
||||||
|
# genauso schwerwiegend wie in Szenario 5.
|
||||||
|
grep -Fq "systemctl enable ninlight-station" "$LOG" && fail "setup_pi.sh aktiviert den Stationsdienst" || pass "Stationsdienst bleibt deaktiviert"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 29 (Task 8b): Reststand in der Ablage fuehrt beim Taster nicht zu einer stillen Nullinstallation ==="
|
||||||
|
# Dasselbe Muster wie Szenario 11 fuer die Anzeige, hier fuer button/: ein
|
||||||
|
# liegengebliebenes "…/ninlight-button/" laesst ein "scp -r" hineinkopieren statt
|
||||||
|
# darauf, die Installationsschleife faende dann nichts.
|
||||||
|
STATE="$TMPROOT/s29-state"; STUBBIN="$TMPROOT/bin29"; LOG="$TMPROOT/s29.log"
|
||||||
|
setup_state "$STATE"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
mkdir -p "$STATE/tmp/ninlight-button"
|
||||||
|
echo "rest" >"$STATE/tmp/ninlight-button/uebrig.py"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
|
||||||
|
BTN29="$STATE/opt/ninlight-station/button"
|
||||||
|
[ -f "$BTN29/button.py" ] && pass "button.py trotz Reststand installiert" || fail "Nullinstallation: $BTN29 enthaelt $(ls -A "$BTN29" 2>/dev/null | tr '\n' ' ')"
|
||||||
|
[ ! -d "$BTN29/button" ] && pass "kein verschachteltes button/button/ entstanden" || fail "verschachteltes Verzeichnis angelegt"
|
||||||
|
[ ! -f "$BTN29/uebrig.py" ] && pass "der Reststand des Vorlaufs wurde nicht mitinstalliert" || fail "uebrig.py aus dem Reststand landete auf dem Pi"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 30 (Task 8b): scheitert die Uebertragung des Tastercodes, wird laut abgebrochen ==="
|
||||||
|
STATE="$TMPROOT/s30-state"; STUBBIN="$TMPROOT/bin30"; LOG="$TMPROOT/s30.log"
|
||||||
|
setup_state "$STATE"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(FAKE_SCP_SKIP_BUTTON_DIR=1 run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC" -ne 0 ] && pass "Exit-Code != 0" || fail "Exit-Code 0 trotz fehlgeschlagener Uebertragung: $OUT"
|
||||||
|
echo "$OUT" | grep -q "button.py fehlt" && pass "Fehlermeldung nennt die fehlende Datei" || fail "Fehlermeldung fehlt: $OUT"
|
||||||
|
grep -Fq "systemctl enable ninlight-button" "$LOG" && fail "der Tasterdienst wurde trotz fehlender Dateien aktiviert" || pass "kein aktivierter Tasterdienst ohne Dateien"
|
||||||
|
for F in "$STATE/opt/ninlight-station/server.py" "$STATE/opt/ninlight-station/products.py" \
|
||||||
|
"$STATE/usr/local/bin/ninlight-station" \
|
||||||
|
"$STATE/etc/systemd/system/ninlight-station.service" \
|
||||||
|
"$STATE/etc/systemd/system/ninlight-display.service" \
|
||||||
|
"$STATE/etc/systemd/system/ninlight-button.service"; do
|
||||||
|
[ ! -e "$F" ] && pass "wirklich nicht installiert: $(basename "$F")" || fail "die Meldung luegt - $F liegt auf dem Pi"
|
||||||
|
done
|
||||||
|
REST30=$(find "$STATE/tmp" -mindepth 1 2>/dev/null | head -n5)
|
||||||
|
[ -z "$REST30" ] && pass "die Ablage wurde auch im Fehlerfall aufgeraeumt" || fail "Reststand in der Ablage: $REST30"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 31 (Task 8b): eine im Repo geloeschte Datei verschwindet auch aus button/ auf dem Pi ==="
|
||||||
|
STATE="$TMPROOT/s31-state"; STUBBIN="$TMPROOT/bin31"; LOG="$TMPROOT/s31.log"
|
||||||
|
setup_state "$STATE"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
mkdir -p "$STATE/opt/ninlight-station/button"
|
||||||
|
echo "alt" >"$STATE/opt/ninlight-station/button/veraltet.py"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
|
||||||
|
[ ! -f "$STATE/opt/ninlight-station/button/veraltet.py" ] && pass "veraltete Datei entfernt" || fail "veraltet.py blieb liegen"
|
||||||
|
[ -f "$STATE/opt/ninlight-station/button/button.py" ] && pass "der aktuelle Code ist trotzdem da" || fail "button.py fehlt"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 32 (Task 8b): ein fehlgeschlagenes enable/restart NUR des Tasterdienstes warnt und bricht nicht ab ==="
|
||||||
|
# Eigene Schalter (FAKE_BUTTON_*), damit die Anzeige dabei unbeteiligt bleibt - das
|
||||||
|
# zeigt, dass der Taster fuer sich genommen keine Voraussetzung ist.
|
||||||
|
STATE="$TMPROOT/s32-state"; STUBBIN="$TMPROOT/bin32"; LOG="$TMPROOT/s32.log"
|
||||||
|
setup_state "$STATE"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(FAKE_BUTTON_ENABLE_EXIT=1 FAKE_BUTTON_RESTART_EXIT=1 run_setup "$STATE" "$STUBBIN" 2>"$TMPROOT/s32.err")
|
||||||
|
RC=$?
|
||||||
|
set -e
|
||||||
|
ERR=$(cat "$TMPROOT/s32.err")
|
||||||
|
[ "$RC" -eq 0 ] && pass "Exit-Code 0 trotz fehlgeschlagenem enable/restart des Tasters" || fail "Exit-Code $RC: $ERR"
|
||||||
|
echo "$ERR" | grep -q "systemctl enable ninlight-button" && pass "Warnung zu 'enable' auf stderr" || fail "keine enable-Warnung: $ERR"
|
||||||
|
echo "$ERR" | grep -q "systemctl restart ninlight-button" && pass "Warnung zu 'restart' auf stderr" || fail "keine restart-Warnung: $ERR"
|
||||||
|
grep -Fq "systemctl enable ninlight-display.service" "$LOG" && pass "die Anzeige wurde trotzdem aktiviert - der Taster reisst sie nicht mit" || fail "die Anzeige-Aktivierung blieb aus"
|
||||||
|
[ -f "$STATE/etc/NetworkManager/system-connections/qconnex-firmware.nmconnection" ] && pass "der Lauf ging danach normal weiter (Profile angelegt)" || fail "der Lauf brach nach der Warnung ab"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Szenario 33 (Task 8b): ein zweiter Lauf ist ein echtes No-Op ==="
|
||||||
|
# Idempotenz ist die Kopfzusage von setup_pi.sh (siehe Kommentar am Dateianfang) - hier
|
||||||
|
# konkret fuer den neu hinzugekommenen Taster geprueft: ein zweiter Lauf auf einem
|
||||||
|
# bereits eingerichteten Pi darf button/ und dessen Unit nicht veraendern.
|
||||||
|
STATE="$TMPROOT/s33-state"; STUBBIN="$TMPROOT/bin33"; LOG="$TMPROOT/s33.log"
|
||||||
|
setup_state "$STATE"
|
||||||
|
setup_stubbin "$STUBBIN" "$LOG"
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
run_setup "$STATE" "$STUBBIN" >/dev/null 2>&1
|
||||||
|
RC1=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC1" -eq 0 ] || fail "erster Lauf schon fehlgeschlagen (rc=$RC1)"
|
||||||
|
SUM_BEFORE=$(find "$STATE/opt/ninlight-station/button" "$STATE/etc/systemd/system/ninlight-button.service" -type f -exec cksum {} \; | sort)
|
||||||
|
: >"$LOG"
|
||||||
|
set +e
|
||||||
|
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
|
||||||
|
RC2=$?
|
||||||
|
set -e
|
||||||
|
[ "$RC2" -eq 0 ] && pass "zweiter Lauf: Exit-Code 0" || fail "zweiter Lauf: Exit-Code $RC2, Ausgabe: $OUT"
|
||||||
|
SUM_AFTER=$(find "$STATE/opt/ninlight-station/button" "$STATE/etc/systemd/system/ninlight-button.service" -type f -exec cksum {} \; | sort)
|
||||||
|
[ "$SUM_BEFORE" = "$SUM_AFTER" ] && pass "button/ und die Taster-Unit sind nach dem zweiten Lauf byte-identisch" || fail "der zweite Lauf hat etwas an button/ veraendert"
|
||||||
|
grep -Fq "systemctl enable ninlight-button.service" "$LOG" && pass "der zweite Lauf aktiviert den Tasterdienst erneut (idempotent, kein Fehler)" || fail "kein erneutes 'systemctl enable ninlight-button' im zweiten Lauf"
|
||||||
|
echo "$OUT" | grep -q "veraltete Datei entfernt: button/" && fail "der zweite Lauf meldet eine veraltete Datei, obwohl nichts geloescht wurde" || pass "keine falsche 'veraltete Datei entfernt'-Meldung im zweiten Lauf"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
if [ "$FAILED" -eq 0 ]; then
|
if [ "$FAILED" -eq 0 ]; then
|
||||||
echo "Alle Tests bestanden."
|
echo "Alle Tests bestanden."
|
||||||
|
|||||||
Reference in New Issue
Block a user