SPICE-Anzeige und USB-Weiterleitung fuer Wiederherstellungen
Der Anlass: ein Software-Schutzmodul am USB-Port. Normalerweise haengt so ein Dongle an einem USB-Server im Netz - eine abgeschottete Wiederherstellung hat aber keins. Ueber SPICE kommt das Geraet vom Rechner des Bedieners, nicht ueber das Gastnetz. Die Maschine bleibt also ohne Netzwerk und hat trotzdem ihren Dongle. --spice SPICE-Anzeige (vga: qxl), zusaetzlich zu noVNC --usb <n> so viele USB-Weiterleitungen --iso <volid> Abbild als CD einlegen spice <vmid> Verbindungsdatei fuer remote-viewer (.vv) Zwei Dinge zeigte erst der Test, beide haetten die Sache still unbrauchbar gemacht: vga: qxl zerstoert den geladenen Arbeitsspeicher. qxl hat 64 MB Grafikspeicher, die Vorgabe 16 - beim Laden kommt "Size mismatch: vga.vram", und die Maschine bleibt angehalten stehen. Wieder mit TASK OK. Wird jetzt abgelehnt, mit den drei Auswegen in der Meldung. Der dauerhafte ist, am Original 'vga: qxl' zu setzen - dann tragen alle kuenftigen Snapshots es mit und beides geht gleichzeitig. USB ohne SPICE ist wirkungslos. QEMU legt die usbredir-Geraete zwar an, aber ohne SPICE-Server gibt es keinen Kanal dafuer - spiceproxy sagt schlicht "no spice port". --usb schaltet die Anzeige deshalb mit ein. Ausserdem korrigiert: in der .vv-Datei darf das Zertifikat nicht in echte Zeilenumbrueche uebersetzt werden. virt-viewer erwartet die Zeichenfolge \n als zwei Zeichen in einer einzigen Zeile; sonst steht nur die erste hinter "ca=". tools/get-guest-tools.sh holt virtio-win auf einen ISO-Storage. Fuer den Dongle wird davon nichts gebraucht - die Tools sind nur fuer Zwischenablage, Aufloesung und Mauszeiger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a1076c6641
commit
e88a80cb25
+64
-1
@@ -27,7 +27,8 @@ from .curses_util import (C_DIM, C_FOOTER, C_HEADER, C_MARK, C_OK, C_SEL, C_WARN
|
||||
keybar, message, prompt, put, read_key)
|
||||
from .proxmox import Proxmox, ProxmoxError, pvesh_available
|
||||
from .recovery import (RecoveryError, Spec, create,
|
||||
eject_transfer, insert_transfer, transfer_state,
|
||||
eject_transfer, insert_transfer, spice_file,
|
||||
transfer_state,
|
||||
destroy, find_orphans, flatten, flatten_cost, flatten_hint,
|
||||
human_bytes, linked_volumes, list_instances, plan,
|
||||
remove_orphans, start)
|
||||
@@ -165,6 +166,13 @@ def _fields(guest):
|
||||
if guest.type == "qemu":
|
||||
rows.append(("resume", "Arbeitsspeicher", "choice", RESUME_CHOICES))
|
||||
rows.append(("transfers", "Transfer-Laufwerke", "transfers", ()))
|
||||
if guest.type == "qemu":
|
||||
rows.append(("spice", "SPICE-Anzeige", "choice",
|
||||
((False, "nein - nur noVNC im Browser"),
|
||||
(True, "ja - zusaetzlich remote-viewer"))))
|
||||
rows.append(("usb", "USB-Weiterleitung", "choice",
|
||||
((0, "keine"), (1, "1 Anschluss"), (2, "2 Anschluesse"),
|
||||
(4, "4 Anschluesse"))))
|
||||
rows += [
|
||||
("newid", "Neue VMID", "text", ()),
|
||||
("node", "Node", "text", ()),
|
||||
@@ -214,6 +222,10 @@ def _options(win, guest, spec):
|
||||
"sie standen - ohne Crash-Recovery.",
|
||||
"transfers": "Vorbereitete Austauschmedien. Anlegen und befuellen "
|
||||
"in der Uebersicht mit v .",
|
||||
"spice": "Zweiter Zugang ueber remote-viewer. Achtung: vertraegt "
|
||||
"sich nicht mit geladenem Arbeitsspeicher.",
|
||||
"usb": "Ein USB-Geraet vom eigenen Rechner in den Gast reichen - "
|
||||
"etwa einen Dongle. Laeuft ueber SPICE, nicht ueber das Netz.",
|
||||
"newid": "VMID der neuen Maschine.",
|
||||
"node": "Auf welchem Node sie laufen soll.",
|
||||
"start": "Sofort hochfahren.",
|
||||
@@ -321,6 +333,14 @@ def summary_lines(plan_):
|
||||
% (human_bytes(plan_.vmstate_bytes) or "?")
|
||||
if plan_.resume else "vorhanden, wird aber nicht geladen"),
|
||||
curses.color_pair(C_OK) if plan_.resume else 0))
|
||||
if plan_.spice:
|
||||
lines.append(("Anzeige: noVNC und SPICE (vga: qxl)",
|
||||
curses.color_pair(C_OK)))
|
||||
if plan_.usb:
|
||||
lines.append(("USB: %d Weiterleitung(en) ueber SPICE" % plan_.usb,
|
||||
curses.color_pair(C_OK)))
|
||||
if plan_.iso:
|
||||
lines.append(("CD: %s" % plan_.iso, 0))
|
||||
for volume in plan_.transfers:
|
||||
lines.append(("Transfer: %-14s %8s im Gast als %s"
|
||||
% (volume.name, human_bytes(volume.size), volume.label),
|
||||
@@ -449,6 +469,9 @@ def _details(stdscr, proxmox, instance):
|
||||
if instance.type == "lxc":
|
||||
lines.append((" oder auf dem Host: pct enter %d" % instance.vmid,
|
||||
curses.color_pair(C_MARK)))
|
||||
else:
|
||||
lines.append((" SPICE (remote-viewer): pvesnap-recovery spice %d"
|
||||
% instance.vmid, curses.color_pair(C_MARK)))
|
||||
|
||||
if instance.resumed:
|
||||
lines.append(("", 0))
|
||||
@@ -713,6 +736,9 @@ def _spec_from_args(args, mode):
|
||||
spec.net = args.net or ""
|
||||
spec.resume = args.resume
|
||||
spec.transfers = list(args.transfer or [])
|
||||
spec.spice = bool(getattr(args, "spice", False))
|
||||
spec.usb = int(getattr(args, "usb", 0) or 0)
|
||||
spec.iso = getattr(args, "iso", "") or ""
|
||||
spec.memory = args.memory or 0
|
||||
spec.cores = args.cores or 0
|
||||
spec.name = args.name or ""
|
||||
@@ -877,6 +903,28 @@ def cmd_cleanup(proxmox, args):
|
||||
return 1 if failed else 0
|
||||
|
||||
|
||||
def cmd_spice(proxmox, args):
|
||||
instance = _find_instance(proxmox, args.vmid)
|
||||
text = spice_file(proxmox, instance)
|
||||
if args.output:
|
||||
with open(args.output, "w", encoding="utf-8") as handle:
|
||||
handle.write(text)
|
||||
os.chmod(args.output, 0o600)
|
||||
print(args.output)
|
||||
print("\n Auf dem eigenen Rechner oeffnen:", file=sys.stderr)
|
||||
print(" scp root@%s:%s . && remote-viewer %s"
|
||||
% (instance.node, args.output, os.path.basename(args.output)),
|
||||
file=sys.stderr)
|
||||
else:
|
||||
sys.stdout.write(text)
|
||||
print("\n Umleiten und mit remote-viewer oeffnen:", file=sys.stderr)
|
||||
print(" pvesnap-recovery spice %d -o vm.vv" % instance.vmid,
|
||||
file=sys.stderr)
|
||||
print(" Das Kennwort darin ist ein Einmal-Kennwort und laeuft bald ab.",
|
||||
file=sys.stderr)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_console(proxmox, args):
|
||||
instance = _find_instance(proxmox, args.vmid)
|
||||
print(instance.console_url())
|
||||
@@ -911,6 +959,14 @@ def _add_create_options(parser):
|
||||
help="Arbeitsspeicher des Snapshots laden")
|
||||
parser.add_argument("--no-resume", dest="resume", action="store_false",
|
||||
help="kalt starten, auch wenn der Snapshot RAM enthaelt")
|
||||
parser.add_argument("--spice", action="store_true",
|
||||
help="SPICE-Anzeige einschalten (vga: qxl) - vertraegt "
|
||||
"sich nicht mit geladenem Arbeitsspeicher")
|
||||
parser.add_argument("--usb", type=int, default=0, metavar="ANZAHL",
|
||||
help="so viele USB-Weiterleitungen ueber SPICE, z.B. "
|
||||
"fuer einen Dongle (geht auch mit RAM-Zustand)")
|
||||
parser.add_argument("--iso", metavar="VOLID",
|
||||
help="Abbild als CD einlegen, z.B. local:iso/virtio-win.iso")
|
||||
parser.add_argument("--transfer", action="append", metavar="NAME", default=[],
|
||||
help="vorbereitetes Transfer-Laufwerk anhaengen "
|
||||
"(mehrfach moeglich)")
|
||||
@@ -978,6 +1034,12 @@ def build_parser():
|
||||
sub = subs.add_parser(name, help=helptext)
|
||||
sub.add_argument("vmid", type=int)
|
||||
|
||||
spice = subs.add_parser("spice",
|
||||
help="SPICE-Verbindungsdatei fuer remote-viewer")
|
||||
spice.add_argument("vmid", type=int)
|
||||
spice.add_argument("-o", "--output", metavar="DATEI",
|
||||
help="hineinschreiben statt auf die Ausgabe")
|
||||
|
||||
flatten_ = subs.add_parser(
|
||||
"flatten", help="vom Quell-Snapshot loesen - fuer den Dauerbetrieb")
|
||||
flatten_.add_argument("vmid", type=int)
|
||||
@@ -1020,6 +1082,7 @@ def main(argv=None):
|
||||
"flatten": lambda: cmd_flatten(proxmox, args),
|
||||
"cleanup": lambda: cmd_cleanup(proxmox, args),
|
||||
"console": lambda: cmd_console(proxmox, args),
|
||||
"spice": lambda: cmd_spice(proxmox, args),
|
||||
"start": lambda: cmd_start(proxmox, args),
|
||||
"stop": lambda: cmd_stop(proxmox, args),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user