fix(mounts): mounten() idempotent - stale/tote Mounts vor Re-Mount loesen
Ampel / ampel (push) Successful in 28s
Ampel / ampel (push) Successful in 28s
Folgefix zum remount-Vorfall 24.07.: mounten() fiel bei einem TOTEN Mount (os.path.ismount wirft OSError) auf den echten `mount` durch und stapelte auf die Leiche. Ueber viele Neustarts (via rshared propagiert, ueberlebt Container-Recreate) wuchs das auf 12 Schichten; die tote oberste blockierte jeden Zugriff (ls-Timeout, obwohl SMB-445 offen) -> Medien-Mount unbrauchbar. Fix: _stale_mounts_loesen(ziel) loest per lazy `umount -l` alle Schichten, bevor neu gemountet wird -> kein Stapeln mehr, Re-Mount idempotent. Ein gesunder Mount wird weiterhin frueh erkannt (os.path.ismount) und unangetastet gelassen. Tests (test_mounts_helpers.py): Loesch-Schleife bis leer (monkeypatch) + Verdrahtung. Ruff gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+29
-1
@@ -73,6 +73,30 @@ def schreibtest(pfad: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _stale_mounts_loesen(ziel: str) -> int:
|
||||
"""Loest ALLE (evtl. gestapelten/toten) Mounts an `ziel` per lazy umount.
|
||||
|
||||
Warum: mounten() faellt bei einem TOTEN Mount (os.path.ismount wirft OSError)
|
||||
auf den echten `mount` durch — der stapelt dann auf die Leiche. Vorfall 24.07.:
|
||||
ueber viele Neustarts 12 Schichten, die tote oberste blockierte jeden Zugriff
|
||||
(ls-Timeout, obwohl SMB-445 offen). Erst alle Schichten loesen macht das
|
||||
Re-Mounten idempotent. `umount -l` (lazy) haengt nicht an einem toten CIFS.
|
||||
Rueckgabe: Zahl der geloesten Schichten.
|
||||
"""
|
||||
geloest = 0
|
||||
for _ in range(20): # harte Obergrenze gegen Endlosschleife
|
||||
try:
|
||||
ergebnis = subprocess.run(
|
||||
["umount", "-l", ziel], capture_output=True, timeout=10
|
||||
)
|
||||
except (OSError, subprocess.TimeoutExpired):
|
||||
break
|
||||
if ergebnis.returncode != 0:
|
||||
break # nichts (mehr) gemountet
|
||||
geloest += 1
|
||||
return geloest
|
||||
|
||||
|
||||
def uebersetze_smb_fehler(fehler: str, mit_credentials: bool) -> str:
|
||||
"""Pure Funktion (testbar): NT_STATUS-Kauderwelsch → handelbarer Klartext.
|
||||
|
||||
@@ -155,7 +179,11 @@ def mounten(name: str, typ: str, quelle: str, optionen: str = "",
|
||||
if os.path.ismount(ziel):
|
||||
return schreibtest(ziel)
|
||||
except OSError:
|
||||
pass # toter Mount → als „nicht gemountet" behandeln und neu mounten
|
||||
pass # toter Mount → unten erst lösen, dann frisch mounten (kein Stapeln)
|
||||
|
||||
# Idempotent: etwaige (auch gestapelte/tote) Alt-Mounts erst lösen, damit der
|
||||
# folgende mount NICHT auf eine Leiche stapelt (Vorfall 24.07.: 12 Schichten).
|
||||
_stale_mounts_loesen(ziel)
|
||||
|
||||
creds_datei = None
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user