From 1f668568d14b1f28be6cb4128f664ad8e395b9ac Mon Sep 17 00:00:00 2001 From: duffyduck Date: Tue, 4 Aug 2026 19:25:42 +0200 Subject: [PATCH] Verweise mit IP statt Hostnamen Auf dem Proxmox-Host loest der Node-Name auf, am Arbeitsplatz meist nicht - und dann ist der noVNC-Verweis wertlos. Die Adresse kommt jetzt aus /etc/pve/.members (lokale Datei, kein API-Aufruf); ist dort nichts zu finden, bleibt es beim Namen. vorher https://pvetest01:8006/?console=kvm&novnc=1&vmid=102&node=pvetest01 nachher https://172.0.4.1:8006/?console=kvm&novnc=1&vmid=102&node=pvetest01 Der Node bleibt als Name im Verweis stehen - so erwartet Proxmox ihn. Dasselbe betraf zwei weitere Stellen: den scp-Hinweis beim SPICE-Befehl und den proxy-Eintrag in der .vv-Datei. Letzterer trug ebenfalls den Hostnamen, womit auch remote-viewer nicht durchgekommen waere. Die TLS-Pruefung laeuft ueber "host-subject" und bleibt davon unberuehrt. Co-Authored-By: Claude Opus 5 (1M context) --- pvesnap/recovery.py | 40 +++++++++++++++++++++++++++++++++++++++- pvesnap/recovery_ui.py | 15 +++++++-------- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/pvesnap/recovery.py b/pvesnap/recovery.py index c60d7db..e5ef171 100644 --- a/pvesnap/recovery.py +++ b/pvesnap/recovery.py @@ -63,6 +63,30 @@ DROP_KEYS = { "replicate", "vmstate", "runningmachine", "runningcpu", } +# Node-Adressen: die Namensaufloesung klappt auf dem Arbeitsplatz haeufig +# nicht, auf dem Proxmox-Host dagegen schon. Ein Link mit Hostnamen ist dann +# unbrauchbar - deshalb wird die IP eingesetzt. +_ADDRESSES = {} + + +def node_address(node): + """IP-Adresse eines Nodes; faellt auf den Namen zurueck.""" + node = str(node or "") + if not node: + return node + if not _ADDRESSES: + try: + with open("/etc/pve/.members", "r", encoding="utf-8") as handle: + data = json.load(handle) + for name, entry in (data.get("nodelist") or {}).items(): + if entry.get("ip"): + _ADDRESSES[name] = entry["ip"] + except (OSError, ValueError, AttributeError) as exc: + log.debug("/etc/pve/.members nicht lesbar: %s", exc) + _ADDRESSES["-"] = "-" # nicht bei jedem Aufruf erneut versuchen + return _ADDRESSES.get(node) or node + + class RecoveryError(Exception): """Eine Wiederherstellung liess sich nicht einrichten.""" @@ -520,9 +544,11 @@ class Instance: self.source, self.snapshot) def console_url(self, host=None): + """noVNC-Adresse. Der Node steht als Name im Verweis - das erwartet + Proxmox so -, die Adresse davor aber als IP.""" kind = "lxc" if self.type == "lxc" else "kvm" return ("https://%s:8006/?console=%s&novnc=1&vmid=%d&node=%s&resize=off&cmd=" - % (host or self.node, kind, self.vmid, self.node)) + % (host or node_address(self.node), kind, self.vmid, self.node)) def to_dict(self): return {k: getattr(self, k) for k in @@ -1190,6 +1216,18 @@ def spice_file(proxmox, instance): "%s liefert keine SPICE-Verbindung. Laeuft die Maschine, und ist " "die SPICE-Anzeige eingeschaltet (vga: qxl)?" % instance.label) + # Derselbe Grund wie beim noVNC-Verweis: der Proxy-Eintrag traegt den + # Hostnamen des Nodes, und wenn der Arbeitsplatz ihn nicht aufloest, + # kommt keine Verbindung zustande. Die TLS-Pruefung laeuft ueber + # "host-subject", nicht ueber diesen Namen - die bleibt also gueltig. + address = node_address(instance.node) + proxy = str(data.get("proxy") or "") + if address != instance.node and proxy: + for name in (instance.node, "%s." % instance.node): + if name in proxy: + data["proxy"] = re.sub(r"//[^:/]+", "//" + address, proxy, count=1) + break + lines = ["[virt-viewer]"] for key in _VV_KEYS: if key in data and data[key] not in (None, ""): diff --git a/pvesnap/recovery_ui.py b/pvesnap/recovery_ui.py index 1a0aeb2..472ac80 100644 --- a/pvesnap/recovery_ui.py +++ b/pvesnap/recovery_ui.py @@ -26,13 +26,12 @@ from .curses_util import (C_DIM, C_FOOTER, C_HEADER, C_MARK, C_OK, C_SEL, C_WARN choose, confirm, fill, init_colors, is_enter, is_escape, keybar, message, prompt, put, read_key) from .proxmox import Proxmox, ProxmoxError, pvesh_available -from .recovery import (RecoveryError, Spec, create, - 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) from . import transfer, transfer_ui +from .recovery import (RecoveryError, Spec, create, destroy, eject_transfer, + find_orphans, flatten, flatten_cost, flatten_hint, + human_bytes, insert_transfer, linked_volumes, + list_instances, node_address, plan, remove_orphans, + spice_file, start, transfer_state) from .snapfs import list_snapshots from .util import truncate @@ -921,8 +920,8 @@ def cmd_spice(proxmox, args): 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) + % (node_address(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)