From 0105cf16e5e95163182b6dbec0d61e1cbaf2be79 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 16 Sep 2026 05:58:59 -0400 Subject: [PATCH] [FIX] cache et guide : suivre la traduction du binaire et le hors ligne MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le rebase apporte trois choses auxquelles ce travail devait s'accorder. Les messages du binaire se traduisent désormais : ceux du refus de place et de l'aide de --oublie passent par T(), avec leur entrée au catalogue — deux garde-fous refusent sinon un message sans traduction ou l'inverse. Soustraire l'hôte au cache est REFUSÉ hors ligne : le magasin est alors la seule source, et l'excepter ne le ferait pas télécharger en direct, cela le priverait de tout, ses propres paquets compris. Et le guide de connexion annonce les outils sur la voie Proxmox aussi ; il n'y était plus écrit du tout, l'argument manquant étant avalé. --- EN --- The rebase brings three things this work had to align with. The binary's messages are now translatable: the out-of-space refusal and the --oublie help go through T(), with their catalogue entry — two guard rails otherwise refuse a message without a translation, or the reverse. Exempting the host from the cache is REFUSED offline: the store is then the only source, and exempting it would not make it download directly, it would leave it with nothing, its own packages included. And the connection guide announces the tools on the Proxmox path too; it was no longer written there at all, the missing argument being swallowed. Assisted-by: Claude Opus 5 --- script/qemu/deploy_qemu.py | 7 ++++++- script/todo/proxmox_menu.py | 27 +++++++++++++++++++++++++-- test/test_proxmox_form.py | 24 ++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/script/qemu/deploy_qemu.py b/script/qemu/deploy_qemu.py index 61020ed..e61caf1 100755 --- a/script/qemu/deploy_qemu.py +++ b/script/qemu/deploy_qemu.py @@ -3594,8 +3594,13 @@ def guide_files(args: argparse.Namespace) -> list[tuple[str, str, str, str]]: args.erplibre_make, editor, bool(args.desktop), + # « getattr » et non « args.vm_tools » : la voie Proxmox + # bâtit ses arguments à la main, et un champ qui lui manque + # ferait avaler le guide par son « except Exception ». tuple( - c.strip() for c in args.vm_tools.split(",") if c.strip() + c.strip() + for c in getattr(args, "vm_tools", "").split(",") + if c.strip() ), ), "", diff --git a/script/todo/proxmox_menu.py b/script/todo/proxmox_menu.py index 13bf1d1..d111760 100644 --- a/script/todo/proxmox_menu.py +++ b/script/todo/proxmox_menu.py @@ -1749,7 +1749,7 @@ class ProxmoxMenuMixin: print(ligne) vm.setdefault("notes", []).append(ligne.strip()) - def _pve_cache_bypass_hote(self, host, vm): + def _pve_cache_bypass_hote(self, host, vm, hors_ligne=False): """Soustrait au cache l'hôte Proxmox qui porte un invité sans magasin. Rend True quand l'exception est en place, False quand il n'y a rien à @@ -1774,7 +1774,16 @@ class ProxmoxMenuMixin: CE QU'ELLE COÛTE. L'exception vaut pour TOUT ce que l'hôte relaie, y compris ses propres téléchargements : il cesse de profiter du cache. C'est le prix, et il est dit plutôt que subi. + + JAMAIS HORS LIGNE. L'amont du cache est alors coupé et le magasin est + la SEULE source : excepter l'hôte ne le ferait pas télécharger en + direct, cela le priverait de tout — ses propres paquets compris. Les + deux issues échouent pour l'invité, mais celle-ci emporte l'hôte avec + lui. On garde donc le cache, et l'avertissement qui suit dit à + l'invité ce qui l'attend. """ + if hors_ligne: + return False try: mod = self._qemu_import_module() except Exception: # pragma: no cover - dépend du module @@ -2040,6 +2049,18 @@ class ProxmoxMenuMixin: ), erplibre_make=self._qemu_make_target(cmd_install), desktop=bool(vm.get("desktop")), + # Les outils que le guide annoncera, FILTRÉS par cette machine + # comme la voie libvirt le fait : en annoncer un que l' + # architecture ou l'absence de bureau écarte enverrait chercher + # une commande qui ne sera jamais posée. + vm_tools=",".join( + self._qemu_tools_for( + spec.get("vm_tools") or (), + vm.get("arch") or "amd64", + bool(vm.get("desktop")), + vm.get("distro") or "", + ) + ), no_git_identity=False, user=spec.get("user") or "erplibre", ) @@ -2295,7 +2316,9 @@ class ProxmoxMenuMixin: # par fichier ne peut RIEN recevoir : on soustrait son # hôte au cache à la place. L'autorité n'est posée que # lorsqu'il y a quelqu'un pour la recevoir. - if not self._pve_cache_bypass_hote(host, vm): + if not self._pve_cache_bypass_hote( + host, vm, hors_ligne=bool(coupee) + ): self._pve_set_cache_ca( vm["alias"], vm, diff --git a/test/test_proxmox_form.py b/test/test_proxmox_form.py index e10dc5a..315e944 100644 --- a/test/test_proxmox_form.py +++ b/test/test_proxmox_form.py @@ -2742,6 +2742,30 @@ class UnInviteImbriqueSortMasqueDerriereSonHote(unittest.TestCase): ) self.assertIn('entry["notes"] = list(notes[name])', dep) + def test_offline_never_exempts(self): + """L'amont du cache est alors coupé et le magasin est la SEULE + source : excepter l'hôte ne le ferait pas télécharger en direct, cela + le priverait de tout — ses propres paquets compris. Les deux issues + échouent pour l'invité, mais celle-ci emporte l'hôte avec lui.""" + import contextlib + import io + import subprocess as sp + + todo = self._todo() + todo._qemu_import_module = lambda: self._Mod + todo._qemu_list_domains = lambda: ["pve-local"] + todo._qemu_domain_mac = lambda nom: "52:54:00:ab:cd:ef" + lance = [] + vrai = sp.run + self.addCleanup(setattr, sp, "run", vrai) + sp.run = lambda c, **k: lance.append(c) + with contextlib.redirect_stdout(io.StringIO()): + rendu = todo._pve_cache_bypass_hote( + {"target": "pve-local"}, {"distro": "nixos"}, hors_ligne=True + ) + self.assertFalse(rendu) + self.assertEqual([], lance, "une exception posée hors ligne") + def test_the_price_is_said(self): """L'exception vaut pour TOUT ce que l'hôte relaie, ses propres téléchargements compris. Le taire ferait chercher plus tard pourquoi