tesm.service startete die App bisher direkt per 'python3 app.py', was
Flasks eingebauten Werkzeug-Entwicklungsserver nutzt -- der meldet bei
jedem Start 'WARNING: This is a development server. Do not use it in a
production deployment.' und ist bewusst nicht für Dauerbetrieb gebaut.
Umgestellt auf Gunicorn, mit zwei bewusst gesetzten Einschraenkungen:
- '--workers 1': die App haelt laufende Wartungs-Jobs/Import-Vorschauen
nur im Arbeitsspeicher DES EINEN Prozesses (_maintenance_jobs,
_pending_imports, ...) -- mehrere Worker-Prozesse wuerden diesen
Zustand auf mehrere, sich nicht kennende Prozesse verteilen.
- '--worker-class gthread --threads 16' statt eines async-Workers: das
Browser-SSH-Terminal (flask-sock) belegt pro offener WebSocket-
Verbindung einen blockierenden Thread.
- '--timeout 0': deaktiviert Gunicorns eigenen 30s-Worker-Timeout, der
sonst auch eine offene, aber gerade inaktive SSH-Terminal-Verbindung
killen wuerde.
Live auf POETEST verifiziert: keine WARNING-Zeile mehr, genau 1 Master-
+ 1 Worker-Prozess, alle Kernseiten weiterhin 200, und als kritischer
Regressionstest das WebSocket-SSH-Terminal Ende-zu-Ende gegen einen
echten Host erfolgreich getestet (Host-Key/Passwort-Prompt/Login/Shell).
Dabei einen unabhaengigen Altlast-Fehler in POETESTs venv gefunden und
allgemein in install.sh gefixt: './venv/bin/pip' hat eine zur
Venv-Erstellung fest einprogrammierte Shebang-Zeile -- nach der
historischen Umbenennung 'poe_manager' -> 'tesm' zeigte sie auf einen
nicht mehr existierenden Pfad und schlug mit 'cannot execute: required
file not found' fehl. 'python3 -m pip' umgeht das, da nur der (korrekt
referenzierte) venv-Python-Interpreter selbst gebraucht wird -- betrifft
sonst auch jedes kuenftige In-Place-Update auf einem aehnlich
gewachsenen Host.
- Login-Seite: WiS-/TESM-Logo und "Melde dich an, um fortzufahren" aus der
Box entfernt; die TESM-Wortmarke mit Funktionszeile ist jetzt der
tatsächliche Seitenhintergrund (absolut positioniert, hinter allem), die
Box liegt zentriert davor. Nebenbei zwei echte Bugs gefunden und behoben:
fehlendes Cache-Busting auf login.html (asset_url() wie in base.html,
sonst hält nginx' 7-Tage-Cache eine alte style.css/app.js fest) und ein
durch den fehlenden align-items-Wert auf die volle Höhe gestrecktes
Login-Formular.
- Neuer SSH-Login-Banner (dynamisches MOTD) mit Live-Flottenstatus statt der
Standard-Ubuntu-Willkommensmeldung: srv/tesm/motd_banner.py liest
Online/Offline- und DHCP-Status aus denselben Quellen wie das
Web-Dashboard (get_device_status()/_dhcp_read_leases()), eingebunden über
etc/update-motd.d/50-tesm. install.sh deaktiviert dabei die Standard-
Ubuntu-MOTD-Skripte (chmod -x, reversibel) und installiert den neuen Hook.
Auf der frisch installierten Test-VM zeigten sich zwei weitere reale Probleme:
1. "Verbindung testen" im Switch-Modal blieb dauerhaft auf "Getrennt"
haengen, sobald ueber nginx (Port 80) statt direkt gegen Flask (Port
5000) zugegriffen wurde. Ursache: etc/nginx/sites-available/poe_manager
reichte den "Upgrade"/"Connection"-Header fuer /ws/ssh_terminal nicht
durch -- Flask/Werkzeug lehnte den WebSocket-Handshake dadurch mit
400 Bad Request ab, statt mit 101 Switching Protocols zu antworten.
Live reproduziert und verifiziert (curl-Handshake direkt vs. durch
nginx). Alle bisherigen Terminal-Tests dieser Session liefen ausschliesslich
direkt gegen Flask, nie durch nginx, daher bis jetzt unentdeckt.
Fix: eigener location /ws/ Block mit Upgrade-Map (Standard-nginx-Pattern)
und grosszuegigen Timeouts fuer die lang offene Terminal-Verbindung.
2. Der Kea-DHCP-Server lief nach einer Aenderung der Host-Netzwerkkonfiguration
unveraendert weiter, obwohl die konfigurierte Range nach einem
IP-/Subnetzwechsel nicht mehr zum neuen Netz passen muss. Neue Funktion
_stop_dhcp_service_if_active() stoppt Kea jetzt sowohl beim Anwenden
als auch beim Auto-Rollback einer Netzwerkaenderung -- bewusst nur
stoppen statt automatisch neu zu starten, die Range muss der Admin
aktiv auf der DHCP-Seite pruefen und den Dienst dort bewusst wieder
starten (gleiche Philosophie wie beim Rest der DHCP-Dienststeuerung).
Beide Fixes live auf der Test-VM verifiziert (WebSocket-Handshake per
curl, Netzwerk-Reapply ohne Fehler im journalctl-Log trotz nicht
installiertem Kea).
- Neues, eigenständiges Frontend (Sidebar, zentriertes Logo in der Topbar,
Dark/Light-Theme, Karten-Dashboard, Toasts/Modals statt Bootstrap)
- Oeffentliches Kurz-Dashboard ohne Login (Status-Uebersicht)
- Browser-SSH-Terminal (paramiko, plattformunabhaengig) zum Testen von
Switch-Zugangsdaten inkl. interaktiver Host-Key-Bestaetigung
- Granulares Rechtesystem mit Gruppen (Devices/Switches-Berechtigungen)
- Aufgeraeumtes Backend mit konfigurierbaren Pfaden, auto-generierten
Secrets statt hart codierter Werte im Original
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>