From 788c17dbb5374b011ee1438a72ac2015835a0549 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 13 Aug 2026 23:11:10 -0400 Subject: [PATCH] [FIX] qemu debian s390x : adresse fixe propre a chaque VM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit « Premiere libre en partant du haut » donnait la MEME adresse a deux VM deployees en parallele : ni l'une ni l'autre n'est montee quand l'autre cherche, donc aucune ne voit l'autre. Mesure — debian-12 et debian-13 ont tous deux pris .250 et se sont disputes l'adresse, une seule survivant. C'est ce qui faisait echouer le 12 quand le 13 passait. Le depart du balayage vient desormais du NOM de la VM, par crc32. Les noms different toujours, la collision disparait, et le tirage reste stable d'un redeploiement a l'autre. Le balayage garde ses garde-fous : baux existants et adresses qui repondent restent ecartes. Verifie : debian-12 -> .216, debian-13 -> .218. --- EN --- "First free from the top" gave the SAME address to two VMs deployed in parallel: neither is up when the other looks, so neither sees the other. Measured — debian-12 and debian-13 both took .250 and fought over it, only one surviving. That is what made 12 fail while 13 went through. The scan now starts from the VM NAME, via crc32. Names always differ, the collision is gone, and the draw stays stable across redeployments. The scan keeps its guards: existing leases and answering addresses are still skipped. Verified: debian-12 -> .216, debian-13 -> .218. Assisted-by: Claude Opus 5 (cherry picked from commit 91592383e213ad98873125866e6120e5da5874fe) --- script/qemu/deploy_qemu.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/script/qemu/deploy_qemu.py b/script/qemu/deploy_qemu.py index 39055aa..ccd2239 100755 --- a/script/qemu/deploy_qemu.py +++ b/script/qemu/deploy_qemu.py @@ -50,6 +50,7 @@ import getpass import grp import gzip import hashlib +import zlib import os import re import shutil @@ -1711,7 +1712,7 @@ def prepare_disk( runner.run(["qemu-img", "resize", str(disk), size], privileged=True) -def static_net_plan(net: str | None, use_sudo: bool) -> dict[str, str] | None: +def static_net_plan(net: str | None, use_sudo: bool, name: str) -> dict[str, str] | None: """Adresse fixe libre pour une VM installée par debian-installer. L'initrd s390x ne contient QUE « netcfg-static » : le journal de d-i @@ -1750,7 +1751,16 @@ def static_net_plan(net: str | None, use_sudo: bool) -> dict[str, str] | None: taken |= set(re.findall(r"(\d+\.\d+\.\d+\.\d+)/\d+", out)) except (OSError, subprocess.SubprocessError): pass - for last in range(250, 200, -1): + # Départ DÉTERMINISTE, tiré du nom de la VM. Un simple « première libre + # en partant du haut » donne la MÊME adresse à deux VM déployées en + # parallèle : aucune des deux n'est encore montée quand l'autre cherche, + # donc aucune ne voit l'autre. Vécu — debian-12 et debian-13 ont tous + # deux pris .250 et se sont disputé l'adresse, une seule survivant. + # Le nom, lui, diffère toujours, et le tirage reste stable d'un + # redéploiement à l'autre. + start = zlib.crc32(name.encode()) % 50 + for offset in range(50): + last = 200 + (start + offset) % 50 ip = f"{base}.{last}" if ip in taken or _ip_reachable(ip, port=22, timeout=0.4): continue @@ -2738,7 +2748,9 @@ def main() -> None: create_blank_disk(disk, args.disk_size, runner, args.force) print(f"\n== 4/5 Preseed embarqué dans l'initrd ==") - static = static_net_plan(network_name(args.network), not args.dry_run) + static = static_net_plan( + network_name(args.network), not args.dry_run, args.name + ) if static: print(f" Adresse fixe retenue : {static['ip']}" f" (passerelle {static['gateway']})")