Vous êtes ici:

Menu

Centreon Signal 2

Stacks Image 1122
Ce nouveau Signal pour Centreon est une reproduction du logo Centreon. Celui-ci va être capable d'afficher l'activité des Hôtes et Services de manière séparée. Autre nouveauté, l'affichage BLEU pour l'état PENDING et BLANC pour l'état UNKNOW. D'autres améliorations sont dans les cartons.

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é.
Stacks Image 388
Principe de fonctionnement
Stacks Image 1097
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).
Vous trouverez ces articles sur le site de MC Hobby mais il en existe bien d'autres.

Montage du signal

Les instructions de montage du signal en Lego se trouvent ici.
Stacks Image 1094
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).
montage-signal2-01

montage-signal2-02

montage-signal2-03
Et voici le montage du circuit électrique dans le boîtier Lego
Stacks Image 1172
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.
Stacks Image 1175
Repositionner l'emplacement de la platine d'essai et l'insérer doucement.
Stacks Image 1178
Ouvrir délicatement la boîte comme indiqué sur la photo.
Stacks Image 1181
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.
Stacks Image 1184
Remettre les briques Lego et repositionner délicatement le tout sur la plaque de fond.
Stacks Image 1187
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.
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
Stacks Image 1215
Host : Critical, Service : Critical
Stacks Image 1218
Host : Critical, Service : Warning
Stacks Image 1221
Host : Critical, Service : OK
Stacks Image 1224
Host : OK, Service : Critical
Stacks Image 1227
Host : OK, Service : Warning
Stacks Image 1230
Host : OK, Service : Unknown
Stacks Image 1233
Host : OK, Service : Pending
Stacks Image 1246
Host : Pending, Service : OK
Stacks Image 1239
Host : OK, Service : OK
Prochain épisode, l'intégration d'une alarme sonore...
comments powered by Disqus
 Vous êtes ici: