From d2345272d4c385bd87151c0df4897d40551b532f Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Thu, 23 Jul 2026 10:21:34 -0400 Subject: [PATCH] devis-reseau : noms uniques par tenant + drapeau federe Deux corrections, revelees quand Chezlepro a eu deux instances (labo index 1 + prod index 13) decouvertes par le devis : 1. Collision de noms. prefixe() reduisait OPS-Chezlepro ET OPS-Chezlepro-lab au meme "CHEZ" (retrait de -lab + troncature 4 lettres) -> deux VLAN "CHEZ-Frontiere" et surtout deux ACL "CHEZ-ISOLATION", que le switch aurait FUSIONNEES (config cassee). Les noms sont desormais qualifies par l'index (CHEZ1-*, CHEZ13-*, TECH2-*) : uniques, et le tenant + son index se lisent dans le nom. Les numeros de VLAN encodaient deja l'index ; les noms le font maintenant aussi. 2. Drapeau federe. decouvrir() saute toute nomenclature avec `federe: false` (defaut true). Permet d'exclure un bac a sable LOCAL (labo, sans remote, pas sur la fabric de production) : on ne provisionne pas ses VLAN sur les switches de prod. Le labo genere toujours son propre inventaire. Verifie : make devis-reseau -> labo (1011-1016) exclu, restent Technolibre (1021-1026) et Chezlepro prod (1131-1136) ; SVI/ACL coherents (access-group == nom d'ACL) ; make verifier rc=0 CONFORME 20/20. Co-Authored-By: Claude Opus 4.8 --- scripts/devis_reseau.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/devis_reseau.py b/scripts/devis_reseau.py index 079ece2..ff8476a 100644 --- a/scripts/devis_reseau.py +++ b/scripts/devis_reseau.py @@ -45,7 +45,9 @@ def decouvrir() -> list[tuple[str, str, dict]]: for chemin in sorted(DOSSIER_INSTANCES.glob("*/plan/nomenclature.yml")): n = yaml.safe_load(chemin.read_text(encoding="utf-8")) or {} # Un tenant federe = une nomenclature avec un index (l'adressage en decoule). - if n.get("index") is not None and n.get("categories"): + # `federe: false` exclut un bac a sable local (labo) du reseau converge : + # il ne partage pas la fabric de production, on ne provisionne pas ses VLAN. + if n.get("index") is not None and n.get("categories") and n.get("federe", True): nom = chemin.parent.parent.name tenants.append((nom, prefixe(nom), n)) tenants.sort(key=lambda t: t[2]["index"]) @@ -68,7 +70,7 @@ def generer(tenants: list[tuple[str, str, dict]]) -> str: for zone in sorted(n["categories"]): c = n["categories"][zone] out.append(f"vlan {vlan_de(n['index'], zone)}") - out.append(f" name {pfx}-{c['libelle']}") + out.append(f" name {pfx}{n['index']}-{c['libelle']}") out += ["!", "! ----- 2. Interfaces de routage (SVI = passerelle des hotes) -----"] for nom, pfx, n in tenants: m = masque(int(n.get("cidr_hote", 24))) @@ -77,12 +79,12 @@ def generer(tenants: list[tuple[str, str, dict]]) -> str: out.append(f"interface Vlan{vlan_de(n['index'], zone)}") out.append(f" description {nom}-{c['libelle']}") out.append(f" ip address {passerelle_de(n['index'], zone)} {m}") - out.append(f" ip access-group {pfx}-ISOLATION in") + out.append(f" ip access-group {pfx}{n['index']}-ISOLATION in") out.append(" no shutdown") out += ["!", "! ----- 3. ACL d'isolation tenant (default-deny inter-tenant) -----"] for nom, pfx, n in tenants: reseau, wild = reseau_wildcard(supernet_de(n["index"])) - out.append(f"ip access-list extended {pfx}-ISOLATION") + out.append(f"ip access-list extended {pfx}{n['index']}-ISOLATION") out.append(f" remark Intra-tenant {nom} : routage local autorise") out.append(f" permit ip {reseau} {wild} {reseau} {wild}") for autre_nom, _, autre in tenants: