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.
47 lines
1.8 KiB
Plaintext
47 lines
1.8 KiB
Plaintext
bcrypt==5.0.0
|
|
blinker==1.9.0
|
|
cffi==2.0.0
|
|
click==8.3.0
|
|
cryptography==46.0.1
|
|
Flask==3.1.2
|
|
Flask-Bcrypt==1.0.1
|
|
Flask-Login==0.6.3
|
|
Flask-Sock==0.7.0
|
|
gunicorn==23.0.0
|
|
itsdangerous==2.2.0
|
|
Jinja2==3.1.6
|
|
ldap3==2.9.1
|
|
MarkupSafe==3.0.2
|
|
paramiko==3.5.1
|
|
pyasn1==0.6.4
|
|
pycparser==2.23
|
|
PyNaCl==1.5.0
|
|
PyYAML==6.0.2
|
|
simple-websocket==1.1.0
|
|
Werkzeug==3.1.3
|
|
|
|
# Hinweis: Das Browser-SSH-Terminal (Switch-Verbindungstest) nutzt paramiko
|
|
# (reines Python) statt eines lokalen pty + System-ssh-Client und läuft
|
|
# damit plattformunabhängig — auch unter Windows. Die SSH-Verbindung wird
|
|
# dabei immer serverseitig (vom PoE-Server) aufgebaut, nie vom Browser aus.
|
|
#
|
|
# PyYAML wird für das netplan-Backend der Host-Netzwerkeinstellungen
|
|
# gebraucht (Systemeinstellungen → Netzwerkeinstellungen) — schreibt/liest
|
|
# die eigene Override-Datei unter /etc/netplan/.
|
|
#
|
|
# ldap3 (reines Python, keine System-Bibliothek wie libldap nötig) für die
|
|
# optionale Active-Directory/LDAP-Anmeldung (Systemeinstellungen → LDAP) —
|
|
# Search+Bind gegen einen AD-Domain-Controller oder generischen LDAP-Server.
|
|
#
|
|
# gunicorn: produktiver WSGI-Server für tesm.service (siehe dort) statt
|
|
# Flasks eigenem app.run()-Entwicklungsserver ("WARNING: This is a
|
|
# development server..."). Läuft bewusst mit genau EINEM Worker-Prozess,
|
|
# aber mehreren Threads (--worker-class gthread) -- mehrere Prozesse
|
|
# würden den In-Memory-Zustand für laufende Wartungs-Jobs/Import-
|
|
# Vorschauen (_maintenance_jobs/_pending_imports/...) auf mehrere,
|
|
# voneinander isolierte Prozesse verteilen, wodurch eine Anfrage, die vom
|
|
# jeweils ANDEREN Worker beantwortet wird, diesen Zustand nie sehen würde.
|
|
# Mehrere Threads (statt eines async-Workers) sind nötig, weil das
|
|
# Browser-SSH-Terminal (flask-sock) pro offener WebSocket-Verbindung einen
|
|
# blockierenden Thread belegt.
|