umbau 1.3

This commit is contained in:
2026-09-03 08:01:27 +02:00
parent 13542163d8
commit 96d9f331b5
10 changed files with 654 additions and 44 deletions

View File

@ -63,15 +63,57 @@ _TIMEZONE_RE = re.compile(r"^[A-Za-z0-9_+\-]+(/[A-Za-z0-9_+\-]+)*$")
async def _cleanup_rdp_drive_path(host_id: int, session_id: int) -> None:
"""Entfernt das pro Sitzung umgeleitete RDP-Laufwerk beim Sitzungsende
(Befund E6, Umsetzungsauftrag Teil E) -- sonst sammeln sich pro Sitzung
Verzeichnisse unbegrenzt an. shutil.rmtree ist blockierendes Datei-I/O
(siehe E.0) und laeuft deshalb in einem Thread statt direkt im
Event-Loop."""
"""Bester Versuch, das pro Sitzung umgeleitete RDP-Laufwerk beim
Sitzungsende zu entfernen (Befund E6, Umsetzungsauftrag Teil E).
WICHTIG (Korrektur nach Live-Test 3.9.): dieser Aufruf ist NICHT der
eigentliche Aufraeummechanismus und kann es auch nicht sein. Der
App-Prozess laeuft als "jumphost" und hat auf
{data_dir}/rdp-drives (0750 guacd:guacd) sowie auf die darin von guacd
selbst angelegten Sitzungsverzeichnisse (0700 guacd:guacd, guacd ruft
mkdir mit S_IRWXU auf, die guacd-Unit setzt zusaetzlich UMask=0077)
keinerlei Zugriff -- rmtree scheitert hier zwangslaeufig mit EACCES.
Die vorherige Fassung rief `shutil.rmtree(path, True)` auf. Das zweite
Positionsargument von rmtree ist `ignore_errors`; mit ignore_errors=True
wird der PermissionError INNERHALB von rmtree abgefangen, der
`except OSError`-Zweig darunter also nie erreicht. Ergebnis: kein
Logeintrag, keine Fehlermeldung -- und die Sitzungsverzeichnisse samt
der darin uebertragenen Dateien blieben seit Inbetriebnahme unbegrenzt
liegen, obwohl Befund E6 als erledigt galt.
Tatsaechlich aufgeraeumt wird jetzt durch scripts/cleanup_rdp_drives.py,
das ein systemd-Timer als root ausfuehrt (siehe
ansible/roles/jumphost_app) und das nur Verzeichnisse entfernt, deren
Sitzung in der Datenbank als beendet markiert ist. Der Versuch hier
bleibt trotzdem stehen: laeuft die App in einer anderen Aufstellung
(Entwicklungsumgebung, Testsuite, gemeinsamer Benutzer fuer App und
guacd), raeumt er sofort auf statt erst beim naechsten Timerlauf.
shutil.rmtree ist blockierendes Datei-I/O (siehe E.0) und laeuft deshalb
in einem Thread statt direkt im Event-Loop.
"""
path = rdp_drive_path(host_id, session_id)
try:
await asyncio.to_thread(shutil.rmtree, path, True)
# ignore_errors NICHT setzen -- Fehler sollen hier sichtbar sein,
# statt wie zuvor stillschweigend in rmtree zu verschwinden.
await asyncio.to_thread(shutil.rmtree, path)
except FileNotFoundError:
# Regelfall bei abgeschalteter Laufwerksumleitung: guacd hat nie ein
# Verzeichnis angelegt. Kein Fehler.
pass
except PermissionError:
# Der in der Produktivaufstellung ERWARTETE Fall (siehe Docstring).
# Bewusst DEBUG statt WARNING: sonst stuende bei jeder einzelnen
# Sitzung eine Warnung im Log, die keinerlei Handlung erfordert --
# zustaendig ist der Timer.
logger.debug(
"RDP-Laufwerksverzeichnis %s bleibt liegen (erwartet: keine Rechte "
"als App-Benutzer); Aufraeumen uebernimmt jumphost-rdp-drives-cleanup.timer",
path,
)
except OSError:
# Alles Uebrige ist unerwartet und gehoert sichtbar ins Log.
logger.warning(
"Konnte RDP-Laufwerksverzeichnis fuer Sitzung %s (Host %s) nicht entfernen: %s",
session_id, host_id, path, exc_info=True,