nagios

Introduction

Nagios, l’outil libre de monitoring réseau va bientôt passer en version 3.0. Nous allons donc dans cet article décrire l’installation de cette nouvelle monture sous un OS Linux Debian url http://nagios-fr.org/forums/

Pre-requis

Nous avons d’abord besoin d’installer un serveur web (si ce n’est pas déjà fait) et les librairies de bases nécessaires pour la compilation de Nagios. Pour cela, il faut utiliser les commandes suivantes:

apt-get install apache2
apt-get install build-essential

Si vous voulez utiliser l’option de visualisation graphique de votre réseau (”status map”), il faut également installer les librairie suivantes.

apt-get install libgd2-noxpm-dev libpng12-dev libjpeg62 libjpeg62-dev

Il faut également créer un utilisateur et un groupe dédié au processus Nagios (pour d’évidente raison de sécurité).

/usr/sbin/useradd nagios
passwd nagios
/usr/sbin/groupadd nagios
/usr/sbin/usermod -G nagios nagios
/usr/sbin/groupadd nagcmd
/usr/sbin/usermod -G nagcmd nagios
/usr/sbin/usermod -G nagcmd www-data

Installation de Nagios à partir des sources

cd /usr/src
wget  http://surfnet.dl.sourceforge.net/sourceforge/nagios/nagios-3.0.2.tar.gz
wget  http://kent.dl.sourceforge.net/sourceforge/nagiosplug/nagios-plugins-1.4.12.tar.gz
tar xzf nagios-3.0.2.tar.gz
cd nagios-3.0.2
./configure --with-command-group=nagcmd
make all
make install
make install-init
make install-config
make install-commandmode
ln -s /etc/init.d/nagios /etc/rcS.d/S99nagios

Il faut ensuite installer l’interface Web:

make install-webconf
sudo htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin
/etc/init.d/apache2 reload

Puis finir par la compilation des plugins de base.

cd ..
tar xzf nagios-plugins-1.4.12.tar.gz
cd nagios-plugins-1.4.12
./configure --with-nagios-user=nagios –-with-nagios-group=nagios
make
make install

Paramétrage

Vous pouvez consulter le lien http://nagios.sourceforge.net/docs/3_0/config.html Pour vérifier que la configration de Nagios est bonne (qu’il n’y a pas d’erreur dans les fichiers de configuration), vous pouvez utiliser l’option “-v” de la commande nagios:

/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg

Les fichiers de paramétrages sont dans /usr/local/nagios/etc et /usr/local/nagios/etc/objects.

Un tableau récapitulatif des fichiers de conf

Fichier Fonction
nagios.cfg cgi.cfg ressources.cfg objects/commands.cfg objects/templates.cfg objects/contacts.cfg objects/windows.cfg objects/printers.cfg objects/localhost.cfg configuration général du serveur Nagios configuration de l’appli web de Nagios ajout d‘“alias” pour Nagios configuration des commandes nagios pour les tests (check_ping, check_ssh, check_http, ...) configuration de base réutilisées pour nos futur serveur configuration des commandes par défaults, des intervals de check, ... liste des contacts pour les notifications exemple de fichier de configuration pour un serveur windows exemple de fichier de configuration pour imprimante fichier de configuration pour controle de la machine locale

Lancement de Nagios

Pour lancer Nagios, vous pouvez utiliser les commandes:

/etc/init.d/nagios start

Utilisation de Nagios

L’accès à l’interface Web de Nagios se fait par l’URL suivante: http://localhost/nagios/ . Ajout du contrôle d’un serveur Linux

Nous allons créer la configuration pour contrôler un nouveau serveur RHSE02. Cela va nécessiter:

  • modification du fichier nagios.cfg
  • création d’un fichier objects/RHSE02.cfg
  • arrêt/redémarrage de nagios

Note

nous n’allons utiliser que des commandes qui existent déjà dans le fichier objects/commands.cfg

Dans le fichier nagios.cfg il faut ajouter:

cfg_file=/usr/local/nagios/etc/objects/RHSE02.cfg

puis pour créer le fichier objects/RHSE02.cfg (à partir du fichier objects/localhost.cfg)

###############################################################################
# RHSE02.CFG
###############################################################################

###############################################################################
###############################################################################
#
# HOST DEFINITION
#
###############################################################################
###############################################################################

# Define a host for the local machine

define host{
        use                     linux-server
        host_name               RHSE02
        alias                   RHSE02
        address                 172.16.10.21
        notes_url               http://172.16.10.21:2431/
        }


###############################################################################
###############################################################################
#
# SERVICE DEFINITIONS
#
###############################################################################
###############################################################################


# Define a service to "ping" the local machine

define service{
        use                             local-service
        host_name                       RHSE02
        service_description             PING
        check_command                   check_ping!100.0,20%!500.0,60%
        }

define service{
        use                             local-service
        host_name                       RHSE02
        service_description             Root Partition
        check_command                   check_local_disk!20%!10%!/
        }

define service{
        use                             local-service
        host_name                       RHSE02
        service_description             SSH
        check_command                   check_ssh
        notifications_enabled           0
        }

define service{
        use                             local-service
        host_name                       RHSE02
        service_description             HTTP
        check_command                   check_http
        notifications_enabled           0
        }

Note

on peut rajouter dans la définition d’un host le paramètre notes_url qui va permettre de trouver sur l’interface web un lien vers un site (utile pour les machines ayant un site de contrôle de performance)

Il suffit par la suite de contrôler la configuration

/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg

Puis de redémarrer le service nagios

/etc/init.d/nagios restart

Cette configuration permet de contrôler sur le serveur RHSE02:

  • ping
  • root partition (warning si < 20 % critical si < 10 %)
  • ssh
  • http

Ajout du contrôle d’un serveur Windows

Nous allons créer la configuration pour contrôler un nouveau serveur aoustin. Cela va nécessiter:

  • modification du fichier nagios.cfg
  • installation de NSClient++ sur le serveur aoustin
  • création d’un fichier objects/aoustin.cfg
  • arrêt/redémarrage de nagios

Note

nous n’allons utiliser que des commandes qui existent déjà dans le fichier objects/commands.cfg

Dans le fichier nagios.cfg il faut ajouter:

cfg_file=/usr/local/nagios/etc/objects/aoustin.cfg

puis pour créer le fichier objects/aoustin.cfg (à partir du fichier objects/localhost.cfg)

###############################################################################
# AOUSTIN.CFG - SAMPLE CONFIG FILE FOR MONITORING A WINDOWS MACHINE
###############################################################################

###############################################################################
###############################################################################
#
# HOST DEFINITIONS
#
###############################################################################
###############################################################################

define host{
    use             windows-server
    host_name       aoustin
    alias           aoustin
    address         177.0.208.206
    }

###############################################################################
###############################################################################
#
# SERVICE DEFINITIONS
#
###############################################################################
###############################################################################

define service{
    use                     generic-service
    host_name               aoustin
    service_description     NSClient++ Version
    check_command           check_nt!CLIENTVERSION
    }

define service{
    use                     generic-service
    host_name               aoustin
    service_description     CPU Load
    check_command           check_nt!CPULOAD!-l 5,80,90
    }

 define service{
    use                     generic-service
    host_name               aoustin
    service_description     Memory Usage
    check_command           check_nt!MEMUSE!-w 80 -c 90
    }

define service{
    use                     generic-service
    host_name               aoustin
    service_description     C:\Drive Space
    check_command           check_nt!USEDDISKSPACE!-l c -w 80 -c 90
    }

define service{
        use                             local-service
        host_name                       aoustin
        service_description             HTTP
        check_command                   check_http
        notifications_enabled           0
        }

Cette configuration permet de contrôler sur le serveur RHSE02:

  • ping
  • CPU
  • Mémoire
  • utilisation disque C:
  • http

Warning

Par défaut vous allez trouver C:Drive Space alors qu’il faut C:Drive Space cela est important si vous utilisez pnp pour les graphiques En général banissez les espaces

Côté serveur aoustin il faut installer le client NSClient++ et modifier le fichier NSC.ini (tout le fichier est commenté)

[modules]
FileLogger.dll
CheckSystem.dll
CheckDisk.dll
NSClientListener.dll
NRPEListener.dll
SysTray.dll
CheckEventLog.dll
CheckHelpers.dll
CheckWMI.dll
NSCAAgent.dll
LUAScript.dll
CheckExternalScripts.dll
NRPEClient.dll
CheckTaskSched.dll

[Settings]
allowed_hosts=127.0.0.1/32,10.10.31.184
use_file=1
[log]
debug=1
file=nsclient.log
date_mask=%Y-%m-%d %H:%M:%S

[NSClient]
allowed_hosts=10.10.31.184
port=12489
bind_to_address=
socket_timeout=30

[NRPE]
port=5666
allowed_hosts=10.10.31.184

[Check System]

[External Script]

[External Scripts]

[External Alias]

[NSCA Agent]

[NSCA Commands]

[NRPE Handlers]

[NRPE Client Handlers]
check_other=-H 192.168.0.1 -p 5666 -c remote_command -a arguments

Note

le serveur aoustin à pour adresse 177.0.208.206 et le serveur nagios 10.10.31.184

Il suffit par la suite de contrôler la configuration

/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg

Puis de redémarrer le service nagios

/etc/init.d/nagios restart

Utilisation NRPE

Le NRPE est le NSClient++ pour les serveurs linux sur le serveur nagios il faut installer un serveur nrpe

apt-get install libssl-dev
apt-get install openbsd-inetd
cd /tmp
wget http://surfnet.dl.sourceforge.net/sourceforge/nagios/nrpe-2.12.tar.gz
tar -xvf nrpe-2.12.tar.gz
cd nrpe-2.12
./configure
make all
make install
cp sample-config/nrpe.cfg /usr/local/nagios/etc
cp src/nrpe /usr/local/sbin
chown -R  nagios:nagios /usr/local/nagios/etc/nrpe.cfg

puis dans le fichier /etc/service ajouter

nrpe        5666/tcp        #NRPE

puis dans le fichier /etc/inetd.conf ajouter

nrpe stream tcp nowait nagios /usr/sbin/tcpd /usr/local/sbin/nrpe -c /usr/local/nagios/etc/nrpe.cfg --inetd

puis redémarrage de inetd

/etc/init.d/openbsd-inetd restart

ajouter dans le fichier commands de nagios

define command{
  command_name check_nrpe
  command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$
}

ajouter les services dans les fichiers de configuration machine (ex localhost.cfg)

# Charge CPU
define service{
  use local-service
  host_name localhost
  service_description CPU Load
  check_command check_nrpe!check_load
}

# Memoire
define service{
  use local-service
  host_name localhost
  service_description Memory
  check_command check_nrpe!check_mem
}

pour le client debian

apt-get install nagios-nrpe-server
apt-get install nagios-plugins
apt-get install chkconfig

il faut modifier le fichier /etc/nagios/nrpe.cfg

allowed_hosts = Mettre ici l’adresse IP de votre serveur Nagios

il faut aussi ajouter une ligne par service qui sera controlé

command[check_users]=/usr/local/nagios/libexec/check_users -w 5 -c 10
command[check_load]=/usr/local/nagios/libexec/check_load -w 15,10,5 -c 30,25,20
command[check_disk1]=/usr/local/nagios/libexec/check_disk -w 10% -c 5% -p /dev/sda1
command[check_zombie_procs]=/usr/local/nagios/libexec/check_procs -w 5 -c 10 -s Z
command[check_total_procs]=/usr/local/nagios/libexec/check_procs -w 150 -c 200
command[check_mem]=/usr/local/nagios/libexec/check_ram -n -w 10 -c 5

On automatise le lancement du daemon au démarrage du serveur avec la commande:

chkconfig --add nrpe

puis on démarre le service

/etc/init.d/nagios-nrpe-server start

Note

pour tester le nrpe à partir du serveur ./check_nrpe -H Adresse_IP_du_serveur_Linux

Note

le check_ram (utilisé pour le check_mem) est un plugin disponible a cette adresse http://www.nagiosexchange.org/cgi-bin/page.cgi?g=Detailed%2F2450.html;d=1 attention, ce plugin n’est pas graphable par PNP

Installation Nuvola

Télécharger la dernière version du theme nuvola sur http://www.nagiosexchange.org/

cd /tmp
mkdir nagiostyle
cd nagiostyle
wget http://www.xoroz.com/files/nagiosstyle.zip
cp -R /usr/local/nagios/share /usr/local/nagios/share.org
unzip nagiosstyle.zip
cp -R /tmp/nagiostyle/* /usr/local/nagios/share

Installation de PNP

PNP est un module qui permet de générer des graphiques de performances. Nous avons quelques pre-requis à installer

apt-get install rrdtool librrdp-perl librrds-perl
apt-get install libapache2-mod-php5 php5-gd

puis passons à l’installation

cd /tmp
wget http://downloads.sourceforge.net/pnp4nagios/pnp-0.4.12.tar.gz
tar -xvf pnp-0.4.12.tar.gz
cd pnp-0.4.12
./configure
make all
make install
make install-config

Passons maintenant à la configuration de nagios. Modifier le fichier nagios.cfg pour ajouter:

process_performance_data=1
service_perfdata_file=/usr/local/nagios/var/service-perfdata
service_perfdata_file_template=DATATYPE::SERVICEPERFdata/tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$
  \tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::
  $SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::
  $SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
service_perfdata_file_mode=a
service_perfdata_file_processing_interval=15
service_perfdata_file_processing_command=process-service-perfdata-file

host_perfdata_command=process-host-perfdata
host_perfdata_file=/usr/local/nagios/var/hostperfdata
host_perfdata_file_template=DATATYPE::HOSTPERFdata/tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\t
   HOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\t
   HOSTSTATETYPE::$HOSTSTATETYPE$
host_perfdata_file_mode=a
host_perfdata_file_processing_interval=15
host_perfdata_file_processing_command=process-host-perfdata-file

Modifier le fichier objects/command.cfg pour ajouter:

define command{
    command_name    process-service-perfdata-file
    command_line    $USER1$/process_perfdata.pl --bulk=/usr/local/nagios/var/service-perfdata
 }
 define command{
    command_name process-host-perfdata-file
    command_line $USER1$/process_perfdata.pl –bulk=/usr/local/nagios/var/host-perfdata
 }

Pour intégrer un lien dans l’interface web il faut modifier les templates. Sous Nagios 3, c’est dans le fichier template.cfg qu’il faut faire les ajouts:

define host {
    name nomdutemplatehost
    …
    action_url /nagios/pnp/index.php?host=$HOSTNAME$
}

define host {
    name nomdutemplateservice
    …
    action_url /nagios/pnp/index.php?host=$HOSTNAME$&srv=$SERVICEDESC$
}

Et voila le résultat

_images/20100811_60.png

Il est possible de tester les services directement en ligne de commande.

/usr/local/nagios/libexec/check_nt -H 192.168.1.6 -v USEDDISKSPACE -p 12489 -l c -w 80 -c 90 -s fxckappa

Note

dans ce dernier exemple le -s permet de préciser un mot de passe

Il est aussi possible de surveiller avec ncclient des counters windows.

Cela permet par exemple pour un serveur TSE d’obtenir:

  • le nombre de session active
  • le nombre de session inactive
  • le nombre de session total

pour cela j’ai ajouter dans le cfg du serveur les services suivant

define service{
    use                     generic-service
    host_name               SRVPZTS5
    service_description     Service Remote Procedure Call
    check_command           check_nt!SERVICESTATE!-l RpcSs
    }

define service{
    use                     generic-service
    host_name               SRVPZTS5
    service_description     Service Terminal Services
    check_command           check_nt!SERVICESTATE!-l TermService
    }
define service {
  use                   generic-service
  host_name             SRVPZTS5
  service_description   check_nt_term_serv_total
  check_command         check_nt!COUNTER!-l "\\Services Terminal Server\\Nb total de sessions","Total","u"  -w 14 -c 16
  }

define service {
  use                   generic-service
  host_name             SRVPZTS5
  service_description   check_nt_term_serv_actif
  check_command         check_nt!COUNTER!-l "\\Services Terminal Server\\Active Sessions","Total","u"  -w 14 -c 16
  }

define service {
  use                   generic-service
  host_name             SRVPZTS5
  service_description   check_nt_term_serv_inactive
  check_command         check_nt!COUNTER!-l "\\Services Terminal Server\\Nb de sessions inactives","Total","u"  -w 14 -c 16
  }

Note

cela comprend aussi des services de surveillance de service windows

pour tester cela en manuel il faut faire

cd /usr/local/nagios/libexec
./check_nt -H myservts2 -p 12489 -s mysociety -v COUNTER -l "\Services Terminal Server\Active Sessions" -w 14 -c 16

Pour obtenir la liste des compteurs on peut simplement aller voir dans le journaux de performance de windows et ajouter des compteurs (ce qui donne le nom complet)

_images/20120321_01.png

Notification

Nagios peut lors de changement d’état utiliser un service de notification pour signaler ce dernier. Par défault il utilise la fonction mail, mais il est possible de changer ce comportement. Je vous propose de paramétrer Nagios pour qu’il notifie les changements d’états par l’envoie d’un email via le compte fraoustin@gmail.com Pour cela nous allons créer un programme python sendmsg.py qui utilise la librairie libgmail librement téléchargeable http://libgmail.sourceforge.net/ code du programme sendmsg

#!/usr/bin/env python

import os
import sys
import logging
import libgmail
import syslog


USER = "fraoustin@gmail.com"
PASSWORD= "04081978"

if __name__ == "__main__":
    import sys
    from getpass import getpass
    try:
        to = sys.argv[1]
        subject = sys.argv[2]
        msg = ''
        for i in sys.argv[3:]:
            msg = msg + i + '\n'
    except IndexError:
    syslog.syslog('[%s][ERROR]Usage: %s <to address> <subject> <txt>' % (sys.argv[0],sys.argv[0]))
    for i in sys.argv[:]:
        syslog.syslog('[%s][ERROR]: %s ' % (sys.argv[0],i))

        print "Usage: %s <to address> <subject> <txt>" % sys.argv[0]
        raise SystemExit


    ga = libgmail.GmailAccount(USER, PASSWORD)

    try:
        ga.login()
    except libgmail.GmailLoginFailure:
    syslog.syslog('[%s][ERROR] Login failed. (Wrong username/password?)' % (sys.argv[0],sys.argv[0]))
    syslog.syslog('[%s][ERROR][TO]: %s ' % to)
    syslog.syslog('[%s][ERROR][SUBJECT]: %s ' % subject)
    syslog.syslog('[%s][ERROR][MSG]: %s ' % msg)
    else:
        gmsg = libgmail.GmailComposedMessage(to, subject, msg)
        if ga.sendMessage(gmsg):
            syslog.syslog('[%s][INFO]message send for %s subject %s' % (sys.argv[0],to,subject))
        else:
        syslog.syslog('[%s][ERROR] Couldn\'t message' % sys.argv[0])
        syslog.syslog('[%s][ERROR][TO]: %s ' % (sys.argv[0],to))
        syslog.syslog('[%s][ERROR][SUBJECT]: %s ' % (sys.argv[0],subject))
        syslog.syslog('[%s][ERROR][MSG]: %s ' % (sys.argv[0],msg))

Il faut maintenant modifier nagios pour qu’il utilise ce programme.

Tout d’abord nous allons lui indiquer l’adresse mail a utiliser. Pour cela modifier le fichier /usr/local/nagios/etc/object/contacts.cfg pour obtenir la ligne suivante

define contact{
    contact_name    nagiosadmin
    use             generic-contact
    alias           Nagios Admin
    email           frederic.aoustin@socopa.fr
    }

Maintenant les commandes permettant la notification, via le fichier /usr/local/nagios/etc/object/commands.cfg

    define command{
    command_name    notify-host-by-email
    command_line    python /home/fraoustin/Desktop/sendmsg.py $CONTACTEMAIL$
       "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" "***** Nagios *****"
       "Notification Type: $NOTIFICATIONTYPE$" "Host: $HOSTNAME$\nState: $HOSTSTATE$"
       "Address: $HOSTADDRESS$" "Info: $HOSTOUTPUT$" "Date/Time: $LONGDATETIME$"
    }

# 'notify-service-by-email' command definition
define command{
    command_name    notify-service-by-email
    command_line    python /home/fraoustin/Desktop/sendmsg.py $CONTACTEMAIL$
        "** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **"
        "***** Nagios *****" "Notification Type: $NOTIFICATIONTYPE$" "Service: $SERVICEDESC$"
        "Host: $HOSTALIAS$\nAddress: $HOSTADDRESS$" "State: $SERVICESTATE$"
        "Date/Time: $LONGDATETIME$" "Additional Info:" "$SERVICEOUTPUT$"
    }

même chose sans la librairie gmail et evec possibilité d’authentification sur le serveur smtp

#!/usr/bin/env python
import os
import sys
import logging
import syslog
import smtplib
from email.MIMEText import MIMEText
server_smtp = 'srvxxxx1'
sender = 'informatiquepz@myprop-group.com'
user = 'informatiquepz'
password = 'informatique'

def send(mfrom,mto, title, msg):
    email = MIMEText(msg)
    email['From']=mfrom
    email['To']=mto
    email['Subject']=title
    server = smtplib.SMTP(server_smtp)
    if user != '':
        server.login(user, password)
    server.sendmail(mfrom,
            mto,
            email.as_string())
    server.quit()

if __name__ == "__main__":
    import sys
    from getpass import getpass
    try:
        to = sys.argv[1]
        subject = sys.argv[2]
        msg = ''
        for i in sys.argv[3:]:
            msg = msg + i + '\n'
    except IndexError:
        syslog.syslog('[%s][ERROR]Usage: %s <to address> <subject> <txt>' % (sys.argv[0],sys.argv[0]))
        for i in sys.argv[:]:
            syslog.syslog('[%s][ERROR]: %s ' % (sys.argv[0],i))
        print "Usage: %s <to address> <subject> <txt>" % sys.argv[0]
        raise SystemExit
    try:
        send(sender ,to, subject, msg)
    except :
        syslog.syslog('[%s][ERROR] Login failed. (Wrong username/password?)' % (sys.argv[0],sys.argv[0]))
        syslog.syslog('[%s][ERROR][TO]: %s ' % to)
        syslog.syslog('[%s][ERROR][SUBJECT]: %s ' % subject)
        syslog.syslog('[%s][ERROR][MSG]: %s ' % msg)

Et voila ....

Pour activer ou déactiver la notification vous pouvez utiliser l’interface web mais aussi le paramètre

notifications_enabled           0

des définitions de service Il suffit par la suite de contrôler la configuration

/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg

Puis de redémarrer le service nagios

/etc/init.d/nagios restart

Note

pour gérer les périodes de notification il faut regarder du côté du fichier timeperiod.cfg et ajouter pour chaque host et service (ou au niveau des templates ...) au niveau de sa définition un element du type notification_period workhours

création de compte utilisateur

htpasswd /usr/local/nagios/etc/htpasswd.users <username>

puis modifier le fichier cgi.cfg et ajouterlà ou il y a nagiosadmin les utilisateurs sinon mettre * pour avoir tout les utilisateurs

Créer un plugin Nagios avec python

voici un exemple qui permet de récupérer des infos depuis une url.

ce plugin nécessite une url (avec un hostname, un user et un password en paramètre)

    #!/usr/bin/env python

from mechanize import Browser
from optparse import OptionParser

# Exit statuses recognized by Nagios
UNKNOWN = -1
OK = 0
WARNING = 1
CRITICAL = 2

def open_url(br, url):
    """Use a given mechanize.Browser to open url.

    If an exception is raised, then exit with CRITICAL status for Nagios.
    """
    try:
        response = br.open(url)
    except Exception, e:
        # Catching all exceptions is usually a bad idea.  We want to catch
        # them all to report to Nagios here.
        print 'CRITICAL - Could not reach page at %s: %s' % (url, e)
        raise SystemExit, CRITICAL
    return response

# I'm going to be using optparse.OptionParser from now on.  It makes
# command-line args a breeze.
parser = OptionParser()
parser.add_option('-H', '--hostname', dest='hostname')
parser.add_option('-u', '--username', dest='username')
parser.add_option('-p', '--password', dest='password')
parser.add_option('-r', '--report_url', dest='url',
    help="""Path to report relative to root, like
    /NetPerfMon/Report.asp?Report=Hostname+__+IPs""")
parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
    default=False)
parser.add_option('-q', '--quiet', dest='verbose', action='store_false')

options, args = parser.parse_args()

# Check for required options
for option in ('hostname', 'username', 'password', 'url'):
    if not getattr(options, option):
        print 'CRITICAL - %s not specified' % option.capitalize()
        raise SystemExit, CRITICAL

# Go to the report and get a login page
br = Browser()
report_url = 'https://%s%s' % (options.hostname, options.url)
open_url(br, report_url)
br.select_form('aspnetForm')

# Solarwinds has interesting field names
# Maybe something with asp.net
br['ctl00$ContentPlaceHolder1$Username'] = options.username
br['ctl00$ContentPlaceHolder1$Password'] = options.password

# Attempt to login.  If we can't, tell Nagios.
try:
    report = br.submit()
except Exception, e:
    print 'CRITICAL - Error logging in: e' % e
    raise SystemExit, CRITICAL

report_html = report.read()
# class=Property occurs in every cell in a Solarwinds report.  If it's not
# there, something is wrong.
if 'class=Property' not in report_html:
    print 'CRITICAL - Report at %s is down' % report_url
    raise SystemExit, CRITICAL

# If we got this far, let's tell Nagios the report is okay.
print 'OK - Report at %s is up' % report_url
raise SystemExit, OK

il faut définir la commande

define command{
    command_name    check_npm_reports
    command_line    /usr/local/bin/reportmonitor.py -H $HOSTADDRESS$ $ARG1$
}

il faut définir le service

define service{
    use         generic-service
    host_name           solarwinds-server
    service_description Solarwinds reports
    check_command       check_npm_reports!-u nagios -p some_password -r '/NetPerfMon/Report.asp?Report=Hostname+__+IPs'
}

un exemple ici

Note

la gestion du status est réalisée sur le type de retour “raise SystemExit,??” ou un “sys.exit(??)”

Note

pour pouvoir grapher le retour il faut que la sortie print soit du type: “txt| label=2unit;warning_level;critical_level;min_value;max_value” seul label, value et unit sont obligatoires ex: print “OK - speed of network on %.2f KB/s | ‘vitesse’=%.2f;1000;1000;0;1000” % (vit,vit)

intégrer des informations de nagios sur un autre site

cela n’est pas évident mais cela est possible

Nous avons:

  • un serveur nagios
  • un serveur web autre (ex redmine) sur une autre machine

sur la machine redmine nous allons créer un fichier python qui aura pour charge de récupérer des infos nagios et de les enregistrer en format html. Sur cette même machine nous allons modifier un fichier html pour intégrer le html généré par python.

nagios.py

import base64
import urllib, urllib2
import tempfile
import sys

#source of Nagstamon

username, password = 'nagiosadmin', 'nagiosadmin'
monitor_url = 'http://myservdeb01/nagios/'
monitor_cgi_url = '%s/cgi-bin' % monitor_url
file_out='nagiosinfo.html'


class Callable:
    def __init__(self, anycallable):
        self.__call__ = anycallable

class MultipartPostHandler(urllib2.BaseHandler):
    handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first

    def http_request(self, request):
        data = request.get_data()
        if data is not None and type(data) != str:
            v_vars = []
            try:
                for(key, value) in data.items():
                    v_vars.append((key, value))
            except TypeError:
                systype, value, traceback = sys.exc_info()
                raise TypeError, "not a valid non-string sequence or mapping object", traceback

            boundary, data = self.multipart_encode(v_vars)
            contenttype = 'multipart/form-data; boundary=%s' % boundary
            if(request.has_header('Content-Type')
               and request.get_header('Content-Type').find('multipart/form-data') != 0):
                print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
            request.add_unredirected_header('Content-Type', contenttype)

            request.add_data(data)
        return request

    def multipart_encode(vars, boundary = None, buffer = None):
        if boundary is None:
            boundary = mimetools.choose_boundary()
        if buffer is None:
            buffer = ''
        for(key, value) in vars:
            buffer += '--%s\r\n' % boundary
            buffer += 'Content-Disposition: form-data; name="%s"' % key
            buffer += '\r\n\r\n' + value + '\r\n'
        buffer += '--%s--\r\n\r\n' % boundary
        return boundary, buffer

    multipart_encode = Callable(multipart_encode)
    https_request = http_request


HTTPheaders = {}
for giveback in ["raw", "obj"]:
    HTTPheaders[giveback] = {"Authorization": "Basic " + base64.b64encode(username + ":" + password)}

host = ''
nagcgiurl_host  = monitor_cgi_url + "/extinfo.cgi?type=1&host=" + host
giveback = "obj"
cgi_data = None

hoststatustypes = 12
servicestatustypes = 253
hostserviceprops = 0
nagcgiurl_services = monitor_cgi_url + "/status.cgi?host=all&servicestatustypes=" + str(servicestatustypes) + "&serviceprops=" + str(hostserviceprops)
nagcgiurl_hosts = monitor_cgi_url + "/status.cgi?hostgroup=all&style=hostdetail&hoststatustypes=" + str(hoststatustypes) + "&hostprops=" + str(hostserviceprops)


# use server-owned attributes instead of redefining them with every request
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, monitor_url, username, password)
passman.add_password(None, monitor_cgi_url, username, password)
basic_handler = urllib2.HTTPBasicAuthHandler(passman)
digest_handler = urllib2.HTTPDigestAuthHandler(passman)
urlopener = urllib2.build_opener(digest_handler,
                                 basic_handler,
                                 MultipartPostHandler)


url = nagcgiurl_hosts

try:
    request = urllib2.Request(url, cgi_data, HTTPheaders[giveback])
    urlcontent = urlopener.open(request)
    txt = urlcontent.read()
    txts = txt.split('\n')
    k = {}
    k['HostUp'] = int(txts[43].split('>')[1].split('<')[0])
    k['HostDown'] = int(txts[44].split('>')[1].split('<')[0])
    k['HostUnreachable'] = int(txts[45].split('>')[1].split('<')[0])
    k['HostPending'] = int(txts[46].split('>')[1].split('<')[0])
    k['ServiceOk'] = int(txts[76].split('>')[1].split('<')[0])
    k['ServiceWarning'] = int(txts[77].split('>')[1].split('<')[0])
    k['ServiceUnknown'] = int(txts[78].split('>')[1].split('<')[0])
    k['ServiceCritical'] = int(txts[79].split('>')[1].split('<')[0])
    k['ServicePending'] = int(txts[80].split('>')[1].split('<')[0])
    lsth= ['HostUp','HostDown','HostUnreachable','HostPending']
    lsts= ['ServiceOk','ServiceWarning','ServiceUnknown','ServiceCritical','ServicePending']
    st = '<table border=0><tr><td><b><a href="%s">Nagios:</a></b></td><td>Host Status:</td>' % monitor_url
    for i in lsth:
        if k[i] > 0 and i == 'HostUp':
            st = st + '<td><element style="color: #088A29;">' + str(k[i]) +' ' + i[4:] + '</element></td>'
        if k[i] > 0 and i == 'HostDown':
            st = st + '<td><element style="color: #DF0101;">' + str(k[i]) +' ' + i[4:] + '</element></td>'
        if k[i] > 0 and i in ('HostUnreachable','HostPending'):
            st = st + '<td><element style="color: #FF8000;">' + str(k[i]) +' ' + i[4:] + '</element></td>'
    st = st + '</tr><tr><td></td><td>Service Status:</td>'
    for i in lsts:
        if k[i] > 0 and i == 'ServiceOk':
            st = st + '<td><element style="color: #088A29;">' + str(k[i]) +' ' + i[7:] + '</element></td>'
        if k[i] > 0 and i == 'ServiceCritical':
            st = st + '<td><element style="color: #DF0101;">' + str(k[i]) +' ' + i[7:] + '</element></td>'
        if k[i] > 0 and i in ('ServiceWarning','ServiceUnknown','ServicePending'):
            st = st + '<td><element style="color: #FF8000;">' + str(k[i]) +' ' + i[7:] + '</element></td>'
    st = st + '</tr></table>'
    a = open(file_out, 'w')
    a.write(st)
    a.close()


except urllib2.URLError, e:
    print 'Nous avons echoue a joindre le serveur.'
    print 'Raison: ', e.reason
except urllib2.HTTPError, e:
    print 'Le serveur n a pu satisfaire la demande.'
    print 'Code d\' erreur : ', e.code

nagios.py permet donc de générer le fichier nagiosinfo.html. il faut maintenant insérer cette page nagiosinfo.html dans une page html de votre site. le code html a insérer dans une page existante pour voir le fichier nagiosinfo.html est le suivant

<SCRIPT language="Javascript">
var http_request = false;

function inclure(url) {
 http_request = false;
 if(url && url!='') {
    if (window.XMLHttpRequest) { // Mozilla, Safari,...
          http_request = new XMLHttpRequest();
          if(http_request.overrideMimeType) {
                http_request.overrideMimeType('text/xml');
            }
      }
    else if (window.ActiveXObject) { // IE
          try {
                http_request = new ActiveXObject("Msxml2.XMLHTTP");
             }
          catch (e) {
                 try {
                    http_request = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                 catch (e) {}
             }
      }
    if (!http_request) {
          alert('Abandon :( Impossible de creer une instance XMLHTTP');
          secours(url);
          return false;
      }
    http_request.onreadystatechange = function() { alertContents(url) };
    http_request.open('GET', url, true);
    http_request.send(null);
    }
}

function alertContents(url) {
 if (http_request.readyState == 4) {
   if (http_request.status == 200) {
      document.getElementById('nagiosinfo').innerHTML = http_request.responseText;
      }
   else {
      alert('Un probleme est survenu avec la requete.');
      secours(url);
      }
   }
}

// pour les navigateurs ne digerant pas XHMHttpRequest
// ou si le serveur ne le permet pas
function secours(url) {
if(confirm('Faut-il que la page de secours soit ouverte?')) {
   var L = self.location.toString();
   location.href=L.substring(L.lastIndexOf('/'+1),L.lastIndexOf('?'))+'?'+url;
   }
}

// attribution de la fonction de requete a tous les liens du menu
function init() {
inclure('nagiosinfo.html'); return false; };

onload = init;
</SCRIPT>
<div id='nagiosinfo'></div>

Pour redmine on pourra intégrer ce code dans le fichier /usr/share/redmine/app/views/welcome/index.rhtml et faire en sorte que le fichier nagiosinfo.html soit placé sur /usr/share/redmine/public

Note

il faut régulièrement, via un crontab, lancer nagios.py

Note

pour certain plugin il faut installer plus de chose concernant PERL et notament YAML

apt-get install libyaml-perl

puis

perl -MCPAN -e 'shell'
cpan > install Nagios::Plugin
cpan > quit

Exemple de configuration et developpement Nagios

ici