Centreon Signal 2
Principe de fonctionnement
Pour cette nouvelle version, nous utiliserons le protocole UDP qui n'exige pas de contrôle de flux. Une trame est émise par un script lancé par un cron toutes les minutes. Le script effectuera une requête sur la base Centstatus ou Centstorage en fonction du type de broker défini par un paramètre.
Le script serveur UDP sera installé sur un ordinateur Raspberry. Grâce à la librairie GPIO, nous accèderons au module d'entrée/sortie logique pour commander des LED RGB. Dans ce premier montage, nous utiliserons des couleurs basiques : VERT, ROUGE, JAUNE, BLEU et BLANC.
La première LED affiche l'état des Hôtes et la deuxième l'état des Services, les services les plus critiques seront affichés en priorité.
Le script serveur UDP sera installé sur un ordinateur Raspberry. Grâce à la librairie GPIO, nous accèderons au module d'entrée/sortie logique pour commander des LED RGB. Dans ce premier montage, nous utiliserons des couleurs basiques : VERT, ROUGE, JAUNE, BLEU et BLANC.
La première LED affiche l'état des Hôtes et la deuxième l'état des Services, les services les plus critiques seront affichés en priorité.
Principe de fonctionnement
Schéma électrique réalisé avec Fritzing
Matériel requis
Pour la réalisation de ce montage, nous aurons besoin :
- de briques Lego que l'on peut acheter au détail sur le site Lego Pick A Brick,
- d'un ordinateur Raspberry,
- d'une platine d'essai (optionnelle) pour le montage électronique,
- de deux LED RGB de diamètre trois millimètres,
- d'une petite plaque de plastique pour fixer les LEDs,
- de six résistances de 330 ohms,
- des câbles nécessaires aux montages (les câbles de platine d'essai sont très bien).
Montage du signal
Les instructions de montage du signal en Lego se trouvent ici.
Schéma de cablage
L'image ci-contre représente le montage réel hors du coffret Lego. Les LEDs ont été fixés sur une plaque de Plexi. La plaque d'essai nous permet un montage plus souple et autorise les modifications qui seront apportées dans le futur.
L'utilisation d'adaptateur mâle/mâle permet la réutilisation de connecteur de lecteur CD/DVD.
On utilisera du matériel de récupération pour le montage des LEDs (plaque de plexi percée aux dimensions des LEDs, souplisseau pour protéger des courts-circuits et câble de récupération d'anciens ordinateurs).



Et voici le montage du circuit électrique dans le boîtier Lego
Positionnement du Raspberry, l'emplacement pour la platine d'essai étant enlevé. Avant de fermer le boîtier, penser à connecter le câble d'alimentation.
Repositionner l'emplacement de la platine d'essai et l'insérer doucement.
Ouvrir délicatement la boîte comme indiqué sur la photo.
C'est l'opération la plus délicate, il faut enlever les briques Lego par le bas et insérer la plaque de Plexi sans abimer les connexions au LEDs.
Remettre les briques Lego et repositionner délicatement le tout sur la plaque de fond.
Le montage est terminé, vous pouvez refermer la boîte.
Le progamme
Le programme python installé sur le serveur Centreon que l'on appellera sendcentreon.py
#!/usr/bin/env python
# -*- coding:Utf-8 -*-
#***********************************************************
#* sendcentreon.py *
#* envoie les informations au signal centreon *
#* version 1:00 date 08/01/2013 *
#***********************************************************
from optparse import OptionParser
# chargement des librairies
import MySQLdb
import sys
import socket
import time
# initialisation des variables
UDP_IP = '127.0.0.1'
UDP_PORT = 20000
HOST_MYSQL = 'localhost'
USER_MYSQL = 'centreon'
PWD_MYSQL = 'passwd'
# définitions des options
options = {}
options[('-b','--broker')] = {'dest':'broker',
'help':'nom du broker'}
options[('-i','--ip')] = {'dest':'ip',
'help':'adresse destination'}
# affichage des options
def main(options, arguments):
print('options %s' % options)
print('arguments %s' % arguments)
# récupérations des options
if __name__ == '__main__':
parser = OptionParser()
for param, option in options.items():
parser.add_option(*param, **option)
options, arguments = parser.parse_args()
if options.ip != "":
UDP_IP = options.ip
ADRESSE=(UDP_IP,UDP_PORT)
BUFFER_SIZE = 1024
MESSAGE="Host:unknown,Service:unknown"
#connection à la base de données
if options.broker == "broker":
conn = MySQLdb.connect(HOST_MYSQL,USER_MYSQL,PWD_MYSQL, 'centstorage')
elif options.broker == "ndo":
conn = MySQLdb.connect(HOST_MYSQL,USER_MYSQL,PWD_MYSQL, 'centstatus')
else:
print "broker inconnu !"
sys.exit(0)
curs = conn.cursor()
# vérification des hosts
if options.broker == "broker":
result=curs.execute("SELECT count(DISTINCT name), state FROM hosts WHERE name NOT LIKE '_Module_%' AND hosts.enabled = 1 group by state")
elif options.broker == "ndo":
result=curs.execute("SELECT count(DISTINCT nagios_objects.name1), nagios_hoststatus.current_state FROM nagios_hoststatus, nagios_objects WHERE nagios_objects.object_id = nagios_hoststatus.host_object_id AND nagios_objects.is_active = 1 AND nagios_objects.name1 NOT LIKE '_Module_%' GROUP BY nagios_hoststatus.current_state")
# récupération du nombre d'enregistrement
numrows = int(curs.rowcount)
# initialisation host alarme
host_alarme = 0
# lecture des enregistrements
for x in range(0, numrows):
result=curs.fetchone()
if result[1] == 1:
host_alarme = 1
break
if result[1] == 4:
host_alarme = 4
# affichage heure
print "envoi le :",time.strftime('%d/%m/%y à %H:%M',time.localtime())
# résultat host
if host_alarme == 1:
print "host down"
elif host_alarme == 4:
print "host pending"
else:
print "Host OK"
# vérification des services
if options.broker == "broker":
result = curs.execute("SELECT COUNT(DISTINCT CONCAT(s.service_id,';', s.host_id)) as number, s.state_type, s.acknowledged, s.scheduled_downtime_depth, s.state FROM services s, `hosts` h WHERE s.host_id IS NOT NULL AND s.host_id = h.host_id AND s.scheduled_downtime_depth = '0' AND s.acknowledged = '0' AND s.state <> '0' AND h.state = '0' AND s.enabled = 1 AND h.enabled = 1 GROUP BY s.state, s.acknowledged, s.scheduled_downtime_depth")
elif options.broker == "ndo":
result = curs.execute("SELECT COUNT(DISTINCT CONCAT(no.name1,';', no.name2)) as number, nss.state_type, nss.problem_has_been_acknowledged, nss.scheduled_downtime_depth, nss.current_state FROM nagios_servicestatus nss, nagios_objects no, nagios_hoststatus nhs, nagios_services ns WHERE no.object_id = nss.service_object_id AND no.name1 NOT LIKE '_Module_%' AND no.is_active = 1 AND nss.scheduled_downtime_depth = '0' AND nss.problem_has_been_acknowledged = '0' AND nss.current_state != '0' AND no.object_id = ns.service_object_id AND ns.host_object_id = nhs.host_object_id AND nhs.current_state = '0' GROUP BY nss.current_state, nss.problem_has_been_acknowledged, nss.scheduled_downtime_depth")
# récupération du nombre d'enregistrement
numrows = int(curs.rowcount)
# inialisation service alarme
service_alarme = 0
# lecture des enregistrement
for x in range(0, numrows):
result=curs.fetchone()
if result[4] == 2:
# Critical
service_alarme = 2
break
if result[4] ==1 and service_alarme==0:
# Warning
service_alarme = 1
if result[4] == 3 and service_alarme==0:
# Unknow
service_alarme = 3
if result[4] == 4 and service_alarme==0:
# Pending
service_alarme = 4
# resultat service
if service_alarme == 0:
print "Services OK"
elif service_alarme == 1:
print "Services Warning"
elif service_alarme == 2:
print "Services Critical"
elif service_alarme == 3:
print "Services Unknow"
else:
print "Services Pending"
curs.close()
conn.close()
# préparation du message et envoi au signal
MESSAGE = "Host:"+str(host_alarme)+", Service:" +str(service_alarme)
print MESSAGE
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(MESSAGE,ADRESSE)
s.close()
et le programme installé sur le raspberry que l'on nommera server_udp.py
#!/usr/bin/env python
# -*- coding:Utf-8 -*-
# Serveur UDP utilisant le module socket
# import nécessaire au fonctionnement du serveur
import socket
import time
import RPi.GPIO as GPIO
import os
# imports seulement nécessaires à l'exemple (=calcul d'expression par eval())
import sys
from math import *
# initialisation des ports
GPIO.setup(11, GPIO.OUT)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.output(11, True)
GPIO.output(12, True)
GPIO.output(13, True)
GPIO.output(15, True)
GPIO.output(16, True)
GPIO.output(18, True)
buf=1024
adresse=('',20000)
socketserveur=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socketserveur.bind(adresse)
print "serveur actif"
# boucle de service du serveur
while True:
# attente d'une nouvelle connexion
# et enregistrement de la requete et de l'adresse du demandeur
requete, adresseclient = socketserveur.recvfrom(buf)
if not requete:
break
data=requete.strip()
# Affichage des informations reçues
print "received data:", data
# traitement des information
if data[5] == "1":
print "affichage host down led rouge"
# réglage led
GPIO.output(11, True)
GPIO.output(12, True)
GPIO.output(13, False)
elif data[5] == "4":
print "affichage host pending led bleu"
# réglage led
GPIO.output(12, True)
GPIO.output(13, True)
GPIO.output(11, False)
elif data[5] == "0":
print "affichage host ok led verte"
# réglage led
GPIO.output(11, True)
GPIO.output(13, True)
GPIO.output(12, False)
if data[16] == "1":
print "affichage service warning led jaune"
# réglage led
GPIO.output(15, True)
GPIO.output(16, False)
GPIO.output(18, False)
elif data[16] == "2":
# réglage led
GPIO.output(15, True)
GPIO.output(16, True)
GPIO.output(18, False)
print "affichage service critical pending led rouge"
elif data[16] == "3":
# réglage led
GPIO.output(15, False)
GPIO.output(16, False)
GPIO.output(18, False)
print "affichage service Unknown pending led blanche"
elif data[16] == "4":
# réglage led
GPIO.output(15, False)
GPIO.output(16, True)
GPIO.output(18, True)
print "affichage service pending pending led bleu"
elif data[16] == "0":
GPIO.output(15, True)
GPIO.output(16, False)
GPIO.output(18, True)
print "affichage service ok led verte"
socketserveur.close()Configuration des systèmes
Pour le serveur Centreon, vous aurez besoin de Python (normalement déjà installé) et de la librairie Mysql pour Python.
Copiez le script sendcentreon.py dans le dossier de votre choix, par exemple pour un utilisateur appelé vmdebian
Ajoutons une tâche cron exécutant le script toutes les minutes.
ajoutons la ligne suivante pour un broker ndo
pour un broker centreon-broker
Le premier paramètre i permet de renseigner l'adresse IP du signal Centreon et le deuxième le type de broker (ndo pour NDOutils, broker pour Centreon-Broker). La redirection des messages de sortie n'est pas indispensable, mais fortement conseillée pour d'éventuels débogages.
Pour le Signal, nous utiliserons une version debian pour Raspberry avec l'installation de la bibliothèque GPIO pour Python. Installez le script server_udp.py dans le dossier utilisateur pi. Lancez le serveur avec la commande ci-dessous.
Au bout d'environ une minute, les LEDs s'afficheront ainsi que les lignes suivantes sur le terminal
apt-get install python-mysqldb
Copiez le script sendcentreon.py dans le dossier de votre choix, par exemple pour un utilisateur appelé vmdebian
cp sendcentreon.py /home/vmdebian
chown vmdebian:vmdebian /home/vmdebian/sendcentreon.py
chmod +x /home/vmdebian/sendcentreon.py
Ajoutons une tâche cron exécutant le script toutes les minutes.
crontab -e
ajoutons la ligne suivante pour un broker ndo
* * * * * /home/vmdebian/sendcentreon.py -i [Adresse IP du signal] -b ndo >> /home/vmdebian/sendcentreon.log
pour un broker centreon-broker
* * * * * /home/vmdebian/sendcentreon.py -i [Adresse IP du signal] -b broker >> /home/vmdebian/sendcentreon.log
Le premier paramètre i permet de renseigner l'adresse IP du signal Centreon et le deuxième le type de broker (ndo pour NDOutils, broker pour Centreon-Broker). La redirection des messages de sortie n'est pas indispensable, mais fortement conseillée pour d'éventuels débogages.
Pour le Signal, nous utiliserons une version debian pour Raspberry avec l'installation de la bibliothèque GPIO pour Python. Installez le script server_udp.py dans le dossier utilisateur pi. Lancez le serveur avec la commande ci-dessous.
pi@raspberrypi:~$ sudo python server_udp.py
serveur actif
Au bout d'environ une minute, les LEDs s'afficheront ainsi que les lignes suivantes sur le terminal
serveur actif
received data: Host:1, Service:0
affichage host down led rouge
affichage service ok led verte
Fonctionnement
Voici quelques exemples du fonctionnement de Centreon Signal 2
Host : Critical, Service : Critical
Host : Critical, Service : Warning
Host : Critical, Service : OK
Host : OK, Service : Critical
Host : OK, Service : Warning
Host : OK, Service : Unknown
Host : OK, Service : Pending
Host : Pending, Service : OK
Host : OK, Service : OK
Prochain épisode, l'intégration d'une alarme sonore...
