From 4df994f721324d3c8e0af28ea4bb2de9b1dd0564 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 13 Aug 2026 16:44:27 -0400 Subject: [PATCH] [FIX] todo qemu : lire les distros par arch dans deploy_qemu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit L'ecran de deploiement portait sa PROPRE copie de S390X_DISTROS, sous un commentaire promettant qu'elle restait « coherente avec deploy_qemu.py ». Une copie ne tient aucune promesse : Debian a gagne s390x la-bas et l'ecran ne le proposait toujours pas. _qemu_arch_distros lit desormais ARCH_DISTRO_SUPPORT, et _qemu_arches_for y passe aussi pour que « toutes les architectures » n'offre rien que deploy_qemu refuserait ensuite. Les tuples locaux restent en repli si l'import echoue. L'import est memorise : le catalogue l'interrogeait une fois par couple (distro, version). Plancher memoire de 2048 Mio sur la voie installateur, annonce et jamais abaissant : d-i deplie un systeme de fichiers en RAM la ou une image cloud arrive installee, et le manque s'y voit comme un ecran fige. --- EN --- The deploy screen carried its OWN copy of S390X_DISTROS, under a comment promising it stayed "consistent with deploy_qemu.py". A copy keeps no promise: Debian gained s390x over there and the screen still did not offer it. _qemu_arch_distros now reads ARCH_DISTRO_SUPPORT, and _qemu_arches_for goes through it too, so "all architectures" offers nothing deploy_qemu would later refuse. The local tuples remain as a fallback if the import fails. The import is memoised: the catalogue queried it once per (distro, version) pair. A 2048 MiB memory floor on the installer path, announced and never lowering: d-i unpacks a filesystem into RAM where a cloud image arrives installed, and running short shows up as a frozen screen. Assisted-by: Claude Opus 5 (cherry picked from commit f0ee70c1ac43ba2bc9f5fb78fe71f821a15daf7d) --- script/qemu/deploy_qemu.py | 17 ++++++++++++ script/todo/todo.py | 54 +++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/script/qemu/deploy_qemu.py b/script/qemu/deploy_qemu.py index 57d5176..29a61ee 100755 --- a/script/qemu/deploy_qemu.py +++ b/script/qemu/deploy_qemu.py @@ -203,6 +203,10 @@ ARCH_ONLY_VERSIONS: dict[str, dict[str, tuple[str, ...]]] = { # cloud-init, un disque VIERGE et un amorçage kernel+initrd. INSTALLER_COMBOS: tuple[tuple[str, str], ...] = (("debian", "s390x"),) +# Plancher mémoire de l'installateur : il déplie un système de fichiers entier +# en RAM, là où une image cloud arrive déjà installée. +INSTALLER_MIN_RAM = 2048 + # kernel.debian / initrd.debian du port s390x. « current » suit les mises à # jour de l'installateur sans figer un numéro qui périmerait. INSTALLER_URL = ( @@ -2585,6 +2589,19 @@ def main() -> None: kernel = cache / f"debian-{args.version}-s390x-kernel" initrd_src = cache / f"debian-{args.version}-s390x-initrd.gz" initrd = cache / f"{args.name}-initrd.gz" + # Le dimensionnement du catalogue vient des images cloud, où le + # système est DÉJÀ installé. debian-installer, lui, déplie un système + # de fichiers complet en mémoire avant d'écrire quoi que ce soit : + # 1024 Mio est le plancher annoncé par Debian, sans marge, et un + # manque de mémoire s'y manifeste par un écran figé sans message. + # On relève le plancher, en le disant — un réglage explicite plus haut + # n'est jamais abaissé. + if args.memory < INSTALLER_MIN_RAM: + print( + f" Mémoire portée à {INSTALLER_MIN_RAM} Mio pour" + f" l'installateur (catalogue : {args.memory})." + ) + args.memory = INSTALLER_MIN_RAM print(f"\n== 1/5 Installateur Debian {args.version} ({code}) s390x ==") download_image( [INSTALLER_URL.format(code=code, fichier="kernel.debian")], diff --git a/script/todo/todo.py b/script/todo/todo.py index 9b6ec2a..4a3b38f 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -1087,14 +1087,19 @@ class TODO: print(f"{t('Invalid selection, using')} {default}") return default - # Distros publiant des images cloud par architecture (cohérent avec - # S390X_DISTROS / ARM64_DISTROS de deploy_qemu.py). amd64 : toutes. + # Repli SEULEMENT : la table qui fait autorité est ARCH_DISTRO_SUPPORT de + # deploy_qemu.py, lue par _qemu_arch_distros. Ces tuples ont longtemps été + # une copie à la main, avec le commentaire « cohérent avec deploy_qemu » en + # guise de garantie — et la cohérence a rompu à la première évolution : + # Debian a gagné s390x là-bas sans l'obtenir ici, donc l'écran ne le + # proposait pas. On ne les garde que pour le cas où l'import échoue. _QEMU_S390X_DISTROS = ( "ubuntu", "almalinux", "rocky", "fedora", "opensuse", + "debian", ) _QEMU_ARM64_DISTROS = ( "ubuntu", @@ -1124,12 +1129,24 @@ class TODO: }.get(machine, "amd64") def _qemu_arch_distros(self, arch): - """Distros supportant `arch` (None = toutes, cas amd64).""" - if arch == "s390x": - return self._QEMU_S390X_DISTROS - if arch == "arm64": - return self._QEMU_ARM64_DISTROS - return None + """Distros supportant `arch` (None = toutes, cas amd64). + + Lu dans deploy_qemu.py, qui refuse aussi les combinaisons qu'il + n'annonce pas : une seule table, donc aucun écran ne peut proposer un + choix rejeté ensuite. « amd64 » n'y figure pas et rend None, ce qui + veut bien dire « toutes » — c'est le contrat attendu ici. + """ + try: + table = getattr(self._qemu_import_module(), "ARCH_DISTRO_SUPPORT") + except Exception: + # Repli sur les copies locales : mieux vaut un catalogue figé + # qu'un écran vide si deploy_qemu.py est absent ou cassé. + if arch == "s390x": + return self._QEMU_S390X_DISTROS + if arch == "arm64": + return self._QEMU_ARM64_DISTROS + return None + return table.get(arch) def _qemu_last_run_line(self): """Ligne « dernière install » (distro version [arch] en durée), depuis @@ -4007,13 +4024,22 @@ class TODO: ERPLIBRE_GIT_URL = "https://github.com/erplibre/erplibre" def _qemu_import_module(self): - """Importe deploy_qemu.py comme module (source de vérité des specs).""" + """Importe deploy_qemu.py comme module (source de vérité des specs). + + Mémorisé : le catalogue interroge cette source une fois par couple + (distro, version), et réexécuter un fichier de 2 700 lignes à chaque + passage se voyait à l'écran. + """ + cached = getattr(self, "_qemu_mod_cache", None) + if cached is not None: + return cached import importlib.util path = self._qemu_script_path() spec = importlib.util.spec_from_file_location("deploy_qemu", path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) + self._qemu_mod_cache = mod return mod @classmethod @@ -5844,11 +5870,13 @@ class TODO: « all » = uniquement celles que la distro publie réellement.""" if arch != "all": return [arch] + # Même source que _qemu_arch_distros : « all » ne doit jamais offrir + # une combinaison que deploy_qemu.py refusera. out = ["amd64"] - if distro in self._QEMU_ARM64_DISTROS: - out.append("arm64") - if distro in self._QEMU_S390X_DISTROS: - out.append("s390x") + for a in ("arm64", "s390x"): + supported = self._qemu_arch_distros(a) + if supported and distro in supported: + out.append(a) return out def _qemu_catalog_entries(self, mod, distros, arch):