diff --git a/script/todo/qemu_install_monitor.py b/script/todo/qemu_install_monitor.py index ad0370b..16d13f1 100644 --- a/script/todo/qemu_install_monitor.py +++ b/script/todo/qemu_install_monitor.py @@ -89,22 +89,50 @@ def _launch_one(ip: str, remote_cmd: str, log_path: str) -> None: ) +def _log_header(vm: dict, branch: str, when: str) -> str: + """En-tête du log : date, VM, distribution, version, architecture, branche. + Permet d'identifier l'installation d'un coup d'œil (et de ne jamais laisser + le log vide pendant l'attente du boot).""" + distro = vm.get("distro") or "?" + version = vm.get("version") or "" + arch = vm.get("arch") or "?" + bar = "=" * 64 + return ( + f"{bar}\n" + f" ERPLibre — {t('installation')}\n" + f" Date : {when}\n" + f" VM : {vm['name']}\n" + f" Distribution : {distro} {version}\n" + f" Architecture : {arch}\n" + f" Branche : {branch}\n" + f" IP : {vm['ip']}\n" + f"{bar}\n\n" + ) + + def launch_installs(vms: list[dict], branch: str, remote_cmd: str) -> str: - """vms : [{name, ip}]. Lance chaque install détachée, écrit un manifeste - et retourne son chemin. remote_cmd : script exécuté dans chaque VM.""" + """vms : [{name, ip, distro?, version?, arch?}]. Lance chaque install + détachée, écrit un manifeste et retourne son chemin. remote_cmd : script + exécuté dans chaque VM.""" sdir = session_dir() stamp = time.strftime("%Y%m%d-%H%M%S") + when = time.strftime("%Y-%m-%d %H:%M:%S") logdir = sdir / stamp logdir.mkdir(parents=True, exist_ok=True) entries = [] for vm in vms: log_path = str(logdir / f"{vm['name']}.log") - Path(log_path).write_text("") # log vide = état « en attente » + # En-tête d'emblée (date/distro/version/arch) : le log n'est jamais + # vide, l'utilisateur voit tout de suite QUOI s'installe. + Path(log_path).write_text(_log_header(vm, branch, when)) _launch_one(vm["ip"], remote_cmd, log_path) entries.append( { "name": vm["name"], "ip": vm["ip"], + "distro": vm.get("distro"), + "version": vm.get("version"), + "arch": vm.get("arch"), "log": log_path, "ssh": f"ssh erplibre@{vm['ip']}", } diff --git a/script/todo/todo.py b/script/todo/todo.py index 741f980..bd4ade2 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -1763,6 +1763,40 @@ class TODO: # Meilleur effort : le dernier bail (le plus récent) plutôt que le 1er. return cands[-1] if cands else None + def _qemu_vm_arch(self, name): + """Architecture d'une VM (jeton amd64/arm64/s390x) via virsh dumpxml.""" + try: + res = subprocess.run( + ["sudo", "virsh", "dumpxml", name], + capture_output=True, + text=True, + timeout=15, + ) + except (OSError, subprocess.SubprocessError): + return None + m = re.search(r"]*\barch='([^']+)'", res.stdout) + if not m: + return None + return { + "x86_64": "amd64", + "aarch64": "arm64", + "s390x": "s390x", + }.get(m.group(1), m.group(1)) + + def _qemu_vm_meta(self, name, mod): + """(distro, version, arch) d'une VM déduits de son nom + son arch. Le + nom suit _qemu_infra_name(distro, version, arch) : on retrouve donc + (distro, version) en testant les combinaisons du catalogue.""" + arch = self._qemu_vm_arch(name) or "amd64" + try: + for d, (versions, _default) in mod.DISTROS.items(): + for v in versions: + if self._qemu_infra_name(d, v, arch) == name: + return d, v, arch + except Exception: + pass + return None, None, arch + def _qemu_pick_branch(self): """Liste les branches distantes d'ERPLibre et en fait choisir une.""" print(f"\n{t('Fetching ERPLibre branch list...')}") @@ -1928,12 +1962,29 @@ class TODO: ) remote = self._qemu_erplibre_remote_cmd(branch) + try: + mod = self._qemu_import_module() + except Exception: + mod = None vms = [] for name in names: print(f" {name}: {t('resolving IP...')}") ip = self._qemu_vm_ip(name) if ip: - vms.append({"name": name, "ip": ip}) + d, v, a = ( + self._qemu_vm_meta(name, mod) + if mod + else (None, None, None) + ) + vms.append( + { + "name": name, + "ip": ip, + "distro": d, + "version": v, + "arch": a, + } + ) else: print(f" {name}: {t('no IP, skipped.')}") if not vms: diff --git a/script/todo/todo_i18n.py b/script/todo/todo_i18n.py index 588b5fa..06cd6fe 100644 --- a/script/todo/todo_i18n.py +++ b/script/todo/todo_i18n.py @@ -1201,6 +1201,10 @@ TRANSLATIONS = { "fr": "Toutes les architectures supportées", "en": "All supported architectures", }, + "installation": { + "fr": "installation", + "en": "installation", + }, "(includes emulated architectures — some VMs are slow)": { "fr": "(inclut des architectures émulées — certaines VM sont lentes)", "en": "(includes emulated architectures — some VMs are slow)",