Wartung: SSH-Bulk-Update & -Neustart für Linux-Clients

Neue Seite "Wartung" (Geräte-Bereich, eigenes Rechtepaar
maintenance.view/maintenance.edit), komplett getrennt vom PoE-Neustart
auf dem Dashboard:

- Dashboard-Neustart bleibt ausschließlich PoE-Reset über den Switch
- Wartung läuft immer per SSH direkt auf dem Gerät, unabhängig von
  jeder Switch-Zuordnung -- nur Geräte mit SSH-Zugangsdaten der
  Kategorie "Linux-Client" erscheinen dort (Windows/PowerShell folgt
  als eigener, separater Schritt -- kein Testsystem dafür verfügbar)

Backend:
- _run_ssh_command()/_run_ssh_reboot(): nicht-interaktive SSH-Ausführung
  mit paramiko.RejectPolicy() gegen dieselbe known_hosts-Datei wie das
  interaktive Browser-Terminal -- ein Host muss vorher einmal per
  "Verbindung testen" bestätigt worden sein, da hier (anders als im
  Terminal) niemand eine "yes/no"-Rückfrage beantworten kann
- _apt_upgrade_command(): "apt update && apt upgrade -y" nicht-
  interaktiv mit DEBIAN_FRONTEND=noninteractive und
  --force-confdef/--force-confold, damit ein Paket-Postinst-Skript
  nicht auf eine nie kommende Config-Rückfrage wartet
- Reboot behandelt einen abrupten Verbindungsabbruch NACH dem Kommando
  als Erfolg (die Maschine fährt herunter, bevor sie antworten kann);
  nur ein Fehler VOR dem Reboot-Kommando zählt als echter Fehler
- Job-Status lebt im Prozessspeicher (wie das SSH-Terminal), Live-
  Anzeige per Polling (/maintenance/status)

Live gegen ein dediziertes Testsystem (getrennt vom gemeinsam
genutzten App-Host, um dort kein echtes apt upgrade auszulösen)
verifiziert: echtes "apt update && apt upgrade" inkl. Kernel-/systemd-/
netplan-Paketen lief vollständig durch, anschließender SSH-Neustart hat
das System nachweislich neu gestartet (uptime nach dem Job bestätigt).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 11:12:07 +02:00
co-authored by Claude Sonnet 5
parent 63ca7782ba
commit 8772f7777b
5 changed files with 620 additions and 13 deletions
+94 -12
View File
@@ -25,8 +25,17 @@ Die App ermöglicht:
Host-Key zu bestätigen und die Zugangsdaten direkt zu prüfen, bevor der
Switch gespeichert wird — funktioniert auf jedem Betriebssystem, die
SSH-Verbindung wird dabei immer vom PoE-Server aus aufgebaut
- Manueller PoE-Neustart einzelner Geräte per Klick; bei deaktivierten
Geräten bietet das Detail-Popup stattdessen direkt eine Aktivieren-Option
- Manueller PoE-Neustart einzelner Geräte per Klick — ausschließlich über
den zugeordneten Switch (`poe.sh`); der Button erscheint im Detail-Popup
nur, wenn dem Gerät tatsächlich Switch **und** Port zugeordnet sind (sonst
wäre kein PoE-Reset möglich), und ist immer der am weitesten links stehende
Aktions-Button — „Schließen“ steht unabhängig davon immer ganz rechts. Bei
deaktivierten Geräten bietet das Detail-Popup stattdessen direkt eine
Aktivieren-Option
- **SSH-basierte Wartung für Linux-Clients** (eigene Seite „Wartung“,
getrennt vom PoE-Neustart oben): Bulk-Update (`apt update && apt upgrade`)
und Neustart per SSH direkt auf dem Gerät, unabhängig von jeder
Switch-Zuordnung (siehe [Wartung](#wartung-ssh-bulk-update--neustart))
- Einstellbares Prüfintervall (steuert den Hintergrund-Check-Dienst) —
der Countdown „Nächste Prüfung“ wird aus dem tatsächlichen letzten
Log-Eintrag berechnet, nicht bei jedem Seitenaufruf neu gestartet, und
@@ -191,15 +200,26 @@ Bereichs-Recht nicht bei jedem Neustart automatisch wieder gesetzt wird.
## Zugangsdaten (wiederverwendbare SSH-Logins)
Switch-Zugangsdaten (Username + verschlüsseltes Passwort) sind eine eigene
Entität (`credentials`-Tabelle) statt direkt am Switch zu hängen — mehrere
Switche mit demselben Login teilen sich einen Eintrag. Beim Anlegen/Bearbeiten
eines Switches lässt sich per Dropdown ein bestehender Eintrag auswählen oder
über „+ Neue Zugangsdaten anlegen“ direkt im selben Formular ein neuer
anlegen, ohne vorher zur eigenen **Zugangsdaten**-Seite wechseln zu müssen.
Löschen ist nur möglich, wenn kein Switch mehr auf den Eintrag verweist.
Bestehende Datenbanken aus einer älteren Version (Username/Passwort direkt
am Switch) werden beim ersten Start automatisch migriert.
Zugangsdaten (Username + verschlüsseltes Passwort) sind eine eigene Entität
(`credentials`-Tabelle) statt direkt am Switch/Gerät zu hängen — mehrere
Switche/Geräte mit demselben Login teilen sich einen Eintrag. Beim Anlegen/
Bearbeiten eines Switches **oder Geräts** lässt sich per Dropdown ein
bestehender Eintrag auswählen oder über „+ Neue Zugangsdaten anlegen“ direkt
im selben Formular ein neuer anlegen, ohne vorher zur eigenen
**Zugangsdaten**-Seite wechseln zu müssen. Löschen ist nur möglich, wenn
weder ein Switch noch ein Gerät mehr auf den Eintrag verweist. Bestehende
Datenbanken aus einer älteren Version (Username/Passwort direkt am Switch)
werden beim ersten Start automatisch migriert.
Jede Zugangsdaten-Zeile hat außerdem eine explizite **Kategorie** (Switch /
Linux-Client / Windows-Client / Router-Sonstiges), vom Admin beim Anlegen
gesetzt — bewusst **nicht** automatisch per Ping/TTL-Heuristik erkannt (zu
unzuverlässig, siehe Diskussion in der Commit-Historie). Aktuell wertet nur
die Kategorie **Linux-Client** etwas aus: nur Geräte mit einer so
kategorisierten Zugangsdaten-Zuordnung erscheinen unter **Wartung** (siehe
unten). Windows/PowerShell-Wartung ist als eigener, separater Schritt
vorgesehen (kein Testsystem dafür verfügbar) — die Kategorie existiert
bereits, die Aktion dahinter noch nicht.
Jeder Switch kann außerdem einen individuellen **SSH-Port** hinterlegen
(Feld „SSH-Port“ beim Anlegen/Bearbeiten) — bleibt er leer, wird überall
@@ -210,6 +230,67 @@ sich per SSH mit einem Switch verbindet: dem Web-Terminal (Verbindungstest),
`expect`-Aufrufen in `poe.sh` selbst (`ssh -p <port> ...`) für automatische
wie manuelle PoE-Neustarts.
## Wartung (SSH-Bulk-Update & -Neustart)
Eigene Seite unter **Geräte → Wartung** (eigenes Rechtepaar
`maintenance.view`/`maintenance.edit`), komplett getrennt vom PoE-Neustart
auf dem Dashboard:
- **Dashboard-Neustart** = immer PoE-Reset über den Switch (`poe.sh`),
funktioniert unabhängig davon, ob das Gerät SSH-Zugangsdaten hat.
- **Wartung** = immer eine direkte SSH-Verbindung zum Gerät selbst,
funktioniert unabhängig davon, ob/an welchem Switch es hängt.
Nur Geräte mit hinterlegten SSH-Zugangsdaten der Kategorie **Linux-Client**
(siehe oben) erscheinen in der Liste. Zwei Aktionen:
- **Update** (Mehrfachauswahl per Checkbox, ein Klick startet alle
ausgewählten parallel als eigene Hintergrund-Threads): führt serverseitig
`env DEBIAN_FRONTEND=noninteractive apt-get update && env
DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef"
-o Dpkg::Options::="--force-confold" upgrade` per SSH aus — nicht
interaktiv (kein Terminal, keine Rückfragemöglichkeit), die
`Dpkg::Options`-Flags verhindern, dass ein Paket-Postinst-Skript auf eine
Config-Datei-Rückfrage wartet, die nie kommt und sonst bis zum Timeout
hängen bliebe.
- **Neustart** (pro Gerät): `sudo reboot` per SSH. Ein abrupter
Verbindungsabbruch direkt danach ist erwartet (die Maschine fährt
herunter, bevor sie noch antworten kann) und zählt als Erfolg, kein
Fehler — nur ein Verbindungs-/Auth-Fehler **vor** dem eigentlichen
Neustart-Kommando gilt als echter Fehler.
Live-Status pro Gerät (läuft/erfolgreich/fehlgeschlagen inkl. Ausgabe der
letzten Aktion, per Klick ein-/ausblendbar) wird per Polling (`/maintenance/status`,
alle 2s solange etwas läuft, sonst alle 8s) aktualisiert, ohne die Seite neu
zu laden. Der Job-Status lebt bewusst nur im Prozessspeicher (wie beim
SSH-Terminal auch keine Sitzung persistiert wird) — ein Neustart von
`poe_web.service` verwirft nur die Anzeige, nicht die auf dem Zielgerät
bereits laufende Aktion selbst.
**Sicherheitsmodell**: dieselbe `known_hosts`-Datei wie beim
Browser-SSH-Terminal (`SSH_KNOWN_HOSTS_PATH`) — ein Host muss vorher
mindestens einmal interaktiv über „Verbindung testen“ bestätigt worden sein.
Anders als das interaktive Terminal (dort kann bei einem unbekannten
Host-Key wie bei einem echten `ssh`-Client live nachgefragt werden) läuft
hier nichts vor einem Menschen ab — ein unbekannter oder nicht vorher
bestätigter Host-Key wird deshalb per `paramiko.RejectPolicy` hart
abgelehnt statt automatisch akzeptiert, da ohne Rückfragemöglichkeit ein
automatisches Akzeptieren ein MITM-Risiko ohne jede Prüfung wäre.
Live gegen ein dediziertes Testsystem verifiziert (separat vom gemeinsam
genutzten App-Host, um dort kein echtes `apt upgrade` auszulösen): ein
echtes `apt update && apt upgrade` (inkl. Kernel-/systemd-/netplan-Paketen)
lief nicht-interaktiv vollständig durch (`status: success`, komplette
`apt`-Ausgabe im Job-Verlauf sichtbar), anschließend hat der SSH-Neustart
das Testsystem tatsächlich neu gestartet — bestätigt über `uptime -s`
direkt nach dem Job (Boot-Zeitpunkt stimmte mit dem Auslöse-Zeitpunkt
überein, nicht nur die vom Code erwartete Verbindungsunterbrechung).
Windows-Clients/PowerShell-Wartung ist bewusst **noch nicht** umgesetzt
(kein Testsystem verfügbar) — die Kategorie „Windows-Client“ existiert in
den Zugangsdaten bereits als Vorbereitung für einen späteren, separaten
Ausbauschritt.
## DHCP-Reservierungen & eigene Options (Systemeinstellungen → DHCP)
Erzeugt aus den vorhandenen Client-Stammdaten (MAC + IP + Name) automatisch
@@ -516,7 +597,8 @@ verursachen, obwohl der Code auf dem Server längst aktuell war.
Die Sidebar ist in drei aufklappbare Gruppen strukturiert:
- **Geräte** — Clients (die eigentlichen Devices), Switche, Zugangsdaten
- **Geräte** — Clients (die eigentlichen Devices), Switche, Zugangsdaten,
Wartung (SSH-Bulk-Update/-Neustart)
- **Einstellungen** — Benutzer, Gruppen, Systemeinstellungen (Prüfintervall),
Im-/Export
- **Logs** — Live, Änderungen (Änderungslog)