contexte : etape 3, le site decouvre ses locataires par leur face reseau
decouvrir_du_site part de underlay.tenants et prend index et zones dans la face publiee. Les sept sorties du site sont identiques a HEAD, a l'octet pres ; frontiere-plan ne voit rien a faire. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
013c1b5279
commit
d0a6002b87
5 changed files with 97 additions and 7 deletions
31
CHANGELOG.md
31
CHANGELOG.md
|
|
@ -1,5 +1,36 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-10-05 (94) — Étape 3 : le site découvre ses locataires par leur face réseau
|
||||
|
||||
**Le chemin** (`docs/conception-contextes.md` §6), étape 3. La découverte des locataires
|
||||
(`devis_reseau.decouvrir_du_site`) alimente tous les devis du site : frontière, Proxmox, SDN,
|
||||
pools, commutateur, et l'inventaire du site. Elle lisait la nomenclature de chaque locataire.
|
||||
|
||||
**Fait** :
|
||||
- relevé de ce que le site lit d'une nomenclature : **cinq champs** (`index`, `categories`,
|
||||
`reservations`, `cidr_hote`, `federe`) ; la face réseau les publie (`nomenclature`) ;
|
||||
- `decouvrir_du_site` part des noms que le site déclare (`underlay.tenants`) et prend index
|
||||
et zones dans la face publiée de chacun. Ordre, filtre `federe`, avertissement pour un nom
|
||||
sans dépôt et refus d'un site sans locataire inchangés. Sans face, la nomenclature, et elle
|
||||
le dit ;
|
||||
- faces republiées chez les deux locataires.
|
||||
|
||||
**Le critère** : les sept sorties des consommateurs du site sont **identiques octet pour
|
||||
octet** à celles de la version de HEAD, lancée à part : commutateur (8,8 Ko), frontière
|
||||
(167 Ko), Proxmox (63 Ko), SDN (ses deux formats), pools, inventaire du site (81 Ko).
|
||||
`make frontiere-plan` contre la frontière réelle : rien à faire.
|
||||
|
||||
**Ce qui lit encore la nomenclature des locataires**, nommé : la découverte de la
|
||||
**fédération** (`decouvrir`), qui sert sur le poste à garder les collisions d'index (P21) et à
|
||||
lister les instances — légitime, ce n'est pas le site — et que `decouvrir_du_site` appelle
|
||||
encore pour son repli ; `vpn_admin.py` (index pour le tunnel) ; `devis_proxmox_pools`
|
||||
(nommer les VM, avec le plan). Ils partiront avec la matérialisation et la fin du repli.
|
||||
|
||||
**Éprouvé** :
|
||||
- `test_contexte.py`, 103 contrôles : un index altéré dans la face publiée est celui que le
|
||||
site découvre (17, puis 99) — la découverte lit bien la face.
|
||||
- `make verifier` conforme, 92/92.
|
||||
|
||||
## 2026-10-05 (93) — Étape 3 : la frontière lit la face réseau
|
||||
|
||||
**Le chemin** (`docs/conception-contextes.md` §6), étape 3. Quatrième consommateur du site, le
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ les publie désormais (`sources_declarees`). La frontière, en trois temps : les
|
|||
(P87), les entrées publiques (P88), l'administration (P89) et les sorties (P90) sont faites.
|
||||
**L'étape 2 est terminée** (2026-10-05). Étape 3 : l'instancier lit la fiche déposée par le site, et
|
||||
l'inventaire d'un locataire se génère sans son site, à l'octet près (P91). Le locataire publie sa face
|
||||
réseau (P92) ; les comptes de sauvegarde, le DNS public, le pare-feu Proxmox et la frontière du site
|
||||
la lisent.
|
||||
réseau (P92) ; les comptes de sauvegarde, le DNS public, le pare-feu Proxmox, la frontière et la
|
||||
découverte des locataires du site la lisent.
|
||||
|
||||
Méthodes du contrat : `site.fiche_pour(locataire)`, `locataire.face_reseau()`. Une classe
|
||||
n'ouvre jamais les fichiers de l'autre ; une preuve vérifiera la règle.
|
||||
|
|
|
|||
|
|
@ -540,6 +540,11 @@ class Locataire(Ecosysteme):
|
|||
"sources": sources,
|
||||
"index": self.index,
|
||||
"zones": zones,
|
||||
# Ce que le site lit de sa nomenclature (decouverte, frontiere, SDN, commutateur) :
|
||||
# ces cinq champs, et rien d'autre (releve du 2026-10-05).
|
||||
"nomenclature": {k: self.nomenclature()[k] for k in
|
||||
("index", "categories", "reservations", "cidr_hote", "federe")
|
||||
if k in self.nomenclature()},
|
||||
"machines": machines,
|
||||
"groupes": groupes,
|
||||
"administration": {"intrant": intrant, "tunnel": tunnel_admin_de(self.depot),
|
||||
|
|
|
|||
|
|
@ -619,6 +619,20 @@ def decouvrir() -> list[tuple[str, str, dict]]:
|
|||
return tenants
|
||||
|
||||
|
||||
def _nomenclature_publiee(nom: str) -> dict | None:
|
||||
"""Les champs de nomenclature que ce locataire publie dans sa face reseau, ou None."""
|
||||
try:
|
||||
import contexte
|
||||
face = contexte.Locataire(DOSSIER_INSTANCES / nom).face_publiee()
|
||||
except Exception:
|
||||
face = None
|
||||
if face is None or not face.get("nomenclature"):
|
||||
print(f"note : {nom} n'a pas publie sa nomenclature dans sa face reseau — lecture de "
|
||||
f"son plan (transition).", file=sys.stderr)
|
||||
return None
|
||||
return dict(face["nomenclature"])
|
||||
|
||||
|
||||
def decouvrir_du_site() -> list[tuple[str, str, dict]]:
|
||||
"""Les tenants que CE SITE heberge — `decouvrir()` restreint par `underlay.tenants`.
|
||||
|
||||
|
|
@ -645,12 +659,23 @@ def decouvrir_du_site() -> list[tuple[str, str, dict]]:
|
|||
portes = underlay_mod.tenants_du_site(underlay_mod.charger())
|
||||
if portes is None:
|
||||
return tenants
|
||||
connus = {nom for nom, _pfx, _n in tenants}
|
||||
# LA FACE RESEAU D'ABORD (2026-10-05, docs/conception-contextes.md §6, etape 3). Les noms
|
||||
# viennent du site (`underlay.tenants`) ; l'index et les zones, de ce que chaque locataire
|
||||
# PUBLIE (`face-reseau.yml`, champ `nomenclature`) — plus de sa nomenclature. Sans face
|
||||
# publiee (transition), sa nomenclature, et on le dit.
|
||||
par_nom = {nom: (pfx, n) for nom, pfx, n in tenants}
|
||||
retenus = []
|
||||
for nom in portes:
|
||||
if nom not in connus:
|
||||
print(f"ATTENTION : `tenants` de l'underlay nomme « {nom} », "
|
||||
f"qu'aucun dossier frere ne fournit.", file=sys.stderr)
|
||||
retenus = [t for t in tenants if t[0] in set(portes)]
|
||||
n = _nomenclature_publiee(nom)
|
||||
if n is None:
|
||||
if nom not in par_nom:
|
||||
print(f"ATTENTION : `tenants` de l'underlay nomme « {nom} », "
|
||||
f"qu'aucun dossier frere ne fournit.", file=sys.stderr)
|
||||
continue
|
||||
n = par_nom[nom][1]
|
||||
if n.get("index") is not None and n.get("categories") and n.get("federe", True):
|
||||
retenus.append((nom, prefixe(nom), n))
|
||||
retenus.sort(key=lambda t: t[2]["index"])
|
||||
if not retenus:
|
||||
raise SystemExit("Aucun tenant heberge sur ce site : `underlay.tenants` n'en "
|
||||
"retient aucun de connu.")
|
||||
|
|
|
|||
|
|
@ -551,6 +551,34 @@ def frontiere_lit_la_face() -> None:
|
|||
f"la frontiere lit la face publiee : {g} {port}/tcp sur le WAN, {avant} regle(s), 0 une fois le verdict bascule")
|
||||
|
||||
|
||||
def decouverte_lit_la_face() -> None:
|
||||
"""La decouverte du site lit l'index que le locataire publie, pas sa nomenclature."""
|
||||
import devis_reseau
|
||||
import yaml as _yaml
|
||||
couples = C.couples_hebergeur()
|
||||
if not couples:
|
||||
print("SAUTE aucun site frere : aucune decouverte a confronter")
|
||||
return
|
||||
site, loc = couples[0]
|
||||
chemin = loc.depot / C.NOM_FICHIER_FACE_RESEAU
|
||||
original = chemin.read_text(encoding="utf-8")
|
||||
|
||||
def index_decouvert():
|
||||
with C._monter(site):
|
||||
return next((n["index"] for nom, _p, n in devis_reseau.decouvrir_du_site() if nom == loc.nom), None)
|
||||
|
||||
avant = index_decouvert()
|
||||
try:
|
||||
f = _yaml.safe_load(original)
|
||||
f["nomenclature"]["index"] = 99
|
||||
chemin.write_text(_yaml.safe_dump(f, allow_unicode=True, sort_keys=False), encoding="utf-8")
|
||||
apres = index_decouvert()
|
||||
finally:
|
||||
chemin.write_text(original, encoding="utf-8")
|
||||
verifier(avant == loc.index and apres == 99,
|
||||
f"la decouverte du site lit l'index publie : {avant}, puis 99 une fois la face alteree")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
d = Path(tmp)
|
||||
|
|
@ -570,6 +598,7 @@ def main() -> int:
|
|||
face_publiee()
|
||||
proxmox_lit_la_face()
|
||||
frontiere_lit_la_face()
|
||||
decouverte_lit_la_face()
|
||||
if ECHECS:
|
||||
print(f"\n{len(ECHECS)} echec(s).")
|
||||
return 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue