Archivi tag: service

Nagios: script bash per monitorare lo stato dei volumi RAID

Partendo dalle considerazioni fatte in questo post, ho deciso di mettere a punto uno script bash da integrare a Nagios, in modo da monitorare lo status dei volumi RAID (e dei dischi fisici annessi) a prescindere dal metodo utilizzato per l’implementazione di tale tecnologia (hardware, fake oppure software).

nagiosDi seguito riporto il suddetto script nella sua interezza:

#!/bin/bash

type=$1

subtype=$2

element=$3

usage="check_raid <--software|--fake|--hardware> [--megaraid|--mpt] [--volume|--physical|--battery]"

if [[ ! -z "$type" && "$type" =~ "software" ]];then
        okswraid=0;
        koswraid=0;
        volumes=`cat /proc/mdstat | grep md | grep active | grep -v inactive | awk '{print $1}' | wc -l`
        if [[ ! -z $volumes ]];then
                for (( v=1; v<=$volumes; v++ ))
                do
                        volume=`cat /proc/mdstat | grep md | grep active | grep -v inactive | awk '{print $1}' | sed -n "$v p"`
                        raidtype=`cat /proc/mdstat | grep md | grep active | grep -v inactive | awk '{print $4}' | sed -n "$v p"`
                        diskno=`cat /proc/mdstat | grep '[[0-9]\/[0-9]]' | awk '{print $3}' | sed -n "$v p"`
                        disksok=`echo $diskno | sed 's/\[//g' | cut -d '/' -f1`
                        diskstotal=`echo $diskno | sed 's/\]//g' | cut -d '/' -f2`
                        if [[ "$disksok" -eq "$diskstotal" ]];then
                                echo "OK: Software RAID volume $volume configured in $raidtype is OK, with $diskno disks UP"
                                ((okswraid++))
                        elif [[ "$disksok" -lt "$diskstotal" ]];then
                                echo "CRITICAL: Software RAID volume $volume configured in $raidtype is CRITICAL, with $diskno disks UP"
                                ((koswraid++))
                        fi
                done

                if [[ $koswraid -eq 0 ]];then
                        exit 0;
                else
                        exit 2;
                fi
        else
                echo "UNKNOWN: No software RAID configured"
                exit 3;
        fi

elif [[ ! -z "$type" && "$type" =~ "fake" ]];then
        bin=`/usr/bin/which dmraid`
        if [[ ! -z $bin ]];then
                result=`$bin -s`
                disksno=`$bin -r | grep -v no | wc -l`
                disksok=`$bin -r | grep ok | wc -l`
                if [[ ! -z "$result" && "$result" =~ "ok" ]];then
                        echo "OK: RAID Status is OK, with $disksok/$disksno disks OK"
                        exit 0;
                elif [[ ! -z "$result" && "$result" =~ "no raid" ]];then
                        echo "UNKNOWN: no fake RAID configured"
                        exit 3;
                else
                        echo "CRITICAL: RAID Status is KO, with $disksok/$disksno disks OK"
                        exit 2;
                fi
        else
                echo "UNKNOWN: no dmraid binary found - please install dmraid"
                exit 3;
        fi

elif [[ ! -z "$type" && "$type" =~ "hardware" ]];then
        okraid=0;
        oksmart=0;
        koraid=0;
        kosmart=0;
        if [[ ! -z "$subtype" && "$subtype" =~ "--megaraid" ]];then
                bin=`/usr/bin/which MegaCli64`
                if [[ ! -z $bin ]];then
                        if [[ ! -z "$element" && "$element" =~ "--volume" ]];then
                                result=`$bin -LDinfo -Lall -aALL | grep State | awk '{print $3}'`
                                if [[ ! -z "$result" && $result =~ "Optimal" ]];then
                                        echo "OK: RAID Volume state is $result"
                                        exit 0;
                                else
                                        echo "CRITICAL: RAID Volume state is $result"
                                        exit 2;
                                fi
                        elif [[ ! -z "$element" && "$element" =~ "--physical" ]];then
                                diskno=`$bin -PDList -aALL | grep "S.M.A.R.T alert" | wc -l`
                                for (( d=1; d<=$diskno; d++ ))
                                do
                                        result=`$bin -PDList -aALL | grep "Firmware state" | sed -n "$d p" | awk '{print $3}' | sed 's/,//g'`
                                        if [[ ! -z "$result" && $result =~ "Online" ]];then
                                                echo "RAID Status for Physical Disk number $d is OK"
                                                ((okraid++));
                                        else
                                                echo "RAID Status for Physical Disks number $d is KO"
                                                ((koraid++));
                                        fi
                                done
                                for (( d=1; d<=$diskno; d++ ))
                                do
                                        result=`$bin -PDList -aALL | grep "S.M.A.R.T alert" | sed -n "$d p" | awk '{print $8}'`
                                        if [[ ! -z "$result" && $result =~ "No" ]];then
                                                echo "S.M.A.R.T Status for Physical Disk number $d is OK"
                                                ((oksmart++));
                                        else
                                                echo "S.M.A.R.T. Status for Physical Disks number $d is KO"
                                                ((kosmart++));
                                        fi
                                done
                                if [[ $koraid -eq 0 && $kosmart -eq 0 ]];then
                                        echo "OK: RAID and S.M.A.R.T Status for all Physical Disks is OK"
                                        exit 0;
                                elif [[ $koraid -eq 0 && $kosmart -ne 0 ]];then
                                        echo "CRITICAL: S.M.A.R.T Status for some Physical Disks is KO"
                                        exit 2;
                                elif [[ $koraid -ne 0 && "$kosmart" -eq 0 ]];then
                                        echo "CRITICAL: RAID Status for some Physical Disks is KO"
                                        exit 2;
                                elif [[ $koraid -ne 0 && $kosmart -ne 0 ]];then
                                        echo "CRITICAL: RAID and S.M.A.R.T Status for some Physical Disks is KO"
                                        exit 2;
                                fi
                        elif [[ ! -z "$element" && "$element" =~ "--battery" ]];then
                                result=`$bin -AdpBbuCmd -aAll | grep "Battery State" | awk '{print $3}'`
                                if [[ ! -z "$result" && $result =~ "OK" ]];then
                                        echo "OK: RAID Controller Battery state is OK"
                                        exit 0;
                                else
                                        echo "CRITICAL: RAID Controller Battery state is $result"
                                        exit 2;
                                fi
                        else
                                echo "UNKNOWN: please specify the element to check"
                                echo $usage;
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: No MegaCli64 binary found - please install MegaCli64"
                        exit 3;
                fi

        elif [[ ! -z "$subtype" && "$subtype" =~ "mpt" ]];then
                modprobe mptctl
                bin=`/usr/bin/which mpt-status`
                bin2=`/usr/bin/which lspci`
                bin3=`/usr/bin/which daemonize`
                if [[ ! -z $bin ]];then
                        if [[ ! -z $bin2 ]];then
                                controller_status=`lspci | grep MPT`
                                if [[ ! -z $controller_status ]];then
                                        if [[ ! -z $bin3 ]];then
                                                controller=`$bin -p | grep id | awk '{print $3}' | sed 's/id=//g' | sed 's/,//g'`
                                                if [[ ! -z $controller ]];then
                                                        result=`$bin -i $controller | grep OPTIMAL`
                                                        if [[ ! -z "$result" ]];then
                                                                echo "OK: RAID Status is OPTIMAL"
                                                                exit 0;
                                                        else
                                                                echo "CRITICAL: RAID Status is DEGRADED"
                                                                exit 2;
                                                        fi
                                                else
                                                        echo "UNKNOWN: MPT Controller found but no RAID configured";
                                                        exit 3;
                                                fi
                                        else
                                                echo "UNKNOWN: No daemonize binary found - please install daemonize";
                                                exit 3;
                                        fi
                                else
                                        echo "UNKNOWN: Unable to find RAID Controller";
                                        exit 3;
                                fi
                        else
                                echo "UNKNOWN: No lspci binary found - please install lspci";
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: No mpt-status binary found - please install mpt-status"
                        exit 3;
                fi

        else
                echo "UNKNOWN: please specify the RAID Controller type"
                echo $usage
                exit 3;
        fi
else
        echo "UNKNOWN: please specify the RAID type"
        echo $usage
        exit 3;
fi
exit 0

Lo usage parla chiaro: il primo argomento identifica, per l’appunto, la tecnologia RAID utilizzata sul sistema target. Il secondo ed il terzo argomento, invece, dovranno essere specificati solo nel caso in cui si abbia a che fare con un RAID di tipo hardware. Nella fattispecie, essi rappresentano, rispettivamente, la tipologia di chipset utilizzata dal controller e l’oggetto di interesse della nostra query, ovvero il volume, i dischi fisici oppure la batteria (tale parametro ha senso solo se il chipset è di tipo LSI MegaRAID).

Configurazione di Nagios

Come al solito, il primo step consiste nel definire un comando che utilizzi lo script (in gergo plugin) riportato in precedenza:

# 'check_local_raid' command definition
define command{
        command_name    check_local_raid
        command_line    $USER1$/check_raid $ARG1$ $ARG2$ $ARG3$
        }

tali direttive andranno opportunamente inserite all’interno del file /etc/nagios/objects/commands.cfg.

Successivamente si potrà procedere con la definizione del servizio che si occuperà del monitoraggio vero e proprio, da aggiungere alla configurazione dell’host target, in questo caso /etc/nagios/object/locahost.cfg:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_description             RAID Status
        check_command                   check_local_raid!--software
        }

A questo punto non ci rimane che ricaricare la configurazione di Nagios per rendere effettive le suddette modifiche:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

CentOS 6: Riavviare automaticamente il servizio barnyard2 mediante Nagios e gli event handlers

In questo post ho mostrato il codice sorgente del demone barnyard2 da me customizzato. Esso, in soldoni, non fa altro che monitorare il contenuto del file alert generato da snort, in modo da poter individuare gli allarmi creati dall’IDS in questione, inserendoli (dopo un’opportuna formattazione) all’interno di uno specifico DBMS (nel nostro caso MySQL).

Purtroppo, però, tale servizio tende a crashare in modo randomico, ragion per cui ho deciso di creare un event handler (per Nagios) in grado di riavviarlo automaticamente.

nagios

Configurazione del SO che ospita L’NMS (Nagios)

Poichè l’operazione di riavvio del demone barnyard2 richiede i privilegi di root, è stato necessario fare in modo che l’utente nagios (che esegue gli event handlers) fosse abilitato all’interno del file /etc/sudoers:

nagios   ALL=NOPASSWD: /sbin/service barnyard2 restart

In particolare, ho fatto in modo che l’esecuzione del comando sudo non richiedesse la password (ALL=NOPASSWD:) solo per il comando /sbin/service barnyard2 restart (per la serie less is more). Inoltre, sempre all’interno del suddetto file, ho inserito, subito dopo la direttiva Defaults    requiretty, la stringa:

Defaults:nagios        !requiretty

in modo tale da consentire all’utente nagios di lanciare il comando sudo anche quando non è in possesso di un terminale (tty). Ciò è necessario poichè tutti gli event handlers vengono lanciati dal nostro NMS in assenza di sessione tty.

Un’altra modifica altrettanto importante ha riguardato SElinux. Esso, infatti, essendo attivo in modalità Enforcing, vietava puntualmente l’esecuzione dell’event handler in questione. Per “aggirare” tale divieto, ho dovuto modificare alcune regole MAC (Mandatory Access Control), attraverso 2 passaggi: il settaggio di una variabile booleana e la creazione di un modulo custom per SElinux.

Nel primo caso è stato sufficiente lanciare il comando:

[root@NMS]# setsebool -P nagios_run_sudo 1

mentre nel secondo caso ho dapprima creato il file permitnagioseventhandlers.te, di cui riporto il contenuto:

module permitnagioseventhandler 1.0;

require {
        type nagios_system_plugin_t;
        type nagios_unconfined_plugin_exec_t;
        type nagios_eventhandler_plugin_t;
        type httpd_t;
        class file { getattr };
        class dir { getattr search };
}

#============= nagios_system_plugin_t ==============
allow nagios_system_plugin_t nagios_unconfined_plugin_exec_t:file {getattr};

#============= httpd_t ==============
allow httpd_t nagios_eventhandler_plugin_t:dir { getattr search };

per poi verificarne la sintassi:

[root@NMS]#  checkmodule -M -m -o permitnagioseventhandler.mod permitnagioseventhandler.te

compliarlo:

[root@NMS]# semodule_package -o permitnagioseventhandler.pp -m permitnagioseventhandler.mod

ed installarlo:

[root@NMS]# semodule -i permitnagioseventhandler.pp

Configurazione di Nagios

Il riavvio del demone barnyard2 richiede parecchio tempo (soprattutto se esso è stato associato a più interfacce di rete, come nel mio caso). Per questo motivo si è reso necessario modificare il paramentro event_handler_timeout presente all’interno del file di configurazione Nagios (/etc/nagios/nagios.cfg), portandolo da 30 secondi (valore di default) a 300 secondi:

event_handler_timeout=400

Per ciò che concerne il servizio (relativo al nostro NMS) che si occupa del monitoraggio di barnyard2, è stata creata la seguente configurazione:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_descripion             Barnyard2 Service Status
        check_command                   check_local_process_status_all!2!2!barnyard2
        event_handler                   restart_barnyard
        }

dove il comando check_local_process_status_all è così definito:

# 'check_local_process_status_all' command definition
define command{
        command_name    check_local_process_status_all
        command_line    $USER1$/check_procs -c $ARG1$:$ARG2$ -C $ARG3$
        }

Nella fattispecie, le variabili $ARG1$ e $ARG2$ rappresentano, rispettivamente, il numero minimo e massimo di processi (recanti la stringa barnyard2, specificata mediante la variabile $ARG3$) attivi sulla macchina da monitorare.

Inoltre, è stato definito il comando restart_barnyard, il cui scopo è quello di eseguire l’event handler in questione:

# 'restart_barnyard' command definition
define command {
        command_name      restart_barnyard
        command_line      /usr/lib64/nagios/plugins/eventhandlers/restart_barnyard $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
}

Ho quindi riavviato Nagios per rendere effettive le suddette modifiche:

[root@NMS]# service nagios reload

Contenuto dell’event handler (restart_barnyard)

Una volta completata la fase preliminare relativa alla configurazione del SO e dell’NMS, mi sono dedicato alla creazione dell’event handler vero e proprio (che ho chiamato, molto semplicemente, restart_barnyard). Esso presenta il seguente contenuto:

#!/bin/bash

case "$1" in
OK)
        ;;
WARNING)
        ;;
UNKNOWN)
        ;;
CRITICAL)
       case "$2" in
                SOFT)
                        case "$3" in
                        3)
                                echo -n "Restarting barnyard2 service (3rd soft critical state)..."
                                /usr/bin/sudo /sbin/service barnyard2 restart
                                ;;
                                esac
                        ;;
                HARD)
                        echo -n "Restarting barnyard2 service..."
                        /usr/bin/sudo /sbin/service barnyard2 restart
                        ;;
                esac
                ;;
        esac

exit 0

ovvero non fa altro che riavviare il servizio in oggetto nel caso del terzo critical state (soft) o del quarto critical state (hard).

L’ho quindi reso eseguibile:

[root@NMS]# chmod +x restart_barnyard

e l’ho salvato all’interno della dir /usr/lib64/nagios/plugins/eventhandlers:

[root@NMS]# mv restart_barnyard /usr/lib64/nagios/plugins/eventhandlers

Test di funzionamento

Infine, ho testato il tutto semplicemente arrestando il servizio barnyard2:

[root@NMS]# service barnyard2 stop

verificando che Nagios svolgesse tutta la trafila per ritirarlo su in modo automatico:

[root@NMS]# tail -f /var/log/nagios/nagios.log

il cui output mi ha mostrato le diverse fasi di passaggio dallo stato CRITICAL allo stato OK:

[1448964811] SERVICE EVENT HANDLER: localhost;Barnyard2 Service Status;CRITICAL;SOFT;3;restart_barnyard
[1448965026] SERVICE ALERT: localhost;Barnyard2 Service Status;CRITICAL;HARD;4;PROCS CRITICAL: 0 processes with command name 'barnyard2'
[1448965026] SERVICE EVENT HANDLER: localhost;Barnyard2 Service Status;CRITICAL;HARD;4;restart_barnyard
[1448965313] SERVICE ALERT: localhost;Barnyard2 Service Status;OK;HARD;4;PROCS OK: 2 processes with command name 'barnyard2'
[1448965313] SERVICE EVENT HANDLER: localhost;Barnyard2 Service Status;OK;HARD;4;restart_barnyard

Inoltre, digitando il comando:

[root@NMS]# ps aux | grep barn

ho visualizzato i processi di barnyard2 durante il loro avvio da parte dell’event handler:

nagios    2799  0.0  0.0 108208  1352 ?        S    11:17   0:00 /bin/bash /usr/lib64/nagios/plugins/eventhandlers/restart_barnyard CRITICAL HARD 4
root      2800  0.1  0.1 189744  3392 ?        S    11:17   0:00 /usr/bin/sudo /sbin/service barnyard2 restart
root      2803  0.0  0.0 106460  1680 ?        S    11:17   0:00 /bin/sh /sbin/service barnyard2 restart
root      2809  0.0  0.0 108568  1868 ?        S    11:17   0:00 /bin/sh /etc/init.d/barnyard2 restart
root      3194 65.8  1.2  92668 40796 ?        Rs   11:18   1:06 barnyard2 -D -c /etc/snort/barnyard2eth0.conf -d /var/log/snort/eth0 -w /var/log/snort/eth0/barnyard2.waldo -l /var/log/snort/eth0 -a /var/log/snort/eth0/archive -f snort.log --pid-path /var/run
root      3196  0.0  0.0 108200  1284 ?        S    11:18   0:00 /bin/bash -c ulimit -S -c 0 >/dev/null 2>&1 ; barnyard2 -D -c /etc/snort/barnyard2eth1.conf -d /var/log/snort/eth1 -w /var/log/snort/eth1/barnyard2.waldo -l /var/log/snort/eth1 -a /var/log/snort/eth1/archive -f snort.log --pid-path /var/run
root      3197 61.4  0.2  58856  7808 ?        R    11:18   1:01 barnyard2 -D -c /etc/snort/barnyard2eth1.conf -d /var/log/snort/eth1 -w /var/log/snort/eth1/barnyard2.waldo -l /var/log/snort/eth1 -a /var/log/snort/eth1/archive -f snort.log --pid-path /var/run
root      3710  0.0  0.0 103268   864 pts/2    S+   11:20   0:00 grep barn

E’ tutto. Alla prossima.

MRTG e Nagios: monitoraggio del throughput di rete

MRTG (Multi Router Traffic Grapher) rappresenta lo standard “de facto” per ciò che concerne il monitoraggio del throughput della nostra rete. Il suo funzionamento è basato sul polling SNMP, grazie al quale vengono raccolte le informazioni sul traffico che coinvolge le schede di rete monitorate, per poi procedere con la creazione di un grafico “ad hoc”, contenente le predette informazioni.

mrtg_logo

Installazione e configurazione di MRTG

La macchina che svolge le operazioni di monitoraggio è una linux box con a bordo CentOS 6. Per installare MRTG è dunque sufficiente digitare il comando:

[root@linuxbox ~]# yum install mrtg

Inoltre, sarà necessario installare anche i pacchetti net-snmp e net-snmp-utils (per effettuare il polling SNMP vero e proprio):

[root@linuxbox ~]# yum install net-snmp net-snmp-utils

Ad installazione completata passiamo alla configurazione di MRTG. Per prima cosa sarà necessario lanciare il comando:

[root@linuxbox ~]# cfgmaker --global 'WorkDir: /var/www/mrtg' --output /etc/mrtg/mrtg.cfg keypublic@iptarget

Esso ci consentirà di popolare in maniera automatica il file di configurazione /etc/mrtg/mrtg.cfg, grazie al quale, successivamente, verrà creata la pagina Web (con estensione *.html) contenente i grafici generati da MRTG. Inoltre, all’interno del file di configurazione mrtg.cfg, sarà opportuno abilitare le seguenti opzioni:

Options[_]: growright, bits

le quali consentiranno la tracciatura dei grafici da sinistra verso destra, utilizzando i bit come unità di misura (anzichè i byte).

Per creare la pagina Web contenente i grafici è necessario digitare il comando:

[root@linuxbox ~]# indexmaker --output=/var/www/mrtg/index.html /etc/mrtg/mrtg.cfg

A questo punto facciamo in modo che i dati relativi al traffico vengano aggiornati ogni 5 minuti, creando un’apposita regola mediante cron (editando il file /etc/cron.d/mrtg):

*/5 * * * * root LANG=C LC_ALL=C /usr/bin/mrtg /etc/mrtg/mrtg.cfg --lock-file /var/lock/mrtg/mrtg_l --confcache-file /var/lib/mrtg/mrtg.ok

L’ultimo step relativo alla configurazione di MRTG riguarda il settaggio delle credenziali (username/password) per l’accesso alla pagina index.html. Per fare ciò occorre creare il file mrtg.conf, all’interno della directory /etc/httpd/conf.d di Apache (il nostro server Web), il cui contenuto dovrà essere simile al seguente:

Alias /mrtg /var/www/mrtg

<Location /mrtg>
    Order deny,allow
    Allow from all
    AuthName "MRTG Access"
    AuthType Basic
    AuthUserFile /etc/mrtg/passwd
    Require valid-user
</Location>

Ora definiamo lo username e la password (che verrà salvata nel file /etc/mrtg/passwd in formato digest), utilizzando il comando:

[root@linuxbox ~]# htpasswd -c /etc/mrtg/passwd mrtguser

Infine, ricarichiamo la configurazione Apache digitando:

[root@linuxbox ~]# service httpd reload

e proviamo ad accedere ai grafici generati da MRTG, puntando a questa URL:

http://iplinuxbox/mrtg

Se la pagina è accessibile ed i grafici sono aggiornati, possiamo passare alla configurazione di Nagios.

Integrazione tra Nagios ed MRTG

Il plugin di Nagios che ci consente di integrare tale NMS con MRTG prende il nome di check_mrtgtraf. Esso può essere installato singolarmente, digitando:

[root@linuxbox ~]# yum install nagios-plugins-mrtgtraf

oppure installando tutti i plugin di Nagios:

[root@linuxbox ~]# yum install nagios-plugins-all

Ad installazione completata, possiamo definire il comando check_local_mrtgtraf (all’interno del file /etc/nagios/object/commands.cfg), il quale si avvarrà del plugin appena installato:

# 'check_local_mrtgtraf' command definition
define command{
        command_name    check_local_mrtgtraf
        command_line    $USER1$/check_mrtgtraf -F $ARG1$ -a $ARG2$ -w $ARG3$ -c $ARG4$ -e $ARG5$
        }

dove -F indica il file di log (generato da MRTG) che dovrà essere consulato; -a indica la modalità di analisi del traffico (MAX o AVG); -w la soglia di warning e -c la soglia critica.

Non ci rimane che definire il servizio (relativo ad uno specifico host) che dovrà avvalersi del suddetto comando:

define service{
        use                             local-service   ; Inherit values from a template
        host_name                       Router-cisco
        service_description             WAN Bandwidth Usage
        check_command                   check_local_mrtgtraf!/var/www/mrtg/router-cisco/192.168.3.1_16.log!AVG!100000000,200000000!110000000,120000000!10
        }

Ricarichiamo la configurazione di Nagios mediante il comando:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

Nagios: script bash + expect per monitorare il numero di NAT translation sui router Cisco

Dopo aver cercato a lungo un OID SNMP che potesse restituirmi on-the-fly il numero di NAT translation attive sul mio router Cisco, sono arrivato alla conclusione che il modo più semplice per ricavare tale informazione consiste nel creare uno scrip bash + expect da dare in pasto a Nagios.

Nagios_logo_blackPer prima cosa, dunque, mi sono soffermato sulla creazione dello scrip expect, in modo da poter interrogare il router oggetto di monitoraggio, lanciando un comando specifico, che è il seguente:

Router# show ip nat statistics

Ed ecco lo scrip expect vero e proprio:

#!/usr/bin/expect

set ip [lindex $argv 0]
set password1 [lindex $argv 1]
set password2 [lindex $argv 2]

spawn ssh -l nightfly "$ip"
expect "*?assword:*"
send "$password1\r"
expect ">"
send "ena\r"
expect "Password:"
send "$password2\r"
expect "#"
send "show ip nat statistics\r"
expect "#"
send "exit\r"
expect eof

Esso riceve come parametri l’IP del dispositivo, la password vty e la password ena.
Dopo averlo chiamato get_nat_num (ed averlo reso eseguibile con chmod +x get_nat_num), mi sono soffermato sulla creazione dello scrip bash, che è il seguente:

#!/bin/bash

host=$1
password1=$2
password2=$3
warning=$4
critical=$5

usage="check_nat_translations <host> <password1> <password2> <warning> <critical>"

if [ -n "$host" ]; then

        if [ -n "$password1" ];then

                if [ -n "$password2" ];then

                        if [ -n "$warning" ];then

                                if [ -n "critical" ];then

                                        if [ "$critical" -lt "$warning" ];then

                                                echo "UNKNOWN: critical has to be greater than warning"
                                                exit 3;

                                        else

                                                output=`/usr/lib64/nagios/plugins/get_nat_num $1 $2 $3 | grep "Total active translations"  | awk '{print $4}'`

                                        fi

                                        if [ -n "$output" ];then

                                                if [ "$output" -ge "$critical" ];then

                                                        echo "CRITICAL: total number of active NAT translations is $output | nat_translations=$output;$warning;$critical";
                                                        exit 2;

                                                elif [ "$output" -lt "$critical"  -a  "$output" -ge "$warning" ];then

                                                        echo "WARNING: total number of active NAT translations is $output | nat_translations=$output;$warning;$critical";
                                                        exit 1;

                                                else

                                                        echo "OK: total number of active NAT translations is $output | nat_translations=$output;$warning;$critical";
                                                        exit 0;

                                                fi
                                        else

                                                echo "UNKNOWN: output is null"
                                                exit 3;

                                        fi

                                else

                                        echo "$usage"
                                        exit 3;
                                fi

                        else

                                echo "$usage"
                                exit 3;
                        fi

                else

                        echo "$usage"
                        exit 3;
                fi
        else

                echo "$usage"
                exit 3;
        fi

else

        echo "$usage"
        exit 3;

fi

Esso accetta in ingresso 5 parametri: i primi 3 da passare allo scrip get_nat_num, gli ultimi 2 da utilizzare come soglie per Nagios (una warning ed una critical).

Rendiamo eseguibile anche questo scrip (chmod +x check_nat_translations) e soffermiamoci sulla configurazione di Nagios.

Come primo step occorre creare il comando che utilizza i plugin appena creati:

# 'check_nat_translations' command definition
 define command{
 command_name    check_nat_translations
 command_line    $USER1$/check_nat_translations $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$ $ARG4$
 }

Successivamente è necessario creare un servizio (da inserire nel file di configurazione relativo ad un host determinato), che si avvalga del comando creato in precedenza:

define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_descripion             NAT Translations Number
 check_command                   check_nat_translations!password1!password2!40000!50000
 }

Salviamo la configurazione, riavviamo Nagios, ed il gioco è fatto.

Alla prossima.

Nagios e gli event handlers

Come già affermato in più occasioni, Nagios è sicuramente uno dei migliori NMS open source in circolazione.  Esso mette a disposizione del sysadmin tutta una serie di funzioni utilissime per verificare lo stato di salute relativo agli host monitorati e consente, in alcune circostanze, di gestire i downtime in modo automatico (ad esempio riavviando il servizio che ha generato lo status di tipo CRITICAL).

Nagios_logo_blackTale gestione automatica dei downtime viene realizzata attraverso i cosiddetti event handlers. Vediamo come configurarli.

Per prima cosa è necessario creare un comando simile al seguente, editando il file /etc/nagios/object/commands.cfg

define command {
command_name      flushcache
command_line      /usr/lib/nagios/plugins/eventhandlers/flushcache $HOSTADDRESS$ $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
}

Nella fattispecie, il suddetto comando utulizza l’eseguibile flushcache, il cui compito è quello connettersi alla macchina target e di cancellare la cache del sistema operativo in caso di memory leak.

Occorre ora configurare l’event handler all’interno del servizio che si occupa del monitoraggio della RAM:

define service{        
use                            local-service              host_name                       vostrohost.vostrodominio.it        service_description             FREE RAM        check_command                   check_remote_ram!10!5        event_handler                   flushcache        notifications_enabled           0        
}

A questo punto la configurazione di Nagios può ritenersi ultimata. Non ci rimane che creare l’eseguibile flushcache all’interno della directory /usr/lib/nagios/plugins/eventhandlers/:

[root@NMS eventhandlers]# nano flushcache

il cui contenuto dovrà essere il seguente:

#!/bin/bash
if [ -n "$1" ];then
        case "$2" in
        OK)
                ;;
        WARNING)
                ;;
        UNKNOWN)
                ;;
        CRITICAL)
                case "$3" in
                SOFT)
                        case "$4" in
                        3)
                                echo -n "Flushing cache memory (3rd soft critical state)..."
                                /usr/lib/nagios/plugins/eventhandlers/connect_server.sh $1
                                ;;
                                esac
                        ;;
                HARD)
                        echo -n "Flushing cache memory..."
                        /usr/lib/nagios/plugins/eventhandlers/connect_server.sh $1
                        ;;
                esac
                ;;
        esac
else
        echo "Usage: flushcache <hostname>"
fi

exit 0

Dove $1 è la variabile $HOSTADDRESS$, $2 è il $SERVICESTATE$, $3 è il $SERVICESTATETYPE$ e $4 è il $SERVICEATTEMPT$ (sono semplicemente le variabili utilizzate nella definizione del comando flushcache in command.cfg).

Premesso che per il tipo di servizio local-service il max_check_attempts è impostato a 4 (nel file template.cfg), il suddetto codice bash non fa altro che interrogare la macchina target ($HOSTADDRESS), ricavando il $SERVICESTATE$ (OK, WARNING, UNKNOWN o CRITICAL), il $SERVICESTATETYPE$ (SOFT oppure HARD) ed il $SERVICEATTEMPT$ (ovvero il numero di check già eseguiti da Nagios nel caso in cui il $SERVICESTATE$ sia diverso da OK).

Il suddetto eseguibile prevede delle operazioni solo se il $SERVICESTATE$ è di tipo CRITICAL: in tal caso, al terzo check consecutivo (siamo ancora in SOFT state – parliamo di HARD state solo se il $SERVICESTATE$ è ancora CRITICAL dopo il quarto check), verrà lanciato l’eseguibile connect_server.sh (expect) che si occuperà di svuotare la cache della macchina monitorata. La suddetta operazione verrà eseguita nuovamente appena il $SERVICESTATETYPE$ passerà da SOFT a HARD.

Inoltre, tale eseguibile prevede come unico parametro in ingresso l’IP dell’host, ovvero $HOSTADDRESS$ (connect_server.sh $1).

Di seguito il sorgente relativo a connect_server.sh:

#!/usr/bin/expect

set hostname [lindex $argv 0]
set password "vostrapass"

spawn ssh -l root $hostname
expect "*assword:"
send "$password\n"
expect "#"
send "sync && echo 3 > /proc/sys/vm/drop_caches\n"
expect "#"
send "exit\n"
expect eof

Nella fattispecie, il comando vero e proprio che si occupa dello svuotamento della cache sulla macchina target è:

sync && echo 3 > /proc/sys/vm/drop_caches

A questo punto possiamo ricaricare la configurazione di Nagios per rendere effettive le suddette modifiche:

[root@NMS eventhandlers]# service nagios reload

ed abbiamo finito.

A presto.