diff --git a/CHANGELOG.md b/CHANGELOG.md index e675419..ea47f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,12 @@ frères (`decouvrir()`), alors que la frontière et le SDN s'en tiennent à proposait donc de recréer ses groupes ; le poste comptait un dossier de CI comme tenant. Les deux devis suivent maintenant la même liste : 2 tenants, et non 3. +Filtré ainsi, le devis ne voyait plus du tout `t29` — ni à créer, ni à RETIRER : son +périmètre ne retient que les préfixes des tenants présents. 3 IPSets et 6 groupes `t29-` +restaient posés sur le cluster. `appliquer_proxmox_fw.py` ajoute à son périmètre les +étiquettes des zones de `ANCIEN_NOMMAGE` (une liste, pas deux), et reçoit le même garde +que le SDN contre un cluster muet. + Wiki republié (P60) : deux de ses pages nommaient patient 0. `make verifier` : 82 OK, 1 échec — P02, `test_ecriture_plan.py` sur `domaines.yml` (`'list' object has no attribute 'get'`), présent avant ce changement. diff --git a/scripts/appliquer_proxmox_fw.py b/scripts/appliquer_proxmox_fw.py index 712e8a0..e55a708 100644 --- a/scripts/appliquer_proxmox_fw.py +++ b/scripts/appliquer_proxmox_fw.py @@ -83,8 +83,36 @@ def _regle_cle(r: dict) -> tuple: str(r.get("dport") or "")) +def _prefixes_retires() -> tuple[str, ...]: + """Les etiquettes des tenants RETIRES : `t29-` pour la zone `t29`. + + UN TENANT RETIRE SORT DU PERIMETRE, ET SES OBJETS AVEC (2026-09-28). Le perimetre ne + retient que les prefixes du devis ; un index libere n'y est plus, donc ses IPSets et + ses groupes n'existaient plus pour ce script — ni a creer, ni a retirer. Ils restaient + poses. La liste n'est pas ecrite ici : c'est celle du SDN (`ANCIEN_NOMMAGE`), dont les + zones `t` portent la meme etiquette que les IPSets. Une liste, pas deux. + """ + import devis_sdn + return tuple(f"{z}-" for z in devis_sdn.ANCIEN_NOMMAGE + if z.startswith("t") and z[1:].isdigit()) + + +def _lire(api: Cluster, chemin: str): + """Une lecture du cluster, ou l'arret : un cluster muet n'est pas un cluster vide. + + Meme defaut, meme correctif que `appliquer_sdn._lire` (2026-09-28) : `rep or []` + parcourait le dict d'erreur comme une liste vide, et le plan proposait de tout creer. + """ + rep = api(chemin) + if api.rate(rep): + raise SystemExit(f"Le cluster {api.hote} ne repond pas sur `{chemin}` : " + f"{api.rate(rep)}\n (un cluster injoignable serait lu comme un " + f"cluster VIDE, et le plan proposerait de tout recreer)") + return rep + + def plan(api: Cluster, devis: dict) -> dict: - prefixes = tuple(_prefixe(b) for b in devis["blocs"] if _prefixe(b)) + prefixes = tuple(_prefixe(b) for b in devis["blocs"] if _prefixe(b)) + _prefixes_retires() ipsets_voulus, groupes_voulus, affect_voulues = {}, {}, {} for b in devis["blocs"]: @@ -98,20 +126,20 @@ def plan(api: Cluster, devis: dict) -> dict: # --- etat du cluster, restreint a nos prefixes ----------------------------- ipsets_poses = {} - for s in (api("/cluster/firewall/ipset") or []): + for s in (_lire(api, "/cluster/firewall/ipset") or []): if isinstance(s, dict) and str(s.get("name", "")).startswith(prefixes): membres = [str(m.get("cidr")) for m in (api(f"/cluster/firewall/ipset/{s['name']}") or []) if isinstance(m, dict)] ipsets_poses[s["name"]] = sorted({_norm(m) for m in membres}) groupes_poses = {} - for g in (api("/cluster/firewall/groups") or []): + for g in (_lire(api, "/cluster/firewall/groups") or []): if isinstance(g, dict) and str(g.get("group", "")).startswith(prefixes): regles = [r for r in (api(f"/cluster/firewall/groups/{g['group']}") or []) if isinstance(r, dict)] groupes_poses[g["group"]] = regles - vm_du_cluster = {int(r["vmid"]): r["node"] for r in (api("/cluster/resources?type=vm") or []) + vm_du_cluster = {int(r["vmid"]): r["node"] for r in (_lire(api, "/cluster/resources?type=vm") or []) if isinstance(r, dict) and r.get("vmid")} affect_posees, vm_absentes = {}, []