Lokales Fenster war nicht navigierbar; halbfertige Snapshots erkennen
Zwei gemeldete Fehler.
1. Im rechten Fenster des Explorers liessen sich weder Verzeichnisse
oeffnen noch ".." benutzen. Die Pruefung "bleibt der Pfad innerhalb der
Wurzel?" haengte an die Wurzel ein "/" an - bei der Wurzel "/" des
lokalen Fensters wurde daraus "//", worauf kein Pfad passt. Damit gab
open_current() immer False zurueck. Die Pruefung steckt jetzt in
within() und behandelt diesen Fall; die Web-Oberflaeche benutzt
dieselbe Funktion.
2. "Snapshots vom LXC aufrufen geht nicht": der Container hatte gar keine
brauchbaren Snapshots. In seiner Konfiguration standen nur zwei
Eintraege mit snapstate "prepare" und "delete" - Reste aus der Zeit, in
der jeder Snapshot am cfs-Lock scheiterte. Auf dem Storage liegt
dahinter nichts (rbd snap ls ist leer), oeffnen kann man sie also
nicht.
Solche Eintraege werden jetzt als das behandelt, was sie sind:
* Explorer und Web-Oberflaeche bieten sie nicht mehr zum Oeffnen an
und nennen den Aufraeumbefehl.
* "pvesnap list" markiert sie mit "!".
* Beim Aufraeumen entfernt der Dienst sie zuerst, und zwar mit
--force, weil sich ein Eintrag ohne Storage-Snapshot sonst nicht
loeschen laesst. Vorher waeren sie ewig liegen geblieben und haetten
zusaetzlich die Zahl der behaltenen Snapshots verfaelscht.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
963463a1a1
commit
3acbebce6f
+26
-3
@@ -57,6 +57,18 @@ COPY_BUFFER = 1024 * 1024
|
||||
# Eintraege und Fenster
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def within(root, path):
|
||||
"""Liegt `path` innerhalb von `root`?
|
||||
|
||||
Wichtig ist der Sonderfall root="/" (das lokale Fenster darf ueberall
|
||||
hin): dort ist root + "/" gleich "//", worauf kein einziger Pfad passt.
|
||||
"""
|
||||
root = os.path.realpath(root)
|
||||
path = os.path.realpath(path)
|
||||
prefix = root if root.endswith(os.sep) else root + os.sep
|
||||
return path == root or path.startswith(prefix)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Entry:
|
||||
name: str
|
||||
@@ -154,8 +166,7 @@ class Pane:
|
||||
if not entry.is_dir:
|
||||
return False
|
||||
target = os.path.realpath(entry.path)
|
||||
root = os.path.realpath(self.root)
|
||||
if not (target == root or target.startswith(root + os.sep)):
|
||||
if not within(self.root, target):
|
||||
return False # nicht aus dem Snapshot herauslaufen
|
||||
self.path = target
|
||||
self.marks.clear()
|
||||
@@ -772,6 +783,8 @@ def _pick_snapshot(win, snapshots):
|
||||
for snap in snapshots:
|
||||
when = (datetime.fromtimestamp(snap.snaptime).strftime("%d.%m.%Y %H:%M")
|
||||
if snap.snaptime else "?")
|
||||
if not getattr(snap, "complete", True):
|
||||
continue
|
||||
entries.append((snap.name, "%-34s %s %s"
|
||||
% (truncate(snap.name, 34), when,
|
||||
truncate(snap.description.replace("\n", " "), 40))))
|
||||
@@ -852,6 +865,9 @@ def _main(stdscr, args):
|
||||
message(stdscr, str(exc), error=True)
|
||||
break
|
||||
|
||||
broken = [s for s in snapshots if not s.complete]
|
||||
snapshots = [s for s in snapshots if s.complete]
|
||||
|
||||
if wanted_snapshot:
|
||||
name = next((s.name for s in snapshots if s.name == wanted_snapshot), None)
|
||||
if name is None:
|
||||
@@ -861,7 +877,14 @@ def _main(stdscr, args):
|
||||
if name is None:
|
||||
continue
|
||||
elif not snapshots:
|
||||
message(stdscr, "%s hat keine Snapshots." % guest.label, error=True)
|
||||
text = "%s hat keine Snapshots." % guest.label
|
||||
if broken:
|
||||
text += (" %d halbfertige(r) Eintrag/Eintraege aus abgebrochenen "
|
||||
"Laeufen sind vorhanden - aufraeumen mit: %s delsnapshot "
|
||||
"%d <name> --force"
|
||||
% (len(broken), "pct" if guest.type == "lxc" else "qm",
|
||||
guest.vmid))
|
||||
message(stdscr, text, error=True)
|
||||
break
|
||||
else:
|
||||
name = _pick_snapshot(stdscr, snapshots)
|
||||
|
||||
Reference in New Issue
Block a user