Gabarit setops-rapport-attendu : actif, dummy critique, check_interval = le ttl que le noeud envoie. Prouve a t+60 s sur site-mon-01, deploye sur les trois Icinga ; la garde test_fraicheur_icinga lie seuils et ttl. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.7 KiB
Python
66 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Les seuils de fraicheur d'Icinga suivent les `ttl` que les noeuds envoient.
|
|
|
|
UNE LISTE QUI EN SUIT UNE AUTRE PREND DU RETARD (2026-09-28). Les services passifs de
|
|
Set-OPS passent CRITIQUES quand aucun rapport n'arrive dans leur `check_interval`. Ce
|
|
seuil vit dans `serveur_icinga` ; le `ttl` que chaque noeud envoie vit dans le role qui
|
|
rapporte. Si le seuil devient plus court que le rythme des rapports, tout rougit a tort ;
|
|
plus long, un noeud muet reste vert trop longtemps. Les deux doivent etre egaux.
|
|
|
|
Et plus aucun service passif ne doit revenir a `enable_active_checks = false` : c'est
|
|
exactement ce qui laissait un service jamais alimente « en attente », jamais rouge.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
RACINE = Path(__file__).resolve().parents[2]
|
|
ROLES = RACINE / "roles"
|
|
|
|
|
|
def defauts(role: str) -> dict:
|
|
return yaml.safe_load((ROLES / role / "defaults" / "main.yml").read_text(encoding="utf-8")) or {}
|
|
|
|
|
|
def main() -> int:
|
|
icinga = defauts("serveur_icinga")
|
|
paires = [
|
|
("serveur_icinga_fraicheur_sauvegarde", "client_backup", "client_backup_ttl_icinga"),
|
|
("serveur_icinga_fraicheur_sauvegarde", "serveur_backup", "serveur_backup_ttl_icinga"),
|
|
("serveur_icinga_fraicheur_sante", "client_sante", "client_sante_ttl_icinga"),
|
|
("serveur_icinga_fraicheur_sondes", "client_sante", "client_sante_ttl_sondes"),
|
|
]
|
|
echecs = 0
|
|
for seuil, role, ttl in paires:
|
|
a, b = icinga.get(seuil), defauts(role).get(ttl)
|
|
if a is None or b is None or int(a) != int(b):
|
|
print(f"ECHEC {seuil} = {a} ≠ {role}.{ttl} = {b}")
|
|
echecs += 1
|
|
else:
|
|
print(f"ok {seuil} = {role}.{ttl} = {a}")
|
|
|
|
gabarits = ROLES / "serveur_icinga" / "templates"
|
|
for f in sorted(gabarits.glob("setops-*.conf.j2")):
|
|
code = re.sub(r"/\*.*?\*/|\{#.*?#\}", "", f.read_text(encoding="utf-8"), flags=re.S)
|
|
for bloc in re.findall(r'object Service "[^"]*" \{.*?\n\}', code, flags=re.S):
|
|
if "enable_passive_checks = true" in bloc and "setops-rapport-attendu" not in bloc:
|
|
print(f"ECHEC {f.name} : service passif sans `setops-rapport-attendu` :\n{bloc[:120]}")
|
|
echecs += 1
|
|
if "enable_active_checks = false" in code:
|
|
print(f"ECHEC {f.name} : `enable_active_checks = false` — un service jamais "
|
|
f"alimente resterait « en attente », jamais rouge")
|
|
echecs += 1
|
|
|
|
if echecs:
|
|
print(f"\n{echecs} echec(s).")
|
|
return 1
|
|
print("OK — fraicheur d'Icinga alignee sur les ttl, aucun service passif sans echeance.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|