[FIX] script todo/qemu: safer VM deploy prompt (size unit, name, errors)

Three papercuts hit when creating a VM from the menu:

1. Disk size "30" was passed verbatim to qemu-img resize, which read it
   as 30 BYTES and failed ("use --shrink"). The prompt now shows units
   (e.g. 30G, 1T) and a bare number is normalised to GB ("30" -> "30G"),
   in the menu and in deploy_qemu.py itself.
2. The VM name is no longer required: leaving it blank uses the default
   erplibre-<distro>-<version> (e.g. erplibre-ubuntu-2604). Distro and
   version are now asked first so the default can be offered.
3. The menu ignored the deploy exit code and carried on to "wait for the
   VM IP" even after a failure, hanging forever with the error scrolled
   off. It now checks the return code and stops with a clear message.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mathieu Benoit 2026-07-28 02:26:07 +00:00
parent 2b7e20493a
commit d83d244805
3 changed files with 40 additions and 9 deletions

View file

@ -1315,6 +1315,10 @@ def main() -> None:
args.memory = min_ram
if args.disk_size is None:
args.disk_size = min_disk
# Un nombre nu (« 30 ») serait pris pour des OCTETS par qemu-img et ferait
# échouer le resize : on suppose des Go par défaut (« 30 » -> « 30G »).
if re.fullmatch(r"\d+", str(args.disk_size)):
args.disk_size = f"{args.disk_size}G"
urls = image_candidates(
args.distro, code, args.arch, args.version, args.dry_run
)

View file

@ -930,19 +930,32 @@ class TODO:
if cmd_no_found:
print(t("Command not found !"))
@staticmethod
def _normalize_disk_size(size):
"""« 30 » -> « 30G » (unité par défaut Go). Laisse « 30G », « 1T »… ou
vide tels quels. Sans unité, qemu-img interpréterait des OCTETS."""
size = size.strip()
if re.fullmatch(r"\d+", size):
return size + "G"
return size
def _qemu_deploy_vm(self, dry_run=False):
script_path = self._qemu_script_path()
name = input(t("VM name (required): ")).strip()
if not name:
print(t("VM name is required!"))
return
# Distro + version d'abord : permet de proposer un nom par défaut.
distro = self._qemu_prompt_distro()
version = self._qemu_prompt_version(distro)
default_name = self._qemu_infra_name(distro, version)
name = (
input(f"{t('VM name (default: ')}{default_name}): ").strip()
or default_name
)
# Laisser vide => le script applique le minimum requis par la version
# choisie (libosinfo). On n'envoie alors pas le flag.
memory = input(t("RAM in MB (blank = version minimum): ")).strip()
vcpus = input(t("vCPUs (default: 2): ")).strip()
disk_size = input(t("Disk size (blank = version minimum): ")).strip()
disk_size = self._normalize_disk_size(
input(t("Disk size (blank = version min; e.g. 30G, 1T): ")).strip()
)
default_key = self._qemu_default_ssh_key()
key_hint = default_key or t("none")
@ -995,7 +1008,13 @@ class TODO:
print(f"{t('Will execute:')} {cmd}")
if password:
print(f"🔑 {t('Console/SSH login:')} erplibre / {password}")
self.execute.exec_command_live(cmd, source_erplibre=False)
status = self.execute.exec_command_live(cmd, source_erplibre=False)
# Arrêt net sur erreur : sinon on enchaînait sur l'attente d'IP d'une
# VM jamais créée (blocage infini), l'utilisateur ne voyant rien.
if status != 0:
print(f"\n{t('Deployment failed (see the error above).')}")
return
# Proposer d'enregistrer la VM dans ~/.ssh/config (après le 1er boot).
if not dry_run:

View file

@ -1359,9 +1359,17 @@ TRANSLATIONS = {
"fr": "vCPU (défaut : 2) : ",
"en": "vCPUs (default: 2): ",
},
"Disk size (blank = version minimum): ": {
"fr": "Taille du disque (vide = minimum de la version) : ",
"en": "Disk size (blank = version minimum): ",
"Disk size (blank = version min; e.g. 30G, 1T): ": {
"fr": "Taille du disque (vide = min. version ; ex. 30G, 1T) : ",
"en": "Disk size (blank = version min; e.g. 30G, 1T): ",
},
"VM name (default: ": {
"fr": "Nom de la VM (défaut : ",
"en": "VM name (default: ",
},
"Deployment failed (see the error above).": {
"fr": "Échec du déploiement (voir l'erreur ci-dessus).",
"en": "Deployment failed (see the error above).",
},
"SSH public key path": {
"fr": "Chemin de la clé publique SSH",