From 8533690e0e439fc02d576c635cf34850ff49e6cf Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 17 Sep 2026 03:48:09 -0400 Subject: [PATCH] =?UTF-8?q?[FIX]=20proxmox=20:=20porter=20la=20d=C3=A9cisi?= =?UTF-8?q?on=20du=20miroir=20apt=20au=20journal=20de=20la=20VM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les décisions que l'hôte prend avant de lancer sont gardées pour le journal de la VM, celui qu'on rouvre le lendemain quand l'installation a échoué. Celle du miroir apt restait sur la console, qui a défilé depuis. C'est pourtant là qu'on la cherche : le magasin range ses index sous l'HÔTE demandé, et une VM qui en réclame un autre ne retrouve rien de ce qui est gardé — hors ligne, l'installation échoue plus bas sur des dépendances introuvables, un message qui accuse le dépôt et jamais le miroir. Le nom du miroir posé, ou le code de l'échec, rejoignent donc les autres notes. --- EN --- The decisions the host takes before launching are kept for the VM's log, the one reopened the next day when the install has failed. The apt mirror's stayed on the console, which has scrolled away since. Yet that is where it is looked for: the store files its indexes under the HOST asked for, and a VM asking for another finds nothing of what is kept — offline, the install fails further down on unresolvable dependencies, a message that blames the repository and never the mirror. The pinned mirror's name, or the failure's code, therefore join the other notes. Assisted-by: Claude Opus 5 --- script/todo/proxmox_menu.py | 7 +++++-- test/test_proxmox_form.py | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/script/todo/proxmox_menu.py b/script/todo/proxmox_menu.py index d111760..c52299e 100644 --- a/script/todo/proxmox_menu.py +++ b/script/todo/proxmox_menu.py @@ -1980,10 +1980,13 @@ class ProxmoxMenuMixin: " /etc/apt/sources.list.d/*.list 2>/dev/null; true" ) code, _o = self._pve_ssh(cible, geste, timeout=60) + # Au JOURNAL, pas seulement à la console : c'est en rouvrant le + # journal qu'on cherche quel miroir a été posé, le jour où la suite + # échoue sur des dépendances introuvables. if code: - print(f" ⚠ {t('apt mirror not pinned')} ({code})") + self._pve_note(vm, f" ⚠ {t('apt mirror not pinned')} ({code})") return False - print(f" ✓ {t('apt mirror pinned')} : {miroir}") + self._pve_note(vm, f" ✓ {t('apt mirror pinned')} : {miroir}") return True def _pve_set_gpu_groups(self, cible, utilisateur, mod=None): diff --git a/test/test_proxmox_form.py b/test/test_proxmox_form.py index 315e944..afdeab1 100644 --- a/test/test_proxmox_form.py +++ b/test/test_proxmox_form.py @@ -1216,6 +1216,33 @@ class TestLeMiroirAptDesVmProxmox(unittest.TestCase): self.assertIn("archive|security", vu["cmd"]) self.assertNotIn("second.invalid", vu["cmd"]) + def test_the_mirror_decision_reaches_the_log(self): + """La console défile ; le journal est ce qu'on rouvre le lendemain. + + C'est en le rouvrant qu'on cherche quel miroir a été posé, le jour où + l'installation échoue plus bas sur des dépendances introuvables — un + message qui accuse le dépôt, jamais le miroir. Dite à l'écran seule, + la décision manquait à l'endroit exact où on la cherche. + """ + for code, marque, porte in ( + (0, "✓", "miroir.invalid"), + (7, "⚠", "(7)"), + ): + with self.subTest(code=code): + vm = {"distro": "ubuntu", "arch": "amd64"} + self._poser(vm, code=code) + notes = vm.get("notes") or [] + self.assertEqual(len(notes), 1, notes) + self.assertTrue(notes[0].startswith(marque), notes[0]) + self.assertIn(porte, notes[0]) + + def test_the_pinned_mirror_is_named_in_the_log(self): + """« posé » sans dire lequel n'apprend rien : c'est le NOM qu'on + vient chercher.""" + vm = {"distro": "ubuntu", "arch": "amd64"} + self._poser(vm) + self.assertIn("miroir.invalid/ubuntu", (vm["notes"] or [""])[0]) + def test_les_deux_formats_de_sources_sont_couverts(self): """Le « .sources » deb822 des images récentes, et le « sources.list » des anciennes : n'en réécrire qu'un laisse l'autre