88 lines
3.7 KiB
Python
88 lines
3.7 KiB
Python
|
|
#!/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=<locataire> make creer-vm HOTE=h` ;
|
||
|
|
- le runner du SITE : aucune instance, `TENANT=<locataire>` ;
|
||
|
|
- le POSTE : l'AUTRE locataire monte, `TENANT=<locataire>`.
|
||
|
|
|
||
|
|
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())
|