reconstruire-locataire : le nom de l'ecosysteme n'est plus demande deux fois
TENANT= le designe en toutes lettres ; le nom qu'exige raser en est derive par raser.nom_court (une seule derivation). raser seul garde son garde-fou. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a5a21ee4c5
commit
249d37d2c4
5 changed files with 35 additions and 17 deletions
|
|
@ -11,8 +11,12 @@ fois la voûte du locataire et l'accès au runner du site) :
|
||||||
sauf `ARMER=oui`) → `monter` (`make monter-flotte` sur le runner du locataire, suivi toutes
|
sauf `ARMER=oui`) → `monter` (`make monter-flotte` sur le runner du locataire, suivi toutes
|
||||||
les 30 s) → `parefeu` (`--flotte`) → `bilan` (ce que chaque jeu d'état est devenu).
|
les 30 s) → `parefeu` (`--flotte`) → `bilan` (ce que chaque jeu d'état est devenu).
|
||||||
|
|
||||||
Le nom de l'écosystème s'écrit en toutes lettres (`INSTANCE=`), comme pour `raser`, qui
|
`TENANT=` désigne l'écosystème en toutes lettres ; le nom qu'exige `raser` en est DÉRIVÉ
|
||||||
n'a pas d'autre condition. Arrêt à la première étape en échec, avec la commande de reprise
|
(`raser.nom_court`, une seule dérivation), pas redemandé. La première version exigeait aussi
|
||||||
|
`INSTANCE=` — relevé par l'exploitant : « pourquoi cette cible a besoin de se faire dire
|
||||||
|
"chezlepro" deux fois ? ». Le garde-fou de `raser` n'a de sens que pour `raser` seul, qui rase
|
||||||
|
l'écosystème du lien `instance/` ; ici, rien d'implicite n'est à confirmer. `raser` n'a pas
|
||||||
|
d'autre condition que sa confirmation. Arrêt à la première étape en échec, avec la commande de reprise
|
||||||
(`DEPUIS=<étape>`) ; journal complet dans `<locataire>/logs/`.
|
(`DEPUIS=<étape>`) ; journal complet dans `<locataire>/logs/`.
|
||||||
|
|
||||||
**Le runner du site se met à jour avant sa première étape** (quelle que soit la reprise) :
|
**Le runner du site se met à jour avant sa première étape** (quelle que soit la reprise) :
|
||||||
|
|
|
||||||
12
Makefile
12
Makefile
|
|
@ -1451,16 +1451,16 @@ monter-flotte: _instance-requise ## Monte une flotte deja creee : flux, AC et DN
|
||||||
# RECONSTRUIRE UN LOCATAIRE DE BOUT EN BOUT, DEPUIS LE POSTE (2026-09-30). Les deux
|
# RECONSTRUIRE UN LOCATAIRE DE BOUT EN BOUT, DEPUIS LE POSTE (2026-09-30). Les deux
|
||||||
# reconstructions du 2026-09-30 passaient par cinq endroits et des commandes tapees a la
|
# reconstructions du 2026-09-30 passaient par cinq endroits et des commandes tapees a la
|
||||||
# main ; la sequence vit desormais dans `scripts/reconstruire_locataire.py` (voir son
|
# main ; la sequence vit desormais dans `scripts/reconstruire_locataire.py` (voir son
|
||||||
# en-tete). Le nom de l'ecosysteme s'ecrit en toutes lettres (`INSTANCE=`), comme pour
|
# en-tete). `TENANT=` designe l'ecosysteme en toutes lettres : le nom qu'exige `raser` en est
|
||||||
# `raser`. L'armement marque une pause, sauf `ARMER=oui`. `DEPUIS=<etape>` reprend apres un
|
# derive, pas redemande. L'armement marque une pause, sauf `ARMER=oui`. `DEPUIS=<etape>` reprend apres un
|
||||||
# arret. Le journal complet va dans `<locataire>/logs/`.
|
# arret. Le journal complet va dans `<locataire>/logs/`.
|
||||||
.PHONY: reconstruire-locataire
|
.PHONY: reconstruire-locataire
|
||||||
reconstruire-locataire: ## Rase et reconstruit un locataire, du site a la recette, etat remis — TENANT= INSTANCE= CONFIRMER=true
|
reconstruire-locataire: ## Rase et reconstruit un locataire, du site a la recette, etat remis — TENANT=OPS-X CONFIRMER=true
|
||||||
@if [[ -z "$(TENANT)" || -z "$(INSTANCE)" ]]; then \
|
@if [[ -z "$(TENANT)" ]]; then \
|
||||||
printf '%s\n' 'Refus: TENANT=<OPS-X> et INSTANCE=<nom de l ecosysteme, en toutes lettres> requis.'; \
|
printf '%s\n' 'Refus: TENANT=<OPS-X> requis (le dossier du locataire, en toutes lettres).'; \
|
||||||
exit 2; \
|
exit 2; \
|
||||||
fi
|
fi
|
||||||
python3 scripts/reconstruire_locataire.py --tenant "$(TENANT)" --instance "$(INSTANCE)" \
|
python3 scripts/reconstruire_locataire.py --tenant "$(TENANT)" \
|
||||||
$(if $(filter true,$(CONFIRMER)),--confirmer) $(if $(DEPUIS),--depuis "$(DEPUIS)") \
|
$(if $(filter true,$(CONFIRMER)),--confirmer) $(if $(DEPUIS),--depuis "$(DEPUIS)") \
|
||||||
$(if $(filter oui,$(ARMER)),--armer)
|
$(if $(filter oui,$(ARMER)),--armer)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -480,7 +480,7 @@ runbooks:
|
||||||
nature: destructif
|
nature: destructif
|
||||||
portee: poste
|
portee: poste
|
||||||
duree: "long"
|
duree: "long"
|
||||||
variables: [TENANT, INSTANCE, DEPUIS, ARMER]
|
variables: [TENANT, DEPUIS, ARMER]
|
||||||
fixes: {CONFIRMER: "true"}
|
fixes: {CONFIRMER: "true"}
|
||||||
pourquoi: >-
|
pourquoi: >-
|
||||||
TOUT, d'une commande, depuis le poste : sauvegarder, raser et recreer (runner du
|
TOUT, d'une commande, depuis le poste : sauvegarder, raser et recreer (runner du
|
||||||
|
|
|
||||||
|
|
@ -41,14 +41,22 @@ from inventory_rules import instance_courante # noqa: E402
|
||||||
RACINE = Path(__file__).resolve().parent.parent
|
RACINE = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
def nom_court(dossier: Path) -> str:
|
||||||
|
"""Le nom qu'il faut TAPER pour raser cet ecosysteme : `OPS-Technolibre` -> `technolibre`.
|
||||||
|
|
||||||
|
Une seule derivation : `reconstruire_locataire.py` l'importe au lieu de redemander le
|
||||||
|
nom (2026-09-30) — la ou l'ecosysteme est deja designe explicitement par `TENANT=`.
|
||||||
|
"""
|
||||||
|
return dossier.name.removeprefix("OPS-").lower()
|
||||||
|
|
||||||
|
|
||||||
def instance_active() -> tuple[Path, str]:
|
def instance_active() -> tuple[Path, str]:
|
||||||
"""Dossier de l'instance montee, et son nom court (celui qu'il faudra taper)."""
|
"""Dossier de l'instance montee, et son nom court (celui qu'il faudra taper)."""
|
||||||
base = instance_courante()
|
base = instance_courante()
|
||||||
if not base.exists():
|
if not base.exists():
|
||||||
raise SystemExit("Aucune instance montee : rien a raser.")
|
raise SystemExit("Aucune instance montee : rien a raser.")
|
||||||
reel = base.resolve()
|
reel = base.resolve()
|
||||||
nom = reel.name.removeprefix("OPS-").lower()
|
return reel, nom_court(reel)
|
||||||
return reel, nom
|
|
||||||
|
|
||||||
|
|
||||||
def plan_derive(base: Path) -> list[tuple[str, int]]:
|
def plan_derive(base: Path) -> list[tuple[str, int]]:
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ pas les secrets du locataire, et c'est voulu : l'armement reste un geste du post
|
||||||
LES ETAPES, dans l'ordre (`--depuis` reprend a l'une d'elles apres un arret) :
|
LES ETAPES, dans l'ordre (`--depuis` reprend a l'une d'elles apres un arret) :
|
||||||
|
|
||||||
sauvegarder poste deposer l'etat de chaque noeud MAINTENANT (sinon on perd la journee)
|
sauvegarder poste deposer l'etat de chaque noeud MAINTENANT (sinon on perd la journee)
|
||||||
raser runner du site detruire les VM — le nom de l'ecosysteme s'ecrit en toutes lettres
|
raser runner du site detruire les VM
|
||||||
creer runner du site recreer les VM depuis le gabarit
|
creer runner du site recreer les VM depuis le gabarit
|
||||||
inseminer runner du site amorcer le runner du locataire (socle + moteur, sans secret)
|
inseminer runner du site amorcer le runner du locataire (socle + moteur, sans secret)
|
||||||
armer poste lui remettre sa voute et sa cle — pause, sauf `--armer`
|
armer poste lui remettre sa voute et sa cle — pause, sauf `--armer`
|
||||||
|
|
@ -26,6 +26,12 @@ LES ETAPES, dans l'ordre (`--depuis` reprend a l'une d'elles apres un arret) :
|
||||||
|
|
||||||
La premiere etape en echec arrete tout, et le dit. `raser` n'a pas d'autre condition que sa
|
La premiere etape en echec arrete tout, et le dit. `raser` n'a pas d'autre condition que sa
|
||||||
confirmation (decision de l'exploitant) : c'est la PROCEDURE qui sauvegarde avant.
|
confirmation (decision de l'exploitant) : c'est la PROCEDURE qui sauvegarde avant.
|
||||||
|
|
||||||
|
LE NOM N'EST DEMANDE QU'UNE FOIS. `raser`, seul, exige qu'on tape le nom de l'ecosysteme
|
||||||
|
parce qu'il rase celui du lien `instance/`, qui peut pointer n'importe ou. Ici l'ecosysteme
|
||||||
|
est deja designe en toutes lettres par `TENANT=` : le nom que `raser` attend en est DERIVE
|
||||||
|
(`raser.nom_court`), pas redemande. Une premiere version l'exigeait deux fois — une
|
||||||
|
occasion de se tromper de plus, et aucune protection de plus (2026-09-30).
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
@ -42,6 +48,7 @@ sys.path.insert(0, str(RACINE / "scripts"))
|
||||||
|
|
||||||
from devis_reseau import DOSSIER_INSTANCES # noqa: E402
|
from devis_reseau import DOSSIER_INSTANCES # noqa: E402
|
||||||
from eprouver_parefeu import _ip_par_hote # noqa: E402
|
from eprouver_parefeu import _ip_par_hote # noqa: E402
|
||||||
|
from raser import nom_court # noqa: E402
|
||||||
|
|
||||||
ETAPES = ["sauvegarder", "raser", "creer", "inseminer", "armer", "monter", "parefeu", "bilan"]
|
ETAPES = ["sauvegarder", "raser", "creer", "inseminer", "armer", "monter", "parefeu", "bilan"]
|
||||||
SSH = ["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=15", "-o", "ServerAliveInterval=30",
|
SSH = ["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=15", "-o", "ServerAliveInterval=30",
|
||||||
|
|
@ -134,8 +141,6 @@ def main() -> int:
|
||||||
global JOURNAL
|
global JOURNAL
|
||||||
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||||
ap.add_argument("--tenant", required=True, help="dossier du locataire, ex. OPS-Technolibre")
|
ap.add_argument("--tenant", required=True, help="dossier du locataire, ex. OPS-Technolibre")
|
||||||
ap.add_argument("--instance", required=True,
|
|
||||||
help="nom de l'ecosysteme, ecrit en toutes lettres (celui qu'exige `raser`)")
|
|
||||||
ap.add_argument("--confirmer", action="store_true", help="sans lui, rien n'est fait")
|
ap.add_argument("--confirmer", action="store_true", help="sans lui, rien n'est fait")
|
||||||
ap.add_argument("--depuis", choices=ETAPES, default=ETAPES[0], help="reprendre a cette etape")
|
ap.add_argument("--depuis", choices=ETAPES, default=ETAPES[0], help="reprendre a cette etape")
|
||||||
ap.add_argument("--armer", action="store_true",
|
ap.add_argument("--armer", action="store_true",
|
||||||
|
|
@ -148,6 +153,7 @@ def main() -> int:
|
||||||
|
|
||||||
T = args.tenant
|
T = args.tenant
|
||||||
dossier = DOSSIER_INSTANCES / T
|
dossier = DOSSIER_INSTANCES / T
|
||||||
|
ecosysteme = nom_court(dossier)
|
||||||
inv = dossier / "inventories" / "principal" / "hosts.yml"
|
inv = dossier / "inventories" / "principal" / "hosts.yml"
|
||||||
if not inv.is_file():
|
if not inv.is_file():
|
||||||
print(f"REFUS : {inv} introuvable.")
|
print(f"REFUS : {inv} introuvable.")
|
||||||
|
|
@ -155,7 +161,7 @@ def main() -> int:
|
||||||
runner_nom, runner_ip = runner_du_locataire(T)
|
runner_nom, runner_ip = runner_du_locataire(T)
|
||||||
a_faire = ETAPES[ETAPES.index(args.depuis):]
|
a_faire = ETAPES[ETAPES.index(args.depuis):]
|
||||||
if not args.confirmer:
|
if not args.confirmer:
|
||||||
print(f"Refus : RECONSTRUCTION de {T} ({args.instance}) — ses VM seront DETRUITES puis refaites.")
|
print(f"Refus : RECONSTRUCTION de {T} ({ecosysteme}) — ses VM seront DETRUITES puis refaites.")
|
||||||
print(f" etapes : {' -> '.join(a_faire)} ; runner du locataire : {runner_nom} ({runner_ip})")
|
print(f" etapes : {' -> '.join(a_faire)} ; runner du locataire : {runner_nom} ({runner_ip})")
|
||||||
print(" Relancer avec CONFIRMER=true.")
|
print(" Relancer avec CONFIRMER=true.")
|
||||||
return 2
|
return 2
|
||||||
|
|
@ -172,7 +178,7 @@ def main() -> int:
|
||||||
def arret(nom: str, rc: int, quoi: str = "") -> int:
|
def arret(nom: str, rc: int, quoi: str = "") -> int:
|
||||||
dire(f"\nARRET a l'etape « {nom} » (code {rc}){' — ' + quoi if quoi else ''}.")
|
dire(f"\nARRET a l'etape « {nom} » (code {rc}){' — ' + quoi if quoi else ''}.")
|
||||||
dire(f"Reprendre, une fois la cause comprise : make reconstruire-locataire TENANT={T} "
|
dire(f"Reprendre, une fois la cause comprise : make reconstruire-locataire TENANT={T} "
|
||||||
f"INSTANCE={args.instance} CONFIRMER=true DEPUIS={nom}")
|
f"CONFIRMER=true DEPUIS={nom}")
|
||||||
return rc or 1
|
return rc or 1
|
||||||
|
|
||||||
site_tire = False
|
site_tire = False
|
||||||
|
|
@ -189,7 +195,7 @@ def main() -> int:
|
||||||
filtre=("fatal:", "PLAY RECAP", "failed="))
|
filtre=("fatal:", "PLAY RECAP", "failed="))
|
||||||
elif nom == "raser":
|
elif nom == "raser":
|
||||||
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make raser CONFIRMER=true "
|
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make raser CONFIRMER=true "
|
||||||
f"INSTANCE={shlex.quote(args.instance)}",
|
f"INSTANCE={shlex.quote(ecosysteme)}",
|
||||||
filtre=("detruite", "VM detruites", "Refus", "REFUS", "ERREUR"))
|
filtre=("detruite", "VM detruites", "Refus", "REFUS", "ERREUR"))
|
||||||
elif nom == "creer":
|
elif nom == "creer":
|
||||||
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make flotte-creer "
|
rc = sur_site(args, f"SETOPS_INSTANCE={args.racine_runner}/{T} make flotte-creer "
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue