Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ea7937b5b | ||
|
|
80d9e30bd4 |
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm"
|
name = "tesm"
|
||||||
version = "2.8.28"
|
version = "2.8.30"
|
||||||
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
+25
-2
@@ -418,9 +418,32 @@ info "Dateien abgeglichen (Instanzdaten unter data/ bleiben unangetastet)"
|
|||||||
|
|
||||||
# -- venv --------------------------------------------------------------------
|
# -- venv --------------------------------------------------------------------
|
||||||
step "Python-Umgebung"
|
step "Python-Umgebung"
|
||||||
if [[ ! -x "$ROOT/venv/bin/python3" ]]; then
|
# Ein venv haengt an der **Minor-Fassung**, mit der er gebaut wurde: die Pakete
|
||||||
|
# liegen unter lib/python3.X. Wechselt die Systemfassung -- ein Release-Upgrade
|
||||||
|
# von Ubuntu bringt genau das, 24.04 hat 3.12 und 26.04 hat 3.14 --, dann ist
|
||||||
|
# venv/bin/python3 weiter ausfuehrbar: der Verweis zeigt auf /usr/bin/python3,
|
||||||
|
# also auf den **neuen** Interpreter. Der venv sieht heil aus und ist es nicht.
|
||||||
|
# Er findet danach kein einziges Paket mehr, nicht einmal pip.
|
||||||
|
#
|
||||||
|
# Gemessen auf dem Testserver, mit verschobenem lib-Verzeichnis:
|
||||||
|
# [[ -x venv/bin/python3 ]] -> wahr
|
||||||
|
# venv/bin/python3 -m pip --version -> "No module named pip"
|
||||||
|
#
|
||||||
|
# Die alte Pruefung fragte nur nach der Ausfuehrbarkeit. Sie haette den toten
|
||||||
|
# venv behalten und waere eine Zeile spaeter an "python3 -m pip" gescheitert --
|
||||||
|
# mitten in einer Aktualisierung, auf einem Server, dessen Dienste ohnehin
|
||||||
|
# schon stehen. Gefragt wird deshalb, was gebraucht wird: laesst sich in
|
||||||
|
# diesem venv pip benutzen?
|
||||||
|
venv_traegt() {
|
||||||
|
[[ -x "$ROOT/venv/bin/python3" ]] || return 1
|
||||||
|
"$ROOT/venv/bin/python3" -c "import pip" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
if ! venv_traegt; then
|
||||||
|
# Ohne --clear: ein erneutes "venv" ergaenzt das fehlende lib-Verzeichnis und
|
||||||
|
# holt pip zurueck; die Abhaengigkeiten kommen gleich darunter ohnehin neu.
|
||||||
|
# Auch das ist gemessen und nicht angenommen.
|
||||||
python3 -m venv "$ROOT/venv"
|
python3 -m venv "$ROOT/venv"
|
||||||
info "venv erzeugt"
|
info "Python-Umgebung aufgebaut ($(python3 -V 2>&1))"
|
||||||
fi
|
fi
|
||||||
# Immer ueber "python3 -m pip" -- der pip-Shim im venv baeckt einen absoluten
|
# Immer ueber "python3 -m pip" -- der pip-Shim im venv baeckt einen absoluten
|
||||||
# Pfad in seinen Shebang, der nach einer Umbenennung des Verzeichnisses bricht.
|
# Pfad in seinen Shebang, der nach einer Umbenennung des Verzeichnisses bricht.
|
||||||
|
|||||||
@@ -150,6 +150,22 @@ def main(argv: list[str] | None = None) -> int:
|
|||||||
globals().update(AMBER="", DIM="", BOLD="", RESET="")
|
globals().update(AMBER="", DIM="", BOLD="", RESET="")
|
||||||
|
|
||||||
root = Path(args.root)
|
root = Path(args.root)
|
||||||
|
|
||||||
|
# Gibt es diese Installation ueberhaupt noch? Wenn nicht, ist hier nichts
|
||||||
|
# zu melden -- auch kein Fehler.
|
||||||
|
#
|
||||||
|
# Der Hook unter /etc/update-motd.d bleibt liegen, wenn jemand eine
|
||||||
|
# Installation von Hand entfernt; einen Rueckbau bringt TESM nicht mit.
|
||||||
|
# Vorher druckte jeder dieser Hooks trotzdem seinen vollen Banner und
|
||||||
|
# darunter "Datenbank nicht lesbar". Auf dem Testserver standen so
|
||||||
|
# vierzehn Bloecke fuer vierzehn laengst geloeschte Probeinstallationen
|
||||||
|
# vor jeder Anmeldung -- und der echte Banner ging darin unter.
|
||||||
|
#
|
||||||
|
# Eine entfernte Installation ist keine kaputte. Eine Datenbank, die da
|
||||||
|
# ist und sich nicht lesen laesst, dagegen schon: die meldet sich weiter.
|
||||||
|
if not (root / "data" / "app.db").is_file():
|
||||||
|
return 0
|
||||||
|
|
||||||
# Kein isatty()-Test: dieses Skript schreibt beim Login nicht auf ein
|
# Kein isatty()-Test: dieses Skript schreibt beim Login nicht auf ein
|
||||||
# Terminal, sondern ueber run-parts in eine Datei. Der Betrachter ist
|
# Terminal, sondern ueber run-parts in eine Datei. Der Betrachter ist
|
||||||
# trotzdem ein echtes Terminal -- deshalb immer Farbe.
|
# trotzdem ein echtes Terminal -- deshalb immer Farbe.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm-core"
|
name = "tesm-core"
|
||||||
version = "2.8.16"
|
version = "2.8.17"
|
||||||
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ def _config_from_settings(extension: Any, conn: Any) -> webserver.WebConfig:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
return webserver.WebConfig(
|
return webserver.WebConfig(
|
||||||
|
# Die neue Schreibweise, sobald der Webserver sie kennt.
|
||||||
|
http2_directive=webserver.nginx_kann_http2(),
|
||||||
app_key=extension.config.site_key,
|
app_key=extension.config.site_key,
|
||||||
upstream=str(extension.registry.get("upstream", "127.0.0.1:5000")),
|
upstream=str(extension.registry.get("upstream", "127.0.0.1:5000")),
|
||||||
static_root=str(
|
static_root=str(
|
||||||
|
|||||||
@@ -58,8 +58,14 @@ class WebConfig:
|
|||||||
#: ``listen ... ssl http2;`` und weisen die neue Direktive mit
|
#: ``listen ... ssl http2;`` und weisen die neue Direktive mit
|
||||||
#: "unknown directive" ab -- der ganze Webserver startet dann nicht mehr.
|
#: "unknown directive" ab -- der ganze Webserver startet dann nicht mehr.
|
||||||
#: Auf POETEST (nginx 1.24) genau so passiert. Vorgabe ist deshalb die alte
|
#: Auf POETEST (nginx 1.24) genau so passiert. Vorgabe ist deshalb die alte
|
||||||
#: Schreibweise: sie funktioniert ueberall und erzeugt auf neuen Versionen
|
#: Schreibweise: sie funktioniert ueberall.
|
||||||
#: nur eine Warnung.
|
#:
|
||||||
|
#: Wer die Konfiguration erzeugt, fragt vorher ``nginx_kann_http2()`` --
|
||||||
|
#: dann steht auf einem neuen Webserver auch die neue Schreibweise. Das ist
|
||||||
|
#: nicht nur Kosmetik gegen eine Warnung: nginx hat die alte Form als
|
||||||
|
#: veraltet erklaert, und was veraltet ist, faellt irgendwann weg. Ein
|
||||||
|
#: Release-Upgrade von Ubuntu ist genau der Moment, in dem so etwas
|
||||||
|
#: unbemerkt naeherrueckt (24.04 hat nginx 1.24, 26.04 hat 1.28).
|
||||||
http2_directive: bool = False
|
http2_directive: bool = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -89,6 +95,47 @@ class WebConfig:
|
|||||||
return "" if self.https_port == 443 else f":{self.https_port}"
|
return "" if self.https_port == 443 else f":{self.https_port}"
|
||||||
|
|
||||||
|
|
||||||
|
#: Ab dieser Fassung kennt nginx ``http2 on;``.
|
||||||
|
HTTP2_DIREKTIVE_AB = (1, 25, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def fassung_aus_ausgabe(text: str) -> tuple[int, ...]:
|
||||||
|
"""``nginx version: nginx/1.28.3 (Ubuntu)`` -> ``(1, 28, 3)``.
|
||||||
|
|
||||||
|
Getrennt vom Aufruf, damit sich die Entscheidung pruefen laesst, ohne
|
||||||
|
einen Webserver zu installieren. Was nicht ins Muster passt, ergibt ein
|
||||||
|
leeres Tupel -- und damit die Schreibweise, die ueberall funktioniert.
|
||||||
|
"""
|
||||||
|
treffer = re.search(r"nginx/(\d+)\.(\d+)\.(\d+)", text or "")
|
||||||
|
return tuple(int(teil) for teil in treffer.groups()) if treffer else ()
|
||||||
|
|
||||||
|
|
||||||
|
def nginx_version() -> tuple[int, ...]:
|
||||||
|
"""Die Fassung des installierten nginx, sonst ein leeres Tupel.
|
||||||
|
|
||||||
|
``nginx -v`` schreibt nach stderr und braucht keine Rechte. Faellt die
|
||||||
|
Antwort aus -- kein nginx, kein Ausfuehrungsrecht, fremdes Format --, gibt
|
||||||
|
es hier nichts zu raten.
|
||||||
|
"""
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
pfad = shutil.which("nginx") or "/usr/sbin/nginx"
|
||||||
|
try:
|
||||||
|
fertig = subprocess.run(
|
||||||
|
[pfad, "-v"], capture_output=True, text=True, timeout=5, check=False
|
||||||
|
)
|
||||||
|
except (OSError, subprocess.SubprocessError):
|
||||||
|
return ()
|
||||||
|
return fassung_aus_ausgabe(fertig.stderr + fertig.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def nginx_kann_http2() -> bool:
|
||||||
|
"""Versteht der installierte nginx ``http2 on;``?"""
|
||||||
|
fassung = nginx_version()
|
||||||
|
return bool(fassung) and fassung >= HTTP2_DIREKTIVE_AB
|
||||||
|
|
||||||
|
|
||||||
def validate_domain(value: str) -> str:
|
def validate_domain(value: str) -> str:
|
||||||
text = (value or "").strip().lower().rstrip(".")
|
text = (value or "").strip().lower().rstrip(".")
|
||||||
if not text:
|
if not text:
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ def _web_config() -> webserver.WebConfig:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
return webserver.WebConfig(
|
return webserver.WebConfig(
|
||||||
|
# Die neue Schreibweise, sobald der Webserver sie kennt.
|
||||||
|
http2_directive=webserver.nginx_kann_http2(),
|
||||||
app_key=extension.config.site_key,
|
app_key=extension.config.site_key,
|
||||||
upstream=str(extension.registry.get("upstream", "127.0.0.1:5000")),
|
upstream=str(extension.registry.get("upstream", "127.0.0.1:5000")),
|
||||||
static_root=str(extension.registry.get("static_root", extension.config.base_dir / "static")),
|
static_root=str(extension.registry.get("static_root", extension.config.base_dir / "static")),
|
||||||
|
|||||||
Reference in new issue
Block a user