[FIX] qemu debian s390x : rallumer la VM quand l'installateur a fini

« This domain is not running » apres une installation reussie. Le disque
portait 1,22 Gio et le XML persistant amorcait deja sur « hd » : rien
n'avait echoue, la VM etait simplement eteinte.

virt-install mene l'installation en deux temps — amorcage transitoire
sur kernel+initrd, puis configuration definitive sur disque — et le
passage se fait par un ARRET. C'est virt-install qui rallume ensuite,
sauf qu'avec « --wait 0 » il est deja parti.

On ne peut pas le laisser attendre : sous emulation l'installation dure
des heures, et le deploiement rendrait la main a ce rythme. Un veilleur
detache fait donc le dernier geste, avec 6 h de garde.

Mesure : domaine « shut off », veilleur lance, domaine « running ».
Et la VM installee repond en SSH.

--- EN ---

"This domain is not running" after a successful install. The disk held
1.22 GiB and the persistent XML already booted from "hd": nothing had
failed, the VM was simply powered off.

virt-install runs the install in two stages — a transient kernel+initrd
boot, then the final disk-boot config — and the handover goes through a
SHUTDOWN. virt-install powers it back on afterwards, except that with
"--wait 0" it is already gone.

We cannot let it wait: under emulation the install takes hours, and
deployment would return at that pace. So a detached watcher makes the
last move, with a 6 h guard.

Measured: domain "shut off", watcher started, domain "running". And the
installed VM answers over SSH.

Assisted-by: Claude Opus 5
(cherry picked from commit 9c6cdb7f14ca504fd9d0855ba0dacc3dbf43c04f)
This commit is contained in:
Mathieu Benoit 2026-08-14 00:25:32 -04:00
parent 58da6cdacd
commit b181ad56e8

View file

@ -2266,6 +2266,54 @@ def virt_install(
runner.run(log_env + cmd, privileged=True)
def watch_and_restart(name: str, runner: Runner) -> None:
"""Rallume la VM quand debian-installer a fini et l'a éteinte.
virt-install mène l'installation en DEUX temps : un amorçage transitoire
sur kernel+initrd, puis la configuration définitive, qui démarre sur le
disque. Le passage de l'un à l'autre se fait par un arrêt — l'installateur
redémarre, libvirt détruit le domaine transitoire — et c'est virt-install
qui rallume ensuite. Avec « --wait 0 » il est déjà parti : le domaine
reste « shut off », disque installé et XML correct, mais éteint.
On ne peut pas pour autant laisser virt-install attendre : sous émulation
l'installation dure des heures, et le déploiement rendrait la main à ce
rythme-là. Un veilleur détaché fait donc le dernier geste.
"""
if runner.dry_run:
print(f"[dry-run] veilleur de redémarrage pour {name}")
return
sudo = "sudo " if runner.use_sudo else ""
# 6 h de garde : bien au-delà d'une installation émulée, et le veilleur
# meurt de lui-même si quelque chose a mal tourné.
script = (
f"for i in $(seq 1 720); do "
f" s=$({sudo}virsh -c {LIBVIRT_URI} domstate {name} 2>/dev/null); "
f' if [ "$s" = "shut off" ]; then '
f" {sudo}virsh -c {LIBVIRT_URI} start {name} >/dev/null 2>&1; "
f" exit 0; "
f" fi; "
f" sleep 30; "
f"done"
)
try:
subprocess.Popen(
["/bin/sh", "-c", script],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
)
except (OSError, subprocess.SubprocessError) as exc:
print(f" ⚠ veilleur non lancé ({exc}) ; démarrer à la main :")
print(f" sudo virsh start {name}")
return
print(
f" Veilleur lancé : {name} sera rallumée dès que l'installateur"
" l'aura éteinte."
)
def _ip_reachable(ip: str, port: int = 22, timeout: float = 3) -> bool:
"""Vrai si le port SSH répond (distingue le bail actif du bail périmé)."""
try:
@ -2818,6 +2866,8 @@ def main() -> None:
print(f"\n== 5/5 virt-install (--osinfo {resolved_osinfo}) ==")
ensure_network(network_name(args.network), runner)
virt_install(args, disk, seed, resolved_osinfo, runner, installer)
if installer:
watch_and_restart(args.name, runner)
has_key = bool(ssh_keys)
print("\nTerminé. Suivi :")