Livestatus avec Nagios

décembre 13, 2014  |   Actualités,Blog   |     |   0 commentaire

Introduction

Dans le monde de la supervision Nagios a été très largement adopté de part sa gratuité et sa licence Opensource. Malgrè un moteur efficace, Nagios dispose d’une interface plus ou moins intuitive et réactive suivant les usages.

Toutefois, il est possible d’ajouter des “broker” au moteur Nagios afin d’accèder à la base de données via une autre application et traiter ces informations de manière intuitive et en temps réel.

Parmi ces broker, celui qui nous interesse aujourd’hui est “MK Livestatus”. Ce module, à l’inverse de son confrère ndo2db qui synchronise la base de données Nagios dans une base SQL, ouvre un socket unix et nous permet d’accèder via LQL (langage créé pour cet usage) à un ensemble d’information du moteur Nagios sans générer d’accès disque.

Module mklivestatus

A ce jour, la version distribuée est la 1.2.4p5 et s’installe en toute simplicité grâce à la procédure fournie sur le site de l’éditeur [3].

L’idée première de ce module est de d’obtenir l’état des indicateurs d’un moteur Nagios grâce à un langage de type base de données. L’accès à ces données permet ensuite de venir recolter les données de plusieurs collecteurs sur une seule et unique console de gestion (mk_multisite).

Cependant, d’autres éditeurs ont profité d’avoir un accès efficace et temps réel à l’état des indicateurs de Nagios pour developpé des interfaces intuitives et pertinentes.

Parmi ces outils nous pouvons citer POM [6], Nagvis [7], Thruk [8], …

Quelques exemples d’utilisation

Une autre utilisation est de générer des rapports et effectuer des synthèses très simplement grâce à LQL qui permet de sélectionner de mannière précise les informations qui nous interesse.

Le lien [4] liste les champs interrogeables/filtrables ainsi que les valeurs possibles pour chacun d’eux. (Note : La version de livestatus décrite sur ce lien est légerement différente. Certains champs n’existe pas (ou pas encore) dans la version officielle.)

Exemple de requête :

GET hosts
Columns: host_name state last_hard_state_change acknowledged
Filter: state != 0
Filter: state_type = 1 

Cette requête permet d’obtenir le statut des hosts en récuréperant :

  • host_name : Le nom
  • state : L’état
  • last_hard_state_change : La date du dernier changement d’état
  • acknowledged : Si l’état est acquité

Cependant les filtres nous permettent de séléctionner uniquement les résultats avec :

  • state != 0 : Uniquement les hosts avec un état non OK
  • state_type = 1 : Uniquement si l’état non OK est de type “HARD STATE”


Capture d’écran

Voici par exemple l’ensemble des éléments permettant d’obtenir cette sythèse quotidienne de l’état de Nagios le matin à 7h.

 

crontab :

0 7 * * * /root/rapports/send_report.sh
hosts_request.live :
GET hosts
Columns: host_name state last_hard_state_change acknowledged
Filter: state != 0
Filter: state_type = 1 

synthese_request.live :

GET services
Columns: host_name description state last_hard_state_change acknowledged
Filter: state != 0
Filter: state_type = 1 

header.mail :

MIME-Version: 1.0
Content-Type: text/html; boundary='nagios/nagios@domain'
<html>
<head>
<title>HTML E-mail</title>
</head>
<body style=\"font-family: "Open Sans";\"> 

footer.mail :

</p>
</body>
</html> 

send_report.sh :

#!/bin/bash
hosts_request="/root/rapports/hosts_request.live"
services_request="/root/rapports/services_request.live"

hosts_result="/root/rapports/hosts_request.db"
services_result="/root/rapports/services_request.db" 

livestatus_socket="/usr/lib/nagios/mk-livestatus/live" 

hosts_down="/root/rapports/hosts_down.db"
hosts_unreach="/root/rapports/hosts_unreach.db"

services_crit="/root/rapports/services_crit.db"
services_warn="/root/rapports/services_warn.db"
services_unkn="/root/rapports/services_unkn.db" 

mail_dest="/root/rapports/dest.mail"
mail_important=0
mail_header="/root/rapports/header.mail"
mail_body="/root/rapports/body.mail"
mail_footer="/root/rapports/footer.mail"

emetteur="From: rapport-nagios@domain.com"
destinataire="Bcc: dest1@domain.com, dest2@domain.com"

host_problem=0
service_problem=0

stats_down=0
stats_unreachable=0
stats_critical=0
stats_warning=0
stats_unknown=0

echo "" > $hosts_down
echo "" > $hosts_unreach
echo "" > $services_crit
echo "" > $services_warn
echo "" > $services_unkn

cat "$hosts_request" | /usr/local/bin/unixcat "$livestatus_socket" > "$hosts_result"
cat "$services_request" | /usr/local/bin/unixcat "$livestatus_socket" > "$services_result"

# Process Hosts
while IFS=';' read -r host_name state time ack
do
    host_problem=$(( $host_problem +1 ))
    time=$(date -d @$time +"%a %d/%m/%y - %H:%I")
    if (test $state -eq 1); then
            stats_down=$(( $stats_down+1 ))
            if (test $ack -eq 1); then
                    echo "<tr><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: red; border: 1px solid black;\">DOWN</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">YES</td></tr>" >> $hosts_down
            else
                    mail_important=1
                    echo "<tr style=\"background: #F66;\"><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: red; border: 1px solid black;\">DOWN</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">NO</td></tr>" >> $hosts_down
            fi
    else
            stats_unreachable=$(( $stats_unreachable+1 ))
            if (test $ack -eq 1); then
                    echo "<tr><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: #A06; border: 1px solid black;\">UNREACHABLE</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">YES</td></tr>" >> $hosts_unreach
            else
                    echo "<tr style=\"background: #A48;\"><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: #A06; border: 1px solid black;\">UNREACHABLE</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">NO</td></tr>" >> $hosts_unreach
            fi
    fi
done < "$hosts_result"

# Process Services
while IFS=';' read -r host_name service_name state time ack
do
    service_problem=$(( $service_problem +1 ))
    time=$(date -d @$time +"%a %d/%m/%y - %H:%I") 
    if (test $state -eq 2); then
            stats_critical=$(( $stats_critical +1 ))
            if (test $ack -eq 1); then
                    echo "<tr><td style=\"border: 1px solid black;\">$service_name</td><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: red; border: 1px solid black;\">CRITICAL</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">YES</td></tr>" >> $services_crit 
            else
                    mail_important=1
                    echo "<tr style=\"background: #F66;\"><td style=\"border: 1px solid black;\">$service_name</td><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: red; border: 1px solid black;\">CRITICAL</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">NO</td></tr>" >> $services_crit
            fi
    elif (test $state -eq 1); then
            stats_warning=$(( $stats_warning+1 ))
            if (test $ack -eq 1); then
                    echo "<tr><td style=\"border: 1px solid black;\">$service_name</td><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: #FA0; border: 1px solid black;\">WARNING</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">YES</td></tr>" >> $services_warn
            else
                    echo "<tr style=\"background: #FC6;\"><td style=\"border: 1px solid black;\">$service_name</td><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: #FA0; border: 1px solid black;\">WARNING</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">NO</td></tr>" >> $services_warn
            fi
    else
            stats_unknown=$(( $stats_unknown+1 ))
            if (test $ack -eq 1); then
                    echo "<tr><td style=\"border: 1px solid black;\">$service_name</td><td style=\"border: 1px solid black;\">$host_name</td><td style\"color: white; background: #A06;\">UNKNOWN</td><td style=\"border: 1px solid black; border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">YES</td></tr>" >> $services_unkn
            else
                    echo "<tr style=\"background: #A48;\"><td style=\"border: 1px solid black;\">$service_name</td><td style=\"border: 1px solid black;\">$host_name</td><td style=\"color: white; background: #A06; border: 1px solid black;\">UNKNOWN</td><td style=\"border: 1px solid black;\">$time</td><td style=\"border: 1px solid black;\">NO</td></tr>" >> $services_unkn
            fi
    fi
done < "$services_result" 
echo "" > $mail_body
if test $host_problem -ne 0; then
    echo -n "<h3>Host(s) Problem(s) :</h3>" >> $mail_body
    echo -n "<table style=\"border-collapse: collapse; text-align: center;\"><tr><th>Host</th><th>State</th><th>Since</th><th>ACK</th></tr>" >> $mail_body
    cat $hosts_down >> $mail_body
    cat $hosts_unreach >> $mail_body
    echo -n "</table><br /><br />" >> $mail_body
else
    echo "<h3>No host problem was listed</h3>" >> $mail_body
fi 
if test $service_problem -ne 0; then
    echo -n "<hr /><h3>Service(s) Problem(s) :</h3>" >> $mail_body
    echo -n "<table style=\"border-collapse: collapse; text-align: center;\"><tr><th>Service</th><th>Host</th><th>State</th><th>Since</th><th>ACK</th></tr>" >> $mail_body
    cat $services_crit >> $mail_body
    cat $services_warn >> $mail_body
    cat $services_unkn >> $mail_body
    echo -n "</table>" >> $mail_body
else
            echo "<hr /><h3>No service problem was listed</h3>" >> $mail_body
fi 

echo $emetteur > $mail_dest
echo $destinataire >> $mail_dest
echo "Subject: Nagios - Hosts: $stats_down/$stats_unreachable - Services: $stats_critical/$stats_warning/$stats_unknown - $(date "+%Y-%m-%d %H:%M")" >> $mail_dest
echo "MIME-Version: 1.0" >> $mail_dest
echo "Content-Type: text/html; boundary='nagios/nagios@domain'" >> $mail_dest 
if test $mail_important -eq 1; then
    echo "X-Priority: 1 (Highest)" >> $mail_dest
    echo "X-MSMail-Priority: High" >> $mail_dest
    echo "Importance: High" >> $mail_dest
fi

cat $mail_dest $mail_header $mail_body $mail_footer | /usr/sbin/sendmail -t

 

Bibliographie

[1] http://fr.wikipedia.org/wiki/Nagios

[2] http://mathias-kettner.com/index.html

[3] https://mathias-kettner.de/checkmk_livestatus.html

[4] http://www.naemon.org/documentation/usersguide/livestatus.html

[5] https://mathias-kettner.de/checkmk_multisite.html

[6] http://www.pom-monitoring.com/

[7] http://www.nagvis.org/

[8] http://www.thruk.org/