Set-OPS-Public/roles/client_sante/templates/setops-sante.sh.j2
Daniel Allaire 018d55ec6c supervision : le site rapporte aussi — et deux corrections pour que ca MARCHE
7 machines du site deployees, 0 echec au playbook — et CINQ rapports sur
sept en TimeoutError. Un playbook vert ne prouve pas qu une chose
fonctionne ; seul l essai de bout en bout l a dit.

1. LE PAIR DE LA FRONTIERE. Le role client declarait son egress 5665, la
politique de sortie etait accept, la regle d entree de l hote autorisait
la source — et les paquets mouraient ENTRE les deux. La frontiere filtre
l inter-zones du site et ne resout que les roles que les machines PORTENT
AU PLAN ; une integration universelle n y figure pas, elle est derivee.
pair: client_sante produisait donc une regle est-ouest correcte et AUCUNE
regle a la frontiere. Le pair devient serveur_debian — le vocabulaire du
depot pour « tout noeud », que le generateur traite deja comme tel, et
exact au sens strict. Six regles creees, zero retiree, une par patte de
zone.

2. LE RAPPORTEUR S ACCUSAIT LUI-MEME. Pendant l heure de blocage,
setops-sante.service a echoue ; une fois debloque, cinq machines ont
rapporte CRITIQUE en citant leur propre rapporteur, et systemd garde l
etat failed jusqu a un reset-failed. Sa propre unite est desormais exclue
du compte — non par complaisance : sa sante est deja mesuree, et mieux,
par la FRAICHEUR de ses envois. S il ne peut plus parler, le ttl perime le
service, ce qui se voit precisement quand il ne peut PAS ecrire.

ETAT FINAL : 7/7 au site, 14/14 au tenant, tous OK. Controle negatif
rejoue sur les deux flottes.

make prouver : CONFORME, 63 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 20:48:36 -04:00

89 lines
4.4 KiB
Django/Jinja

#jinja2: comment_start_string:'{=#', comment_end_string:'#=}'
#!/bin/bash
# GENERE par Set-OPS (role client_sante). Ne pas editer a la main.
#
# (Le gabarit redefinit le delimiteur de commentaire Jinja : `${#tableau[@]}` contient
# la sequence `{#`, que Jinja lirait comme un debut de commentaire — et le rendu
# echouait sur « Missing end of comment tag ». Le shell a besoin de `${#...}` ; c'est
# donc a Jinja de s'ecarter.)
#
# CE NOEUD RAPPORTE SES UNITES EN ECHEC — parce que personne d'autre ne peut le voir.
#
# CE QUI A REVELE LE BESOIN (2026-09-09). `openipmi.service` echouait a CHAQUE demarrage
# sur les quatorze machines depuis le 2026-09-02. `systemctl --failed` rendait pourtant
# ZERO partout — non parce qu'elles allaient bien, mais parce qu'aucune n'avait REDEMARRE
# depuis. Six jours et vingt heures pour la premiere. Il a fallu qu'un humain redemarre
# une machine pour que le defaut existe aux yeux de quelqu'un.
#
# Un controle qui ne peut echouer qu'au demarrage ne mesure rien tant que rien ne demarre.
#
# POURQUOI UN RAPPORT PASSIF, ET PAS UN CONTROLE ACTIF. Un controle actif ne voit pas la
# machine MUETTE : si elle ne repond plus, la sonde echoue et on croit a un probleme de
# reseau. Ici c'est le noeud qui parle, avec un `ttl` : sans nouvelle, Icinga perime le
# service tout seul. Le silence alerte autant que l'echec — et le silence est precisement
# ce qui n'a alerte personne.
set -uo pipefail
API="https://{{ client_sante_icinga_hote }}.{{ domaine_interne }}:5665"
TTL={{ client_sante_ttl_icinga }}
MOI="{{ inventory_hostname }}"
MOTDEPASSE="$(cat /etc/setops/icinga-api.pass)"
rapporter() { # $1=code $2=texte
local charge reponse
charge=$(python3 -c 'import json,sys; print(json.dumps({
"type": "Service", "service": sys.argv[1], "exit_status": int(sys.argv[2]),
"plugin_output": sys.argv[3], "ttl": int(sys.argv[4])}))' \
"${MOI}!sante" "$1" "$2" "${TTL}")
reponse=$(curl -sS --cacert "{{ client_sante_ca_verification }}" --max-time 20 \
-u "{{ client_sante_icinga_utilisateur }}:${MOTDEPASSE}" \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-X POST "${API}/v1/actions/process-check-result" -d "${charge}" 2>&1)
if ! printf '%s' "${reponse}" | grep -q '"code": *200'; then
echo "ECHEC du rapport Icinga : ${reponse}" >&2
exit 1
fi
}
# `--plain` et `--no-legend` : la sortie doit etre analysable, pas jolie. Sans eux,
# systemd insere une puce « ● » en tete de ligne, qui devient le premier champ.
# SA PROPRE UNITE EST EXCLUE, ET CE N'EST PAS SE MENAGER.
#
# Mesure du 2026-09-09 sur le site : le pare-feu a bloque les rapports pendant une heure,
# `setops-sante.service` a donc echoue, et cinq machines se sont mises a rapporter
# CRITIQUE en citant... leur propre rapporteur. Le blocage corrige, l'accusation restait :
# systemd garde l'etat `failed` jusqu'a un `reset-failed`. Un rapporteur qui trebuche une
# fois s'accuserait indefiniment.
#
# La sante du rapporteur est DEJA mesuree, et mieux : par la FRAICHEUR de ses envois. S'il
# ne peut plus parler, Icinga perime le service tout seul (`ttl`) — ce qui se voit
# precisement quand il ne peut PAS ecrire, alors que sa propre unite en echec ne se voit
# que quand il le peut. Se compter soi-meme, c'est mesurer deux fois la meme chose, dont
# une fois mal.
mapfile -t echecs < <(systemctl list-units --state=failed --plain --no-legend 2>/dev/null \
| awk '{print $1}' | grep -vx 'setops-sante.service')
{% if client_sante_unites_tolerees %}
# UNITES TOLEREES, NOMMEES UNE PAR UNE. Jamais un motif large : un filtre qui cache une
# unite en cache d'autres, et on ne s'en apercoit que le jour ou l'on cherche pourquoi
# rien n'a alerte.
tolerees=({% for u in client_sante_unites_tolerees %}"{{ u }}" {% endfor %})
restantes=()
for u in "${echecs[@]}"; do
garder=1
for t in "${tolerees[@]}"; do [[ "$u" == "$t" ]] && garder=0 && break; done
[[ $garder -eq 1 ]] && restantes+=("$u")
done
echecs=("${restantes[@]}")
{% endif %}
n=${#echecs[@]}
if [[ $n -eq 0 ]]; then
rapporter 0 "Aucune unite systemd en echec."
exit 0
fi
# CRITIQUE des la premiere, et non un seuil. Une unite en echec est soit un vrai
# probleme, soit du bruit qu'il faut retirer : dans les deux cas il faut agir. Un seuil
# ferait vivre le bruit indefiniment, et c'est exactement ce qu'on vient de corriger.
rapporter 2 "$n unite(s) systemd en echec : ${echecs[*]}"