#!/usr/bin/env python3 """`make creer-vm TENANT=` lance-t-il le MEME clonage que l'ancien chemin, l'instance montee ? Compare, machine par machine, la ligne `ansible-playbook` qui part reellement — un faux `ansible-playbook` en tete du PATH la consigne au lieu de cloner. Trois appels par machine : - l'ancien chemin : `SETOPS_INSTANCE= make creer-vm HOTE=h` ; - le runner du SITE : aucune instance, `TENANT=` ; - le POSTE : l'AUTRE locataire monte, `TENANT=`. POURQUOI (2026-10-05, materialisation M2). Comparer les parametres de clonage ne suffisait pas : le sous-make `cloner-vm` nommait encore le pool par l'instance MONTEE (`--pool-actif`). Sur le site, la VM serait nee hors de tout pool ; sur le poste, dans le pool de l'autre locataire. Seule la ligne finale montre tout ce qui part, y compris ce qu'aucune liste de parametres ne nomme. Les dossiers sont designes par des liens SANS ESPACE : le Makefile prend `SETOPS_INSTANCE` dans des `$(wildcard …)`, qu'une espace coupe en deux (le runner du site vit sous `/opt/setops`). """ from __future__ import annotations import os import subprocess import sys import tempfile from pathlib import Path RACINE = Path(__file__).resolve().parents[2] sys.path.insert(0, str(RACINE / "scripts")) import contexte as C # noqa: E402 FAUX = "#!/bin/bash\nfor a in \"$@\"; do printf '%s\\n' \"$a\"; done >> \"$CAPTURE\"\n" def appel(tmp: Path, instance: str, hote: str, tenant: str | None) -> tuple[int, str]: capture = tmp / "capture" capture.write_text("") env = dict(os.environ, CAPTURE=str(capture), SETOPS_INSTANCE=instance, PATH=f"{tmp / 'faux'}:{os.environ['PATH']}") env.pop("SETOPS_INVENTAIRE", None) cmd = ["make", "--no-print-directory", "creer-vm", "ATTENDRE=false", f"HOTE={hote}"] if tenant: cmd.append(f"TENANT={tenant}") r = subprocess.run(cmd, cwd=RACINE, env=env, capture_output=True, text=True, stdin=subprocess.DEVNULL) return r.returncode, capture.read_text() def main() -> int: couples = C.couples_hebergeur() locataires = sorted({l for _s, l in couples}, key=lambda l: l.nom) if len(locataires) < 2: print("SAUTE il faut deux locataires freres (le cas du poste monte l'autre)") return 0 echecs, n = [], 0 with tempfile.TemporaryDirectory() as t: tmp = Path(t) (tmp / "faux").mkdir() faux = tmp / "faux" / "ansible-playbook" faux.write_text(FAUX) faux.chmod(0o755) liens = {} for l in locataires: liens[l.nom] = tmp / l.nom liens[l.nom].symlink_to(l.depot.resolve()) for l in locataires: autre = next(x for x in locataires if x.nom != l.nom) for h in C.hotes_actifs(l.face_publiee() or {}): rc0, ancien = appel(tmp, str(liens[l.nom]), h, None) rc1, site = appel(tmp, "/nulle/part", h, l.nom) rc2, poste = appel(tmp, str(liens[autre.nom]), h, l.nom) n += 1 if rc0 or not ancien: echecs.append(f"{l.nom} {h} : l'ancien chemin n'a rien lance (code {rc0})") elif (rc1, site) != (0, ancien): echecs.append(f"{l.nom} {h} : le site lancerait autre chose (code {rc1})") elif (rc2, poste) != (0, ancien): echecs.append(f"{l.nom} {h} : le poste ({autre.nom} monte) lancerait autre chose") for e in echecs: print("ECHEC " + e) if echecs: return 1 print(f"OK {n} machine(s) : site et poste lancent le clonage de l'ancien chemin, a l'argument pres") return 0 if __name__ == "__main__": sys.exit(main())