77 lines
3.5 KiB
Text
77 lines
3.5 KiB
Text
|
|
#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.
|
||
|
|
mapfile -t echecs < <(systemctl list-units --state=failed --plain --no-legend 2>/dev/null \
|
||
|
|
| awk '{print $1}')
|
||
|
|
|
||
|
|
{% 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[*]}"
|