From c3e0d5521ef7f4ae41ca9cf4b919a91b8e952ad6 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 9 Aug 2026 09:59:28 +0200 Subject: [PATCH] Zwei Funktionen waren beim Ausbauen mit weggeschnitten worden Beim Entfernen des alten Austauschlaufwerks habe ich Textbereiche zwischen zwei Marken herausgeschnitten - und dabei zwei Funktionen mitgenommen, die zufaellig darin lagen: _swap() Auswerfen und Einklinken in der Detailansicht. Taste e endete in "NameError: name '_swap' is not defined". cmd_flatten() der gesamte Unterbefehl "flatten" haette beim Aufruf abgebrochen - unbemerkt, weil ihn danach niemand mehr aufgerufen hat. Beide sind wieder da. Dass es beim Uebersetzen nicht auffiel, liegt an Python: ein Name, der erst zur Laufzeit nachgeschlagen wird, stoert den Compiler nicht. Gefunden mit einem Abgleich aller geladenen gegen alle definierten Namen je Modul - der haette beide Faelle sofort gezeigt. Co-Authored-By: Claude Opus 5 (1M context) --- pvesnap/recovery_ui.py | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/pvesnap/recovery_ui.py b/pvesnap/recovery_ui.py index 472ac80..9a4b17f 100644 --- a/pvesnap/recovery_ui.py +++ b/pvesnap/recovery_ui.py @@ -553,6 +553,36 @@ def _do(stdscr, text, action): message(stdscr, hint, error=True) +def _swap(stdscr, proxmox, instance, steckplaetze): + """Transfer-Laufwerk im laufenden Betrieb abziehen oder wieder einklinken.""" + wechselbar = [(e, drin) for e, drin in steckplaetze if e.get("kind") != "bind"] + if not wechselbar: + message(stdscr, "Hier gibt es nichts zu wechseln - durchgereichte " + "Verzeichnisse bleiben, wie sie sind.", error=True) + return + + if len(wechselbar) == 1: + entry, drin = wechselbar[0] + else: + gewaehlt = choose(stdscr, "Welches Laufwerk?", + [((e, d), "%-14s %s" + % (e["name"], "eingesteckt" if d else "ausgeworfen")) + for e, d in wechselbar]) + if gewaehlt is None: + return + entry, drin = gewaehlt + + name = entry["name"] + if drin: + if not confirm(stdscr, "%r auswerfen? Im Gast vorher aushaengen!" % name): + return + _do(stdscr, "Werfe %r aus ..." % name, + lambda: eject_transfer(proxmox, instance, name)) + else: + _do(stdscr, "Klinke %r ein ..." % name, + lambda: insert_transfer(proxmox, instance, name)) + + def _flatten(stdscr, proxmox, instance, linked): if not linked: message(stdscr, "%s haengt an keinem Snapshot mehr." % instance.label) @@ -870,6 +900,37 @@ def cmd_destroy(proxmox, args): return 0 +def cmd_flatten(proxmox, args): + instance = _find_instance(proxmox, args.vmid) + linked = linked_volumes(proxmox, instance) + if not linked: + print("%s haengt an keinem Snapshot mehr - nichts zu tun." % instance.label) + return 0 + + print("%s loest sich von %s." % (instance.label, instance.origin)) + for volid in linked: + print(" %s" % volid) + cost = flatten_cost(proxmox, instance) + print("\nDabei werden die Daten wirklich kopiert%s." + % ((" - rund %s" % human_bytes(cost)) if cost else "")) + if not args.yes: + if _ask("Jetzt loesen? [j/N] ") not in ("j", "y", "ja", "yes"): + print("Abgebrochen.") + return 1 + + done, already, other = flatten(proxmox, instance, stream=True, force=args.force, + progress=lambda text: print(" " + text)) + print("\n%d Datentraeger geloest." % len(done)) + for volid in already: + print(" war schon eigenstaendig: %s" % volid) + for volid in other: + print(" %s: %s" % (volid, flatten_hint(proxmox, volid))) + if not linked_volumes(proxmox, instance): + print("\n%s ist jetzt eigenstaendig. Die Snapshots des Originals lassen " + "sich wieder loeschen." % instance.label) + return 0 + + def cmd_cleanup(proxmox, args): orphans = find_orphans(proxmox) if not orphans: