Explorer: aus dem Dateibrowser zurueck in die Auswahl statt beenden
Bisher endete das Programm, sobald man den Dateibrowser verliess - wollte man einen zweiten Snapshot ansehen, musste man es neu starten und sich wieder durch Gast und Snapshot klicken. Jetzt gibt es drei Ebenen, aus denen q oder F10 jeweils eine zurueckfuehrt: Gastauswahl -> Snapshot-Auswahl -> Dateibrowser Beim Verlassen des Browsers wird der Snapshot ausgehaengt, bevor die Snapshot-Liste wieder erscheint - dort steht dann auch, was in der Zwischenzeit dazugekommen ist. Aus der Snapshot-Liste geht es zurueck zur Gastauswahl, deren Inventar dabei ebenfalls neu gelesen wird. Das rechte Fenster behaelt sein Verzeichnis ueber mehrere Snapshots hinweg, damit man aus verschiedenen Snapshots ins selbe Ziel sammeln kann. Auf pvetest01 gegen echte Snapshots geprueft: beim Wechsel wird der erste Snapshot restlos abgebaut, bevor der zweite eingebunden wird (nie mehr als eine Einbindung gleichzeitig), und der regulaere Ausstieg hinterlaesst weder rbd-Maps noch Mountpunkte. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
700492391a
commit
91bfdea76c
@@ -373,7 +373,13 @@ Links der Snapshot, rechts der lokale Rechner:
|
|||||||
| `F7` / `n` | neues Verzeichnis (nur lokal) |
|
| `F7` / `n` | neues Verzeichnis (nur lokal) |
|
||||||
| `F6` / `g` | Verzeichnis direkt eingeben |
|
| `F6` / `g` | Verzeichnis direkt eingeben |
|
||||||
| `F2` / `m` | anderes Dateisystem des Snapshots wählen |
|
| `F2` / `m` | anderes Dateisystem des Snapshots wählen |
|
||||||
| `F10` / `q` | beenden |
|
| `F10` / `q` | eine Ebene zurück (Snapshot wird ausgehängt) |
|
||||||
|
|
||||||
|
Der Explorer hat drei Ebenen: **Gastauswahl → Snapshot-Auswahl → Dateien**. Mit
|
||||||
|
`q` geht es jeweils eine Ebene zurück; beim Verlassen des Dateibrowsers wird der
|
||||||
|
Snapshot wieder ausgehängt, sodass man gleich den nächsten öffnen kann. Das
|
||||||
|
rechte Fenster behält dabei sein Verzeichnis — praktisch, wenn man aus mehreren
|
||||||
|
Snapshots ins selbe Zielverzeichnis sammelt.
|
||||||
|
|
||||||
Kopiert wird immer vom aktiven ins andere Fenster — in den Snapshot hinein geht
|
Kopiert wird immer vom aktiven ins andere Fenster — in den Snapshot hinein geht
|
||||||
nichts, er ist schreibgeschützt. Beim Kopieren gibt es einen Fortschrittsbalken,
|
nichts, er ist schreibgeschützt. Beim Kopieren gibt es einen Fortschrittsbalken,
|
||||||
|
|||||||
+77
-36
@@ -3,6 +3,10 @@
|
|||||||
Zwei Fenster wie im Midnight Commander: links der geoeffnete Snapshot
|
Zwei Fenster wie im Midnight Commander: links der geoeffnete Snapshot
|
||||||
(schreibgeschuetzt), rechts der lokale Rechner. Markieren, F5 - fertig.
|
(schreibgeschuetzt), rechts der lokale Rechner. Markieren, F5 - fertig.
|
||||||
|
|
||||||
|
Drei Ebenen, aus denen man mit q jeweils eine zurueckkommt:
|
||||||
|
Gastauswahl -> Snapshot-Auswahl -> Dateibrowser. Beim Verlassen des
|
||||||
|
Browsers wird der Snapshot wieder ausgehaengt.
|
||||||
|
|
||||||
pvesnap-explorer Gast und Snapshot auswaehlen
|
pvesnap-explorer Gast und Snapshot auswaehlen
|
||||||
pvesnap-explorer 802 Snapshot von VM 802 auswaehlen
|
pvesnap-explorer 802 Snapshot von VM 802 auswaehlen
|
||||||
pvesnap-explorer 802 <snapname> direkt oeffnen
|
pvesnap-explorer 802 <snapname> direkt oeffnen
|
||||||
@@ -43,7 +47,7 @@ KEYS = [
|
|||||||
("F3", "Ansehen", "Ansehen"),
|
("F3", "Ansehen", "Ansehen"),
|
||||||
("F7", "Neuer Ordner", "Ordner"),
|
("F7", "Neuer Ordner", "Ordner"),
|
||||||
("F2", "Laufwerk", "Laufw."),
|
("F2", "Laufwerk", "Laufw."),
|
||||||
("F10", "Ende", "Ende"),
|
("F10", "Zurueck", "Zurueck"),
|
||||||
]
|
]
|
||||||
|
|
||||||
COPY_BUFFER = 1024 * 1024
|
COPY_BUFFER = 1024 * 1024
|
||||||
@@ -542,7 +546,7 @@ class Explorer:
|
|||||||
elif key in (curses.KEY_F10, "q", "Q"):
|
elif key in (curses.KEY_F10, "q", "Q"):
|
||||||
return
|
return
|
||||||
elif is_escape(key):
|
elif is_escape(key):
|
||||||
if confirm(win, "Explorer beenden?"):
|
if confirm(win, "Snapshot schliessen und zurueck zur Auswahl?"):
|
||||||
return
|
return
|
||||||
|
|
||||||
# -- Aktionen ---------------------------------------------------------
|
# -- Aktionen ---------------------------------------------------------
|
||||||
@@ -719,12 +723,17 @@ class Explorer:
|
|||||||
"F6 / g Verzeichnis direkt eingeben",
|
"F6 / g Verzeichnis direkt eingeben",
|
||||||
"F2 / m anderes Dateisystem des Snapshots waehlen",
|
"F2 / m anderes Dateisystem des Snapshots waehlen",
|
||||||
"r neu einlesen",
|
"r neu einlesen",
|
||||||
"F10 / q beenden",
|
"F10 / q zurueck zur Snapshot-Auswahl",
|
||||||
"",
|
"",
|
||||||
"Der Snapshot ist schreibgeschuetzt eingebunden - es kann nichts",
|
"Der Snapshot ist schreibgeschuetzt eingebunden - es kann nichts",
|
||||||
"kaputtgehen. Kopiert wird immer vom aktiven ins andere Fenster.",
|
"kaputtgehen. Kopiert wird immer vom aktiven ins andere Fenster.",
|
||||||
"Geraetedateien und Sockets werden uebersprungen, symbolische",
|
"Geraetedateien und Sockets werden uebersprungen, symbolische",
|
||||||
"Verweise bleiben Verweise.",
|
"Verweise bleiben Verweise.",
|
||||||
|
"",
|
||||||
|
"Es gibt drei Ebenen: Gastauswahl -> Snapshot-Auswahl -> Dateien.",
|
||||||
|
"F10 oder q geht jeweils eine Ebene zurueck; der Snapshot wird",
|
||||||
|
"dabei wieder ausgehaengt. Das rechte Fenster behaelt sein",
|
||||||
|
"Verzeichnis, auch wenn man den naechsten Snapshot oeffnet.",
|
||||||
]
|
]
|
||||||
height, width = win.getmaxyx()
|
height, width = win.getmaxyx()
|
||||||
win.erase()
|
win.erase()
|
||||||
@@ -755,7 +764,7 @@ def _pick_guest(win, guests):
|
|||||||
% ("LXC" if g.type == "lxc" else "VM ", g.vmid,
|
% ("LXC" if g.type == "lxc" else "VM ", g.vmid,
|
||||||
truncate(g.name or "-", 24), g.status, g.node))
|
truncate(g.name or "-", 24), g.status, g.node))
|
||||||
for g in guests]
|
for g in guests]
|
||||||
return choose(win, "Welcher Gast?", entries)
|
return choose(win, "Welcher Gast? (Esc beendet)", entries)
|
||||||
|
|
||||||
|
|
||||||
def _pick_snapshot(win, snapshots):
|
def _pick_snapshot(win, snapshots):
|
||||||
@@ -766,7 +775,7 @@ def _pick_snapshot(win, snapshots):
|
|||||||
entries.append((snap.name, "%-34s %s %s"
|
entries.append((snap.name, "%-34s %s %s"
|
||||||
% (truncate(snap.name, 34), when,
|
% (truncate(snap.name, 34), when,
|
||||||
truncate(snap.description.replace("\n", " "), 40))))
|
truncate(snap.description.replace("\n", " "), 40))))
|
||||||
return choose(win, "Welcher Snapshot?", entries)
|
return choose(win, "Welcher Snapshot? (Esc = zurueck zur Gastauswahl)", entries)
|
||||||
|
|
||||||
|
|
||||||
def _wait_screen(win, text):
|
def _wait_screen(win, text):
|
||||||
@@ -817,41 +826,71 @@ def _main(stdscr, args):
|
|||||||
message(stdscr, "Keine VMs oder Container gefunden.", error=True)
|
message(stdscr, "Keine VMs oder Container gefunden.", error=True)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if args.vmid:
|
# Drei Ebenen, aus denen man jeweils eine zurueckkommt:
|
||||||
guest = next((g for g in guests if g.vmid == args.vmid), None)
|
# Gastauswahl -> Snapshot-Auswahl -> Dateibrowser
|
||||||
if guest is None:
|
# Der Snapshot wird beim Verlassen des Browsers wieder ausgehaengt, damit
|
||||||
message(stdscr, "Gast %d nicht gefunden." % args.vmid, error=True)
|
# man gleich den naechsten oeffnen kann.
|
||||||
return 2
|
wanted_vmid, wanted_snapshot = args.vmid, args.snapshot
|
||||||
else:
|
|
||||||
guest = _pick_guest(stdscr, guests)
|
|
||||||
if guest is None:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
_wait_screen(stdscr, "Lese Snapshots von %s ..." % guest.label)
|
while True:
|
||||||
snapshots = list_snapshots(proxmox, guest)
|
if wanted_vmid:
|
||||||
if not snapshots:
|
guest = next((g for g in guests if g.vmid == wanted_vmid), None)
|
||||||
message(stdscr, "%s hat keine Snapshots." % guest.label, error=True)
|
wanted_vmid = None
|
||||||
return 1
|
if guest is None:
|
||||||
|
message(stdscr, "Gast %d nicht gefunden." % args.vmid, error=True)
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
guest = _pick_guest(stdscr, guests)
|
||||||
|
if guest is None:
|
||||||
|
return 0
|
||||||
|
|
||||||
if args.snapshot:
|
while True:
|
||||||
name = next((s.name for s in snapshots if s.name == args.snapshot), None)
|
_wait_screen(stdscr, "Lese Snapshots von %s ..." % guest.label)
|
||||||
if name is None:
|
try:
|
||||||
message(stdscr, "Snapshot %r nicht gefunden." % args.snapshot, error=True)
|
snapshots = list_snapshots(proxmox, guest)
|
||||||
return 2
|
except ProxmoxError as exc:
|
||||||
else:
|
message(stdscr, str(exc), error=True)
|
||||||
name = _pick_snapshot(stdscr, snapshots)
|
break
|
||||||
if name is None:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
session = Session(proxmox, guest, name)
|
if wanted_snapshot:
|
||||||
|
name = next((s.name for s in snapshots if s.name == wanted_snapshot), None)
|
||||||
|
if name is None:
|
||||||
|
message(stdscr, "Snapshot %r nicht gefunden."
|
||||||
|
% wanted_snapshot, error=True)
|
||||||
|
wanted_snapshot = None
|
||||||
|
if name is None:
|
||||||
|
continue
|
||||||
|
elif not snapshots:
|
||||||
|
message(stdscr, "%s hat keine Snapshots." % guest.label, error=True)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
name = _pick_snapshot(stdscr, snapshots)
|
||||||
|
if name is None:
|
||||||
|
break # zurueck zur Gastauswahl
|
||||||
|
|
||||||
|
_browse(stdscr, proxmox, guest, name, local)
|
||||||
|
|
||||||
|
# Beim Zurueckkommen kann sich das Inventar geaendert haben.
|
||||||
|
_wait_screen(stdscr, "Frage Proxmox nach VMs und Containern ...")
|
||||||
|
try:
|
||||||
|
guests = proxmox.inventory(refresh=True)
|
||||||
|
except ProxmoxError as exc:
|
||||||
|
message(stdscr, str(exc), error=True)
|
||||||
|
return 3
|
||||||
|
|
||||||
|
|
||||||
|
def _browse(stdscr, proxmox, guest, snapname, local):
|
||||||
|
"""Einen Snapshot einbinden, durchsehen und wieder aushaengen."""
|
||||||
|
session = Session(proxmox, guest, snapname)
|
||||||
try:
|
try:
|
||||||
_wait_screen(stdscr, "Binde Snapshot '%s' ein - das kann etwas dauern ..." % name)
|
_wait_screen(stdscr,
|
||||||
|
"Binde Snapshot '%s' ein - das kann etwas dauern ..." % snapname)
|
||||||
session.open()
|
session.open()
|
||||||
session.prepare()
|
session.prepare()
|
||||||
except (SnapfsError, ProxmoxError) as exc:
|
except (SnapfsError, ProxmoxError) as exc:
|
||||||
session.close()
|
session.close()
|
||||||
_show_notes(stdscr, str(exc).splitlines() + session.notes, "Fehlgeschlagen")
|
_show_notes(stdscr, str(exc).splitlines() + session.notes, "Fehlgeschlagen")
|
||||||
return 3
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_show_notes(stdscr, session.notes)
|
_show_notes(stdscr, session.notes)
|
||||||
@@ -860,19 +899,21 @@ def _main(stdscr, args):
|
|||||||
_show_notes(stdscr,
|
_show_notes(stdscr,
|
||||||
["Es wurde kein Dateisystem eingehaengt."] + session.notes,
|
["Es wurde kein Dateisystem eingehaengt."] + session.notes,
|
||||||
"Nichts zu zeigen")
|
"Nichts zu zeigen")
|
||||||
return 3
|
return
|
||||||
|
|
||||||
start = entries[0][0]
|
start = entries[0][0]
|
||||||
if len(entries) > 1:
|
if len(entries) > 1:
|
||||||
start = choose(stdscr, "Welches Dateisystem zuerst?", entries) or start
|
start = choose(stdscr, "Welches Dateisystem zuerst?", entries)
|
||||||
|
if start is None:
|
||||||
|
return # zurueck zur Snapshot-Auswahl
|
||||||
|
|
||||||
left = Pane(path=start, root=start, readonly=True,
|
left = Pane(path=start, root=start, readonly=True,
|
||||||
title="%s @ %s" % (guest.label, name))
|
title="%s @ %s" % (guest.label, snapname))
|
||||||
Explorer(left, local, session=session,
|
Explorer(left, local, session=session,
|
||||||
subtitle="%s - Snapshot %s" % (guest.label, name)).run(stdscr)
|
subtitle="%s - Snapshot %s" % (guest.label, snapname)).run(stdscr)
|
||||||
finally:
|
finally:
|
||||||
_wait_screen(stdscr, "Haenge Snapshot wieder aus ...")
|
_wait_screen(stdscr, "Haenge Snapshot wieder aus ...")
|
||||||
session.close()
|
session.close()
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def build_parser():
|
def build_parser():
|
||||||
|
|||||||
Reference in New Issue
Block a user