[FIX] proxmox : le rebond est le seul chemin vers la VM
Une VM créée sur l'hôte Proxmox vit derrière lui, sur un pont interne : son adresse n'est pas routable d'ici, et seule l'entrée ~/.ssh/config avec son ProxyJump y mène. Décocher « ajouter une entrée » tout en demandant une installation laissait donc le suivi frapper à une porte qui n'existe pas. L'entrée est maintenant écrite quand une installation ou le suivi la réclame, et on le dit. Sans rien à faire dans la VM, le choix est respecté. Trouvé par l'audit du découpage, pas par l'exécution : c'est un cas que personne n'avait joué. --- EN --- A VM created on the Proxmox host lives behind it, on an internal bridge: its address is not routable from here, and only the ~/.ssh/config entry with its ProxyJump leads there. Unticking "add an entry" while asking for an install therefore left the monitor knocking at a door that does not exist. The entry is now written whenever an install or the dashboard needs it, and we say so. With nothing to do inside the VM, the choice stands. Found by the split's audit, not by running it: nobody had played that case. Assisted-by: Claude Opus 5
This commit is contained in:
parent
ad72f43daa
commit
215b0aac3f
3 changed files with 64 additions and 1 deletions
|
|
@ -987,7 +987,16 @@ class ProxmoxMenuMixin:
|
|||
)
|
||||
continue
|
||||
print(f" ✓ {vm['name']} : {ip}")
|
||||
if spec.get("add_ssh_config"):
|
||||
# L'entrée ~/.ssh/config est le SEUL chemin vers cette VM : elle
|
||||
# est derrière l'hôte Proxmox (pont interne), donc son adresse
|
||||
# n'est pas routable d'ici et seul le rebond y mène. Décochée
|
||||
# alors qu'une installation est demandée, l'installation suivie ne
|
||||
# pouvait pas entrer — elle est donc écrite quand même, et on le
|
||||
# dit. Sans installation ni suivi, le choix est respecté.
|
||||
besoin = bool(spec.get("install")) or spec.get("monitor", True)
|
||||
if not spec.get("add_ssh_config") and besoin:
|
||||
print(f" → {t('~/.ssh/config written anyway (install)')}")
|
||||
if spec.get("add_ssh_config") or besoin:
|
||||
self._write_ssh_config_entry(
|
||||
vm["name"],
|
||||
spec.get("user") or "erplibre",
|
||||
|
|
|
|||
|
|
@ -2290,6 +2290,10 @@ TRANSLATIONS = {
|
|||
"fr": "Aucun affichage ici ; à lancer sur VOTRE poste :",
|
||||
"en": "No display here; run this on YOUR workstation:",
|
||||
},
|
||||
"~/.ssh/config written anyway (install)": {
|
||||
"fr": "entrée ~/.ssh/config écrite quand même : l'installation passe par le rebond",
|
||||
"en": "~/.ssh/config written anyway: the install needs the jump",
|
||||
},
|
||||
"Still on the distribution kernel:": {
|
||||
"fr": "Encore sur le noyau de la distribution :",
|
||||
"en": "Still on the distribution kernel:",
|
||||
|
|
|
|||
|
|
@ -467,6 +467,56 @@ class TestLeSuivi(unittest.TestCase):
|
|||
def test_unticked_and_nothing_to_install_does_nothing(self):
|
||||
self.assertEqual(self._apres_creation(install=None, monitor=False), {})
|
||||
|
||||
def test_the_ssh_entry_is_written_when_the_install_needs_it(self):
|
||||
"""La VM est derrière l'hôte : le rebond de ~/.ssh/config est le SEUL
|
||||
chemin. Décoché alors qu'une installation est demandée, le suivi ne
|
||||
pouvait pas entrer dans la VM."""
|
||||
import contextlib
|
||||
import io
|
||||
import sys
|
||||
|
||||
sys.argv = ["todo.py"]
|
||||
from script.todo.todo import TODO
|
||||
|
||||
def essai(add_ssh_config, install, monitor):
|
||||
todo = TODO.__new__(TODO)
|
||||
ecrites = []
|
||||
todo._write_ssh_config_entry = lambda nom, *a, **k: ecrites.append(
|
||||
nom
|
||||
)
|
||||
todo._ssh_private_key = lambda k: None
|
||||
todo._pve_guest_ip = lambda vmid, attente=120: ""
|
||||
todo._qemu_install_erplibre_monitored = lambda *a, **k: None
|
||||
todo._qemu_install_erplibre_vm = lambda *a, **k: None
|
||||
spec = {
|
||||
"host": {"target": "pve1"},
|
||||
"vms": [
|
||||
{
|
||||
"name": "vm-a",
|
||||
"vmid": 100,
|
||||
"ipconfig": "ip=10.10.10.150/24,gw=10.10.10.1",
|
||||
"install_cmd": "",
|
||||
}
|
||||
],
|
||||
"add_ssh_config": add_ssh_config,
|
||||
"user": "erplibre",
|
||||
"install": install,
|
||||
"monitor": monitor,
|
||||
}
|
||||
with contextlib.redirect_stdout(io.StringIO()):
|
||||
todo._pve_after_create(spec["host"], spec, ["vm-a"], "")
|
||||
return ecrites
|
||||
|
||||
cmd = {"branch": "develop", "cmd": "make x", "label": "X"}
|
||||
# Décoché mais une installation demandée : écrite quand même.
|
||||
self.assertEqual(essai(False, cmd, False), ["vm-a"])
|
||||
# Décoché, suivi demandé : le suivi entre aussi par le rebond.
|
||||
self.assertEqual(essai(False, None, True), ["vm-a"])
|
||||
# Décoché et rien à faire dans la VM : le choix est respecté.
|
||||
self.assertEqual(essai(False, None, False), [])
|
||||
# Coché : écrite, évidemment.
|
||||
self.assertEqual(essai(True, None, False), ["vm-a"])
|
||||
|
||||
def test_ticked_with_an_install_opens_it(self):
|
||||
vus = self._apres_creation(
|
||||
install={"branch": "develop", "cmd": "make x", "label": "X"},
|
||||
|
|
|
|||
Loading…
Reference in a new issue