jeudi 23 décembre 2010

Installation de shinken et configuration de l'interface Thruk

J'utilise beaucoup nagios pour mon travail de tous les jours mais c'est un outil qui n'est pas parfait (loin de là! ). J'ai donc lu avec beaucoup d'intérêt le démarrage du projet shinken qui a comme gros avantage d'être beaucoup plus performant et d'être beaucoup plus modulable que son ainé.

Voulant m'en faire une idée pour de vrai, j'ai donc procédé à une installation from scratch. Comme la documentation ne parle pas du tout de l'ajout de l'interface, je laisse donc ici quelques mots à ce sujet.

Installation de shinken



Tout d'abord créer un utilisateur shinken. Très important, il faut un home qui soit valide (sinon, l'arbitrer ne démarre pas !).

Reste ensuite à procéder à l'installation. Ici, rien de plus simple, il faut simplement récupérer le package shinken-0.4.tar.gz puis de le décompresser. Se rendre dans le répertoire shinken-0.4 puis lancer la commande suivante :

sudo python setup.py install --install-scripts=/usr/bin


De là, shinken va créer pas mal de répertoire (notamment /var/lib/shinken et /etc/shinken). Par convenance, j'ai créé un fichier shinken.sh qui me lance tous les éléments dans le bon ordre :


patrice@Enclume:~/tmp/shinken-0.4$ cat /etc/init.d/shinken.sh
#!/bin/bash

cd /etc/init.d

for script in shinken-scheduler shinken-poller shinken-reactionner shinken-broker shinken-arbiter
do
./$script $1
done


De là, il suffit de faire un /etc/init.d/shinken.sh start et c'est parti ! Pour vérifier que tout va bien, il faut s'assurer que les process suivants sont bien présents :


patrice@Enclume:~/tmp/shinken-0.4$ ps -u shinken
PID TTY TIME CMD
4358 ? 00:00:09 shinken-schedul
4367 ? 00:00:10 shinken-poller
4372 ? 00:00:00 shinken-poller
4380 ? 00:00:09 shinken-reactio
4385 ? 00:00:00 shinken-reactio
4949 ? 00:00:13 shinken-broker
4989 ? 00:00:00 shinken-poller
4990 ? 00:00:00 shinken-poller
4993 ? 00:00:00 shinken-poller
4996 ? 00:00:18 shinken-broker
4997 ? 00:00:00 shinken-broker
5001 ? 00:00:00 shinken-reactio
5004 ? 00:00:00 shinken-poller
5018 ? 00:00:10 shinken-arbiter


Configuration de l'interface Thruk



Ici, il faut récupérer l'interface Thruk à l'emplacement suivant. On la décompresse puis nous nous rendons dedans afin d'y créer un fichier thruk_local.conf. En voici le contenu :


~/tmp/Thruk-0.74$ cat thruk_local.conf
######################################
# Backend Configuration, enter your backends here
<component Thruk::Backend>
<peer>
name = Shinken
type = livestatus
hidden = 0 # make this backend hidden by default
groups = admins # make this backend only visible to the admin group
<options>
peer = 127.0.0.1:50000
verbose = 0
</options>
</peer>
</component>


De là, il ne nous reste plus qu'à lancer le démon Thruk :


~/tmp/Thruk-0.74/script$ ./thruk_server.pl
You can connect to your server at http://enclume:3000


NB : Attention, il s'agit d'un test. Il est possible de lancer l'interface Thruk en utilisant un serveur apache mais ce n'est pas l'objet de cet article.

De là, il ne nous reste plus qu'à accéder à l'interface http://localhost:3000 au travers un navigateur :



Bon, il va maintenant falloir que je configure correctement ma map :D Mais bon, ça c'est une autre histoire ;).

mercredi 6 octobre 2010

Import des données de ndoutils dans pnp4nagios

Il y a de ça 5 ou 6 mois, j'ai procédé à un refresh à notre infrastructure de suivi nagios. A l'époque nous utilisions un nagios couplé avec NDOUtils pour faire notre suivi de tendance des machines. J'avais par ailleurs créé un plugin permettant de grapher tout ceci en me basant sur la bibliothéque JPGraph.

Malheureusement, entre les problèmes sur la base de données, le fait que je sois sur Solaris (chouette encore un truc à compiler), les problèmes liés au broker nagios (pourquoi ce foutu machin ne veut pas se reconnecter à la base !!!), les problèmes de performance de la base (j'avais mis en place un système de rotation de la table nagios_servicechecks pour m'affranchir des problèmes de dégradation des performances avec le temps), la taille de tout ceci (200 Mo de place par jour pour 600 services !) et le plugin de graph à maintenir, j'ai fini par péter un cable !

Bref, à l'occasion d'un plan de refresh de ma machine, je suis tombé sur pnp4nagios et là, j'ai sérieusement réfléchi à me débarrasser de NDOUtils. En revanche, un point m'embêter : perdre mon historique de 100 jours de l'ancienne base MySQL. J'ai donc à ce moment pensé à utiliser les possibilités d'insertion en mode bulk de pnp4nagios afin de reconstituer mon historique.

Au démarrage, j'ai procédé par une extraction via un ensemble de scripts shells. J'ai ensuite procédé à un refactoring de ce script afin de le réécrire en perl que j'ai ensuite proposé à l'équipe de pnp4nagios. Ils m'ont simplement proposé de le déposer sur leur wiki à l'emplacement suivant.

Le script en question s'appelle ndo2pnp.pl et vous trouverez ci-dessous l'aide en ligne disponible sur l'outil :

$ ./ndo2pnp.pl --help
Usage :
-h --help Display this message.
--version Display version then exit.
-v --verbose Verbose run.
-u --user ndouser Log on to database with ndouser (default root).
-p --pass passwd Use passwd to logon (default gbu2kfe).
-t --type dbtype Change database type (default mysql).
--host dbhost Use dbhost (default localhost).
--dbname db Use db for ndo database name (default ndoutils).
--list-machine Display machine definition in ndo database.
--list-service Show services defined.
--export-as-pnp Export ndo content as a bulk file used by process_perfdata.pl.
>


Globalement, pour procéder à votre export/import, il faut suivre les étapes suivantes :
  • Extraction du contenu de la base : ./ndo2pnp.pl --user mysql_user -p mysql_pass --export-as-pnp > /tmp/perfdata.bulk

  • Import de l'extraction :/usr/share/pnp4nagios/libexec/process_perfdata.pl -b /tmp/perfdata.bulk --timeout 0

Quoi ? C'est tout ! Euh, juste une petite précision : l'import a duré 4 jours sur ma machine de production :). Un conseil : essayez de faire des extracts machine par machine (avec l'option --machines MAMACHINEAEXTRAIRE ou --services MESSERVICESAEXTRAIRE que j'ai oublié de documenté d'ailleurs ... Pas beau !). Les imports seront du coup moins long à faire (et éventuellement en parallèle) et peuvent vous donner une idée du résultat final sans avoir à vous coltiner l'intégralité de l'import de vos données.

Le résultat de tout ceci se trouve ci-dessous :


Toute la partie de décembre à février et le résultat de l'import (plus les quelques jours parasites d'octobre et novembre, date à laquelle nous avions eu des soucis avec la base MySQL). Vous remarquerez qu'entre temps, la base s'est alimentée avec de nouvelles valeurs.

dimanche 5 septembre 2010

Utilisation d'un robot avec Mediawiki

Il y a de ça quelques temps, j'ai eu l'occasion de travailler sur un robot de mise à jour automatique des populations sur les articles des communes de Charente-Maritime. Le principe est assez simple : les articles de commune utilisent tous un système de modèle afin de donner un aspect uniforme à tous les articles. Jetons un coup d'oeil au code source de l'article Wikipedia sur la ville de La Rochelle :


{{Infobox Communes de France
| nomcommune = La Rochelle
| image = La Rochelle Vieux-Port.JPG
| image-desc = Les tours du vieux-port de La Rochelle
[...]
| insee = 17300
| cp = 17000
| maire = [[Maxime Bono]]
[...]
| km² = 28.43
| sans = 76848
| date-sans = 2007
| aire-urbaine = 186271
| nomhab = Rochelaise, Rochelais
| siteweb = http://www.ville-larochelle.fr/
| géoloc-département = Charente-Maritime
}}


Comme vous pouvez le constater, l'article utilise un modèle Mediawiki (ici le modèle Infobox Communes de France) et utilise des paramètres nommés (aire-urbaine=186271 par exemple). L'idée de l'automate est donc de venir modifier les paramètres sans et date-sans (respectivement la population et la date de ce recensement) à partir de fichier plat. Ceci bien sûr afin d'éviter de faire le travail de mise à jour des centaines de communes de France à la main.

Pour les plus curieux, le code source du robot se trouve à l'adresse suivante : DroopigBot sur google code

Bref, le robot a fonctionné sur les communes de Charente-Maritime (ainsi que sur une partie de la Vendée) et m'a donné une idée lumineuse : alimenter automatiquement notre wiki de documentation interne. En effet, nous avions tout un tas de site différent dispersé avec des fonctionnalités différentes :

  • Un inventaire de machine

  • Un spip de documentation (avec une version complètement obsolète)

  • Un inventaire par mail de nos instances de serveurs Java

  • Mais également plein de chose avec des fichiers plats dans plein d'endroit différent



J'ai donc récupéré le code que j'avais utilisé pour mes communes afin d'en faire quelque chose de plus simple sous la forme d'un script d'extraction et de mise à jour de contenu d'article.

Je ne vais pas tout vous présenter mais juste l'utilitaire en ligne de commande qui me permet de faire cette mise à jour : update_article.sh. Vous pouvez le récupérer à l'adresse suivante : http://code.google.com/p/droopigbot/source/browse/#svn/trunk/public_html.

Pour le configurer, c'est assez simple : créer un utilisateur avec droit d'écriture sur votre mediawiki, créer un fichier robot_config.inc.php avec les informations de connexion. Ci-dessous un exemple pour ce fichier :
$robot = new DroopigBot("Nomdubot", "passdubot", "http://addresse-du-serveur/wiki");
?>


Une fois enregistré, votre robot est prêt à fonctionner. Faisons un test simple d'extraction :

drayan@robert:~/dev/droopigbot/public_html$ ./update_article.sh --name 'Page de test' --dump
Un article de test.


Alimentons maintenant un fichier pour mettre à jour cet article :
drayan@robert:~/dev/droopigbot/public_html$ cat > essai.txt
Mon article a été mise à jour.

Et j'en suis très content.


Lançons la mise à jour :
drayan@robert:~/dev/droopigbot/public_html$ ./update_article.sh --name 'Page de test' --update ./essai.txt --no-simulation --message 'Mise à jour par un robot'
Updating 'Page de test' with './essai.txt' content


Si on jette un coup d'oeil à l'article, nous voyons qu'il a été mis à jour :



Allons maintenant voir l'historique :


Reste maintenant plus qu'à faire vos scripts de mise à jour de votre wiki :)

dimanche 11 juillet 2010

Sortie de pnp4nagios 0.6.5

Juste un petit billet pour signaler la sortie de pnp4nagios en version 0.6.5. Un rapide coup d'oeil sur le changelog nous donne les nouveautés suivantes (par rapport à la version 0.4.x) :
  • Interface Web se basant sur le moteur Kohana, thème jQuery et utilisation de plugin jQuery
  • process_perfdata.pl peut utiliser plusieurs bases RRD par source nagios
  • Nouvelle fonctionnalitée d'installation : possibilité de spécifier l'emplacement des fichiers layout (-–with-layout)
  • Lors d'une erreur de rendu, les erreurs sont affichées sous la forme d'image.
  • Les templates d'affichage ne peuvent plus changer la valeur des variables internes.
  • Possibilité d'utiliser les templates des versions 0.4.x.
  • Refonte du code PDF ainsi que pour les pages.
  • Optimisation du Template par défaut (default.php)
  • Export des bases RRD au format XML, CSV et JSON en utilisation la fonction RRDtool "xport"
  • Les erreurs font pointer sur la FAQ en ligne.
  • Plugin permettant d'afficher les graphiques dans un popup.
  • Support du rrdcached
Une fonctionnalité que je n'ai pas encore eu le loisir de tester est la partie "special template" qui permet apparemment de récupérer des informations sur plusieurs machines en même temps pour les afficher sur un même graphique. Une application de cette nouvelle fonction pourrait être de disposer d'un graphique indiquant le trafic en temps réel de 4 machines frontales Web.

Autre fonctionnalité nouvelle sur la version 0.6.5, la présence de fonction d'aide à la création de template (voir la page suivante : http://docs.pnp4nagios.org/pnp-0.6/tpl_helper). Ces fonctions vous permettront de simplifier la prise en main des outils RRD. Quelques exemples d'utilisation :
  • Définir une nouvelle source de données RRD : $def = rrd::def('var1', $RRDFILE[0], $DS[0], 'MAX');
  • Définir un gradient : $def .= rrd::gradient('var1', '#ff0000', '#ffff00' );
  • Afficher une ligne : $def .= rrd::line1('var1', #ff00ff );
Autre point qui pourrait vous intéresser, j'ai reversé une traduction française de l'interface.

vendredi 25 juin 2010

Compilation NRPE sous AIX 5.3 avec support du SSL

J'ai eu dernièrement besoin de compiler un agent nagios NRPE pour AIX 5.3. Malheureusement pour moi, cet OS est livré sans librairie dynamique openssl (ie libssl.so). J'ai donc du compiler nrpe en static.

N'ayant pas trouver d'information intéressante sur le net (en dehors de désactiver le ssl), je me suis dit que ce genre d'information pourrait être utile à d'autre.

Tout d'abord, modifier le fichier configure de la manière suivante (sur une version 2.12 de nrpe) :


$ diff configure.orig configure
6673c6673
< if test -f "$dir/libssl.so"; then
---
> if test -f "$dir/libssl.a"; then
6687c6687
< LIBS="$LIBS -lssl -lcrypto";
---
> LIBS="$LIBS $ssllibdir/libssl.a $ssllibdir/libcrypto.a";


Le patch consiste à changer la nature du fichier recherché (libssl.a à la place de libssl.so) et remplacer les flags de compilation -lssl et -lcrypto par les fichiers des bibliothèques que l'on vient de trouver.

Il ne reste plus qu'à lancer configure avec les options suivantes :
./configure --with-ssl=/opt/freeware --with-ssl-lib=/opt/freeware/lib --prefix=/opt/nagios


Un coup de make ; make install et vous disposez maintenant des binaires nrpe et check_nrpe à la mode AIX et surtout avec le support du SSL.

jeudi 24 juin 2010

Problème de performance avec pnp4nagios sous Solaris

Depuis quelques temps déjà, je devais mettre en place pnp4nagios combiné à un nagios 3.2 sur une nouvelle machine. Auparavant, je passais par une machine un peu vieillotte (un sunfire V210 avec 2 Go de mémoire) que je devais remplacer par une plus récente (à base de M5000 Sun). L'ancienne plateforme passait par un nagios combiné avec ndoutils (un backend de stockage des données de performance sous MySQL). Cette plateforme était très contraignante pour plusieurs raisons :
  • Plugin de génération de graphique maison (c'est votre serviteur qui avait écrit ça)
  • Scripts de gestion du contenu de la table nagios_servicechecks : je découpais cette table en journée pour pouvoir supporté le volume de données (environ 200 Mo/jour et 17 Go d'historique)
  • Lenteur de la solution : nagios et le module de base de données (ndo2db) n'était pas très consommateur mais en revanche, la base MySQL était très consommatrice de ressource disque et CPU.
Bref, pour toutes ces raisons et après un rapide tour des solutions existantes, nous avions décidé de partir sur l'excellent plugin pnp4nagios pour l'historisation. Avec ce plugin, plus de serveur MySQL, moins d'IO, plus de script de maintenance. Bref, que du bonheur.

C'est donc assez confiant qu'il y a quelques jours que nous avons procédé à la mise en production. Mais comme toujours, j'ai eu une mauvaise surprise lors de la migration. Lors de la fin de la bascule de tous nos anciens services sur la nouvelle (environ 900 services), j'ai commencé à voir des messages d'erreurs m'indiquant un time out lors du lancement du script process_perfdata.pl au bout de 5 secondes. En y regardant de plus près, j'ai constaté que le timeout était fixé par la directive perfdata_timeout=5 et en urgence, j'ai donc fixé le timeout à 30 s.

Une fois ce contournement mis en place, j'ai pu regarder en détail le problème. J'ai notamment constaté que la machine passait énormément de temps à faire ses mises à jour. En rajoutant quelques traces, je me suis rendu compte que le script process_perfdata.pl n'utilisait pas la bibliothéque native perl RRD mais le binaire rrd ! Suite à quelques tests que j'avais pu faire il y a quelques temps sur les deux modes de fonctionnement, j'ai essayé de voir si le problème ne pouvait pas venir de là.

Après un coup d'oeil à la configuration de nagios et je suis tombé sur cette partie :
define command {
command_name process-service-perfdata-file
command_line /bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl --bulk=/var/nagios/service-perfdata
}

define command {
command_name process-host-perfdata-file
command_line /bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA --bulk=/var/nagios/host-perfdata
}
Rien de bien choquant mais le problème est que sous Solaris la version de RRD venant de sunfreeware s'installe dans /usr/local. Problème, ce dernier est livré avec un binding perl prévu pour la version 5.8.8. Malheureusement, la version installée par défaut (ie dans le répertoire /usr/bin) est une version 5.8.4 et n'est pas en mesure d'utiliser la bibliothéque native perl de RRD.

Bref, j'ai donc changé la version de perl par celle se trouvant dans /usr/local/bin :
define command {
command_name process-service-perfdata-file
command_line /usr/local/bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl --bulk=/var/nagios/service-perfdata
}

define command {
command_name process-host-perfdata-file
command_line /usr/local/bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA --bulk=/var/nagios/host-perfdata
}
Un coup d'arrêt relance et après quelques temps, j'ai obtenu une nette diminution au niveau des temps de traitement de perfdata :

Zoom sur la partie basse :

C'est ici qu'on constate tout l'intérêt de l'utilisation de la bibliothéque native RRD : on est passé à des temps de traitement d'environ 30s à des temps de traitement de l'ordre de la seconde.

mercredi 23 juin 2010

Supervision de WebLogic à l'aide de nagios

Afin de surveiller la consommation mémoire de nos instances WebLogic, j'ai commencé à écrire un plugin se basant sur le protocole SNMP.

Pour ceux qui ne le saurait pas, WebLogic est un serveur d'application Java propriétaire.

Ce besoin de surveillance vient du fait que les serveurs les hébergeants (des Sun V890 avec 40 Go de mémoire) sont sur le point d'arriver à saturation mémoire. Pour cette raison, nous avons donc essayé de savoir quelles instances consommées et à quelle hauteur.

Il faut dire que nous avons constaté que la mémoire allouée aux JVMs étaient le double de la mémoire physique ! Pour info, la machine héberge une centaine d'instance WebLogic en version 8.1 et Java 1.4. Comme vous vous en doutez, nous avons prévu de faire le ménage dans nos instances. Mais pour ça, il nous faudrait un petit état des lieux, d'où l'écriture d'un script.

Passons maintenant à l'écriture du script.

Premier point, il faut se débrouiller pour activer l'agent SNMP au niveau du domaine WebLogic. Nous pourrons ainsi interroger le serveur sans avoir à faire de couteuses interrogations à base de programme en java. Nous allons ensuite nous baser sur l'outil snmpwalk.

Pour mémoire, une page de référence de la MIB de ce serveur d'application est disponible à l'adresse suivante : http://download.oracle.com/docs/cd/E13222_01/wls/docs90/snmp/index.html

Commençons tout d'abord par interroger l'agent SNMP WebLogic en ligne de commande :
drayan@robinet:~$ snmpwalk -m ./BEA-WEBLOGIC-MIB.mib -c public -v 1 192.168.0.10:7061 .1.3.6.1.4.1.140.625.180
La branche .1.3.6.1.4.1.140.625.180 correspond aux informations sur les threads Java actifs. Nous pouvons également interroger la branche .1.3.6.1.4.1.140.625.340.1 pour récupérer la quantité de mémoire consommée (jvmRuntimeHeapSizeCurrent). A noter que pour connaître les instances présentes dans le domaine WebLogic, je fais appel à la branche 1.3.6.1.4.1.140.625.361.1.

Une fois enrobé tout ceci j'obtiens le script suivant :
#!/usr/bin/perl
use strict;
use File::Basename;
use Sys::Hostname;
use Getopt::Long;

my $verbose = 0;
my $show_help = 0;
my $show_version = 0;
my $snmp_address = 0;
my $instance = 0;
my $snmp_cmd = "snmpwalk -m ".dirname($0)."/../share/BEA-WEBLOGIC-MIB.mib";
my $show_only = ".*";

sub usage {
my ($msg) = @_;
$msg = "" if(!$msg);
my $name = basename($0);
print "Usage :
\$ $name [OPTION]

Get runtime information about WebLogic instance
-h --help display this help and exit.
--intance <SRVNAME>[,<>] name of the instances to check.
--only <REGEXP> show only instance corresponding to regexp.
--snmp <HOST[:PORT]> address (and port) of the snmp server.
-v --verbose verbose.

Examples:
\$ $name --port 10861 --instance srvback11,srvback12,srvback13,srvback14
".($msg ? "\n".$msg."\n" : "")
}

GetOptions(
"V" => \$show_version,
"version" => \$show_version,
"h" => \$show_help,
"help" => \$show_help,
"v" => \$verbose,
"verbose" => \$verbose,
"snmp=s" => \$snmp_address,
"instance=s" => \$instance,
"only=s" => \$show_only,
);

if($show_help) { usage(); exit(0); }
die("Please specify snmp address (--snmp host:port)") if(!$snmp_address);

if(!$instance) {
my(%instance_name, %instance_state) = ((), ());
my @tmp = ();
my ($i, $j) = (0, 0);
foreach(`$snmp_cmd -c public -v 1 $snmp_address 1.3.6.1.4.1.140.625.361.1 2> /dev/null`) {
if(/BEA-WEBLOGIC-MIB::serverLifeCycleRuntimeName.*STRING: "(\w+)"/) {
$instance_name{$i++} = $1;
} elsif(/BEA-WEBLOGIC-MIB::serverLifeCycleRuntimeState.*STRING: "(\w+)"/) {
my $label = $instance_name{$j++};
$instance_state{$label} = $1;
if($1 =~ /RUNNING/) {
print "$label is RUNNING\n" if($verbose);
push(@tmp, $label);
} else {
print "Ignoring $label\n" if($verbose);
}
}
}
$instance = join(",", @tmp);
}

my $perfdata = "";
foreach my $srv(sort(split(/,/, $instance))) {
next if(!($srv =~ /$show_only/));
my @result = `$snmp_cmd -c public\@$srv -v 1 $snmp_address .1.3.6.1.4.1.140.625.340.1 2> /dev/null`;
my($label, $current_max_heap, $free_heap);
foreach(@result) {
if(/BEA-WEBLOGIC-MIB::jvmRuntimeName.*STRING:\s+"(\w+)"/) { $label = $1; }
elsif(/BEA-WEBLOGIC-MIB::jvmRuntimeHeapFreeCurrent.*INTEGER:\s+(\d+)/) { $free_heap = $1; }
elsif(/BEA-WEBLOGIC-MIB::jvmRuntimeHeapSizeCurrent.*INTEGER:\s+(\d+)/) {
$current_max_heap = $1;
$current_max_heap = int($current_max_heap / 1048576 + .5);
$free_heap = int($free_heap / 1048576 + .5);
my $used = $current_max_heap - $free_heap;
$perfdata .= " $label=$used;$current_max_heap;$current_max_heap;0;$current_max_heap";
}
}
}

print "WebLogic memory OK|$perfdata\n";
On configure notre agent pour accepter un nouveau type de commande :
command[check_weblogic_memory]=/usr/lib/nagios/plugins/check_weblogic --snmp localhost:7061
On configure un nouveau service sous Nagios :
define service {
host_name machine-weblogic
use generic-service
service_description Suivi memoire WebLogic
check_command check_nrpe!check_weblogic_memory
}
Et hop ! Au bout de quelques jours, vous obtenez le résultat suivant (en combinaison avec pnp4nagios) :


lundi 31 mai 2010

Recyclage d'une miroir SDS sous ZFS

ATTENTION !!! Dans ce qui va suivre, je vais vous expliquer comment mettre en place un pool ZFS. Cette manœuvre supprimera entièrement le contenu de votre ancien FS. Pensez à faire des sauvegardes de vos anciennes données !!!

Il y a peu de temps, j'ai eu à préparer une machine Solaris (une T5120 pour les plus curieux d'entre vous). A l'origine cette machine n'utilisait que du SDS (un mirroring software livré en standard sous Solaris) en combinaison avec les slices Solaris (l'équivalent des partitions classiques sous Linux). Comme on ne peut faire que 7 slices et que 5 slices étaient déjà pris pour le système et que la machine n'avait que deux disques, je me suis donc trouvé très rapidement bloqué pour la création de nouveaux FS. Auparavant, pour contourner ce problème, nous utilisions le mécanisme de lofs de Solaris (l'équivalent de l'option de montage bind sous Linux). Mais je n'étais pas vraiment enchanté de la situation ...

J'ai donc décidé de recycler un slice des deux disques qui étaient auparavant alloué à un device SDS afin de le réaffecter à un pool ZFS. En effet, avec ZFS, plus de problème de limitation de slice, de problème de mirroring, de création de FS, etc. Bref quelque chose d'un petit peu plus poussé en terme de fonctionnalité.

Pour démarrer, nous allons jeter un coup d'oeil au miroir existant avant de le casser. Tout ceci se fait à l'aide de la commande metastat :

$ metastat d6
d6: Miroir
Sous-miroir 0: d16
Etat : Ok
Sous-miroir 1: d26
Etat : Ok
Accès : 1
Option de lecture : roundrobin (par défaut)
Option d'écriture : parallel (par défaut)
Taille : 179891328 blocs (85 GB)

d16: Sous-miroir de d6
Etat : Ok
Taille : 179891328 blocs (85 GB)
Bande 0 :
Périphérique Bloc de débu Base Etat Redis Tranche dynamique
c1t0d0s6 0 Non Ok Oui
[...]


Nous avons donc un device d6 constitué de deux sous-miroirs d16 et d26 eux-même étant les slices 6 des disques c1t0d0 et c1t1d0 (soit respectivement les slices c1t0d0s6 et c1t1d0s6). Nous allons donc supprimer tout ceci à l'aide de la commande metaclear :
- suppression du mirroir :
metaclear d6
- puis suppression des sous-mirroirs :
metaclear d16
et
metaclear d26
Maintenant que nous avons deux slices de disponible, nous allons les allouer à un pool ZFS en mirroir que l'on appellera zfs_pool :
$ zpool create -f zfs_pool mirror c1t0d0s6 c1t1d0s6
NB : ne pas oublier l'option '-f'. Dans notre cas, comme les devices étaient anciennement utilisé en tant que partition ufs, zpool refuse de créer le pool zfs avec le message suivant :
$ zpool create zfs_pool mirror c1t0d0s6 c1t1d0s6
spécification vdev incorrecte
utilisez '-f' pour ignorer les erreurs suivantes :
/dev/dsk/c1t0d0s6 contient un système de fichiers ufs.
Et voilà ! Notre pool ZFS est prêt !

Tentons maintenant de créer un FS :
$ zfs create -o mountpoint=/data zfs_pool/data
Et voilà ! Le FS est monté, formaté et prêt à l'emploi. A remarquer que par défaut, il n'y a aucune limitation dans l'utilisation du FS et qu'il est possible d'utiliser tout l'espace du pool. Bien sûr, il est possible de limiter l'utilisation à l'aide de l'option quota. Ceci peut se faire avec la commande zfs set :
$ zfs set -o quota=10G zfs_pool/data
Vérifions le résultat :
$ df -h /data
Filesystem size used avail capacity Mounted on
zfs_pool/data 10G 8K 10G 1% /data
Et voilà, je pense que ça sera tout pour aujourd'hui.

jeudi 27 mai 2010

Problème de buffer nrpe

Cet après-midi, j'ai commencé à mettre en place une surveillance de tablespace sur Oracle. Petit soucis, j'ai dépassé sans trop m'apercevoir la limite du buffer de nrpe (1024 pour un résultat).

Autre petit problème, il est impossible de modifier la taille du buffer sans avoir à recompiler la commande check_nrpe et - petit bonus - le client check_nrpe obtenu est incompatible avec les anciens démons NRPE.

Donc, retour à l'ancienne version et du coup, j'ai modifié ma commande de surveillance pour faire mes stats en deux fois :).

jeudi 20 mai 2010

Connexion via ipmi sur un serveur

Je suis plutôt habitué au console Solaris mais il se trouve que récemment, j'ai eu l'occasion de bosser sur une console ipmi. Le principe est le même, à savoir une console texte accessible via le réseau.

Comment est-ce qu'on arrive à s'intéresser à ce genre de problème allez vous me demander ? Et bien simplement, j'ai eu besoin de modifier les paramètres du BIOS sur une machine d'un client qui se trouve chez un hébergeur. Et il est vrai que sans accès physique à la machine, on se trouve bien bête :).

Assez parlé, commençons l'activation de l'ipmi sur notre serveur. Il nous faut tout d'abord installer ipmitool :
# apt-get install ipmitool
Nous allons maintenant charger le module kernel ipmi :
# modprobe ipmi_si
# modprobe ipmi_devintf
# lsmod | grep ipmi
ipmi_devintf 13200 0
ipmi_si 43628 0
ipmi_msghandler 38520 2 ipmi_devintf,ipmi_si
Tout semble bon. Ajoutons maintenant le module au redémarrage :
# echo "ipmi_devintf" >> /etc/modules
# echo "ipmi_si" >> /etc/modules
Nous allons maintenant définir un utilisateur qui puisse se connecter à la console (nous utilisons ici l'id 8 pour l'utilisateur operator du fait que la société qui nous héberge utilise déjà les 7 premiers identifiants pour ses propres besoins) :
# ipmitool -U root user set name 8 operator
# ipmitool -U root user set password 8 operatorpass
# ipmitool -U root user enable 8
Nous allons maintenant essayer de nous connecter à la console :
ipmitool -I lanplus  -U operator -P operatorpass -H 10.10.10.10 sol activate
Malheureusement, nous allons nous retrouver bloquer puisque personne n'écoute. Néanmoins, si nous rebootons notre serveur, il nous permettra d'accéder au bios (le but de ce billet !). Un rapide coup de F2 au redémarrage et nous voyons apparaître l'écran suivant :



Activons ensuite le support Intel de virtualisation :


Il faudra ensuite arrêter électriquement la machine et la redémarrer à l'aide de l'interface Web de l'hébergeur.

Notre mission est terminée mais pourquoi s'arrêter en si bon chemin ? Nous allons ajouter la gestion de grub ainsi que celle de la console de Linux.

Pour la gestion de la console dans grub, il faut rajouter les lignes suivantes dans le fichier /boot/grub/menu.lst :
serial --unit=0 --speed=9600 --word=8 --parity=no --stop=1
terminal --timeout=15 serial console
Et ensuite mettre à jour grub :
grub-install /dev/sda
Enfin, ajoutons le support du port série sur le kernel linux. Il faut pour cela ajouter console=tty0 console=ttyS0,9600n8 dans la ligne de démarrage du kernel. Exemple :
kernel          /vmlinuz-2.6.26-2-amd64 root=/dev/md1 ro quiet console=tty0 console=ttyS0,9600n8

mercredi 19 mai 2010

Multiple vs single datasource sous pnp4nagios

Voici maintenant quelques temps que nous utilisons pnp4nagios et je n'avais - jusqu'à maintenant - pas eu à me plaindre de ce produit plus que ça. Malheureusement, aujourd'hui, je suis tombé sur un os : la gestion des données de performances changeante. Dit comme ça, ça peut ne pas sembler complètement évident mais vous allez très vite comprendre que ça peut devenir embêtant ...

Sous nagios, les données de performances (ce qu'on retrouve après le '|' sous la forme param1=i;warn-i;crit-i;min-i;max-i param2=j) est en principe tout le temps identique. Malheureusement, vous l'aurez deviné, les choses ne sont pas toujours simple et vous pouvez rencontrer des commandes qui à un moment vous donnez un certain résultat et qui le moment d'après vous sorte un résultat d'une autre forme. Ce type de désagrément arrive dans les cas suivants :
- changement du comportement d'un script
- changement des indicateurs surveillés (comme dans check_disk par exemple).

Dans ce cas, pnp4nagios perd un peu la boule et du coup, remplace des séries de données par d'autre et plus embêtant, fait un mélange in fine entre les différentes séries. Ce petit désagrément m'est arrivé cet après-midi et j'ai donc regarder un peu si j'étais la seule personne a qui c'était arrivé. Donc en épluchant la documentation, j'ai compris qu'il s'agissait de l'utilisation des datasources de type SINGLE vs MULTIPLE sous RRD. Plus simplement, dans le cas d'un RRD SINGLE (par défaut), toutes les données sont stockées dans un seul fichier. Très pratique pour réduire le bazard dans un répertoire. En revanche, dès que mes sources changent, c'est l'anarchie. L'autre option MULTIPLE quand à elle va créer un datasource par source de données.

C'est bien beau vous allez me dire mais qu'est ce que je fais du coup de mes 6 mois d'historique ? Et bien là, mauvaise nouvelle pour l'instant, il faudra restaurer le fichier avant le changement de datasource ... Ensuite, le script rrd_convert.pl est là pour faire le découpage des fichiers et - cerise sur le gateau - positionner un fichier de configuration dans le répertoire etc/check_commands de pnp4nagios afin de préciser au script process_perfdata.pl de ne plus utiliser un datasource SINGLE mais MULTIPLE.

Ci-dessous, quelques exemples de l'utilisation de cette commande :
- Consultation des commandes disponibles :

$ /usr/share/pnp4nagios/libexec/rrd_convert.pl --list_commands
XML Files analyzed 14
XML Files found 0
Old XML Files ignored 1
Number of unique check_commands 7
\ List of Check Commands
|- check-host-alive 7
|- 2
|- check_ping 1
|- check_load 1
|- check_all_disks 1
|- check_users 1
|- check_http 1

- Etat des indicateurs sur mon nagios de test avant conversion :

$ ls -ltr Current_Load.*
total 6084
-rw-rw-r-- 1 nagios nagios 1151496 2010-05-19 20:46 Current_Load.rrd
-rw-rw-r-- 1 nagios nagios 12872 2010-05-19 20:46 Current_Load.xml

- Lancement de la conversion :

$ /usr/share/pnp4nagios/libexec/rrd_convert.pl --check_command=check_load

Search pattern check_load
XML Files analyzed 14
XML Files found 1
Old XML Files ignored 1
Number of unique check_commands 7
Start Converter [n|Y]?:Y

Config for command check_load created (/usr/share/pnp4nagios/etc//check_commands/check_load.cfg)
File 1/1
RRDtool dump to /tmp/rrd_convert/localhost-Current_Load.dump
Manipulating /tmp/rrd_convert/localhost-Current_Load.dump
............ done 48166 lines
Restoring File
/var/spool/pnp4nagios/perfdata/localhost/Current_Load_load1.rrd
/var/spool/pnp4nagios/perfdata/localhost/Current_Load_load15.rrd
/var/spool/pnp4nagios/perfdata/localhost/Current_Load_load5.rrd
... done
DONE


\Statistics:
|- runtime 3.048887
|- rrd_out 3
|- old_xml 1
|- rrd_in 1

- Etat après la conversion :
$ ls -ltr Current_Load*

-rw-rw-r-- 1 nagios nagios 1151496 2010-05-19 20:51 Current_Load.rrd
-rw-rw-r-- 1 nagios nagios 12840 2010-05-19 21:21 Current_Load.xml
-rw-r--r-- 1 nagios nagios 384952 2010-05-19 21:21 Current_Load_load5.rrd
-rw-r--r-- 1 nagios nagios 384952 2010-05-19 21:21 Current_Load_load1.rrd
-rw-r--r-- 1 nagios nagios 384952 2010-05-19 21:21 Current_Load_load15.rrd


Le fichier Current_Load.rrd existe toujours, mais au vu de la date du fichier, il n'est plus alimenté. Nous pouvons également jeter un coup d'oeil dans le répertoire etc/check_commands de pnp4nagios :

$ more /usr/share/pnp4nagios/etc/check_commands/check_load.cfg
# Generated by rrd_convert.pl 0.6.3
RRD_STORAGE_TYPE = MULTIPLE


Comme nous pouvons le voir, l'outil rrd_convert.pl a bien créé un fichier pour la commande check_load afin de lui indiquer que le type de stockage étant maintenant MULTIPLE.

Demain, nous testerons ça sur des vrais données de recette !

samedi 15 mai 2010

Personnalisation de PNP4Nagios : écriture d'un template

L'import de mon historique ndoutils sous pnp4nagios s'est bien passé et j'ai maintenant quelques courbes avec lesquels je peux m'amuser. J'ai notamment personnalisé l'aspect des courbes CPU afin d'y faire apparaître une tendance sur une certaine période. Pour info, j'ai mis à disposition le plugin à l'emplacement suivant : http://docs.pnp4nagios.org/templates/check_cpu

Nous allons voir ensemble comment fonctionne la création de template pour pnp4nagios. Pour cela, il suffit de se rendre dans le répertoire de pnp4nagios dans le sous-répertoire share/templates. De là, on va créer un nouveau fichier et nous allons commencer à personnaliser l'aspect de nos graphiques (ici check_cpu.php).

Ce qu'il faut savoir avant de commencer est que l'interface pnp4nagios génère des fichiers PNG à l'aide des RRDTools. Notre template est donc en réalité un petit programme en PHP qui initialisera les valeurs envoyé au programme RRDTool.

Commençons tout d'abord par changer le titre de notre graphique :


#
# Copyright (c) 2010 Yannig Perre
# Plugin: check_cpu
#
$ds_name[1] = "Activité CPU";

$opt[1] = "--vertical-label CPU -l0 --title \"Activité CPU sur $hostname\" ";


Nous allons maintenant définir les périodes pendant lesquelles nous allons dessiner une tendance :


$trend_array = array(
"one_month" => array(strtotime("-1 month", $this->TIMERANGE['end']), $this->TIMERANGE['end'], "Tendance sur 1 mois:dashes=10", "#FF007F", "LINE3"),
"global_trend" => array($this->TIMERANGE['start'], $this->TIMERANGE['end'], "Tendance globale:dashes=20", "#707070", "LINE2"),
);


Ci-dessous, nous définissons simplement les sources de notre graphique.

NB : Nous allons cumuler les valeurs des sources afin d'obtenir un graphique sous forme d'aire (io en haut du graphique, user puis consommation système). Pour se faire nous utilisons la notion de CDEF des outils RRDs :


$def[1] = "DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE " ;
$def[1] .= "DEF:var2=$RRDFILE[2]:$DS[2]:AVERAGE " ;
$def[1] .= "CDEF:user=var2,var1,+ " ;
$def[1] .= "DEF:var3=$RRDFILE[3]:$DS[3]:AVERAGE " ;
$def[1] .= "CDEF:io=var3,var2,+,var1,+ " ;


Une fois nos sources redéfinies, nous allons maintenant définir nos tendances en fonction du tableau $trend_array que nous avons définit précédemment :


$trend_elements = "";

foreach(array_keys($trend_array) as $trend) {
$def[1] .= "DEF:var1$trend=$RRDFILE[1]:$DS[1]:AVERAGE:start=".$trend_array[$trend][0]." ";
$def[1] .= "DEF:var2$trend=$RRDFILE[2]:$DS[2]:AVERAGE:start=".$trend_array[$trend][0]." ";
$def[1] .= "CDEF:user$trend=var2$trend,var1$trend,+ " ;

$def[1] .= "VDEF:dtrend$trend=user$trend,LSLSLOPE ";
$def[1] .= "VDEF:htrend$trend=user$trend,LSLINT ";
$def[1] .= "CDEF:curve_user$trend=user$trend,POP,dtrend$trend,COUNT,*,htrend$trend,+ ";
$trend_elements .= $trend_array[$trend][4].":curve_user$trend".$trend_array[$trend][3].":\"".$trend_array[$trend][2]."\" " ;
}


Ici, on rajoute les valeurs de warning et critical si présente :

if ($WARN[1] != "") {
$def[1] .= "HRULE:$WARN[1]#FFFF00 ";
}
if ($CRIT[1] != "") {
$def[1] .= "HRULE:$CRIT[1]#FF0000 ";
}


Enfin, nous allons dire aux RRD tools de dessiner 3 graphiques d'aire : les io en premier (en vert), la consommation user en bleu et enfin la consommation système en dernier. A noter que nous ajoutons des lignes noirs pour mieux définir les 3 aires.


$def[1] .= "AREA:io#00FF00:\"iowait\" " ;
$def[1] .= "GPRINT:var3:LAST:\"%6.2lf\" " ;
$def[1] .= "GPRINT:var3:AVERAGE:\"moy %6.2lf\" " ;
$def[1] .= "GPRINT:var3:MAX:\"max %6.2lf\\n\" " ;
$def[1] .= "AREA:user#005CFF:\"user \" " ;
$def[1] .= "GPRINT:var1:LAST:\"%6.2lf\" " ;
$def[1] .= "GPRINT:var1:AVERAGE:\"moy %6.2lf\" " ;
$def[1] .= "GPRINT:var1:MAX:\"max %6.2lf\\n\" ";
$def[1] .= "AREA:var2#FF5C00:\"sys \" " ;
$def[1] .= "GPRINT:var2:LAST:\"%6.2lf\" " ;
$def[1] .= "GPRINT:var2:AVERAGE:\"moy %6.2lf\" " ;
$def[1] .= "GPRINT:var2:MAX:\"max %6.2lf\\n\" " ;
$def[1] .= "LINE1:io#000000:\"\" " ;
$def[1] .= "LINE1:user#000000:\"\" " ;
$def[1] .= "LINE1:var2#000000:\"\" " ;
$def[1] .= $trend_elements;


Voici notre fichier template terminée, il ne nous reste plus qu'à consulter le résultat sur l'interface PNP. Voici ce que j'obtiens par exemple après quelques petits réglages au niveau de la tendance sur une de mes machines sur 6 mois d'historique :

mercredi 12 mai 2010

Compilation NRPE et génération d'un binaire statique sous Solaris 8 ou 10

On va pas aller jusqu'à dire qu'en ce moment Nagios soit toute ma vie mais en tout cas, au taff, ça occupe pas mal mes journées. Donc, je vais essayer de sortir les astuces que j'ai pu utiliser pour arriver à compiler NRPE et les plugins de surveillance standard.

Donc, pour la compilation, récupérer le source de NRPE, le décompresser et commencer par modifier le fichier src/nrpe.c de la manière suivante :

617c617
< log_facility=LOG_AUTHPRIV;
---
> log_facility=LOG_AUTH;
619c619
< log_facility=LOG_FTP;
---
> log_facility=LOG_DAEMON;


Une fois la modification terminée, il nous faut maintenant lancer configure avec les options suivantes :

./configure --prefix=/path/to/nagios --with-ssl=/usr/local/ssl/lib

NB : Ici il faut s'assurer d'avoir télécharger un compilateur GCC et OpenSSL depuis le site www.sunfreeware.com.

Lancez ensuite la compilation. En principe, vous devriez obtenir un nrpe fonctionnel mais lié aux librairies situées dans /usr/local/lib et autant vous dire, vous n'aurez jamais cette librairie présente sur vos machines Solaris.

Pour cette raison, nous allons donc générer un binaire statique pour ne plus avoir de dépendance sur openssl. Pour se faire, se rendre dans le répertoire src et relancer manuellement la compilation de nrpe avec la commande suivante :

gcc -g -O2 -I/usr/local/ssl/include/openssl -I/usr/local/ssl/include -DHAVE_CONFIG_H -o nrpe-static \
nrpe.c utils.c -lsocket -L/usr/local/ssl/lib /usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a \
-lnsl -lsocket ./snprintf.o


Pour info, voici le résultat sous Solaris 10 :

$ ls -l nrpe nrpe-static
-rwxr-xr-x 1 root root 118888 mars 19 14:42 nrpe
-rwxr-xr-x 1 root root 1349532 mars 19 14:41 nrpe-static


Le binaire est maintenant parfaitement fonctionnel. Il ne vous reste plus qu'à le déployer sur vos machines.

mardi 11 mai 2010

Import en cours

J'ai lancé mon script d'import de ma base ndo MySQL vers pnp4nagios. J'ai compté, il y en a pour environ 25 minutes par jour et j'ai environ 130 jours à importer. Après avoir parallélisé un peu les traitements j'ai réussi à descendre à 15 minutes pour chaque jour. Chouette, ça me fera donc environ 30 heures d'import ...

Courage ! On va y arriver.

lundi 10 mai 2010

Test du module RRD perl

Je suis en ce moment en train de finir mes scripts de migration de la base MySQL ndoutils vers des bases RRD gérées par pnp4nagios.

Globalement, le script est terminé et je suis juste en train de faire quelques tests. A cette occasion, j'ai voulu connaître le différentiel de performance entre RRD via le binaire et via la bibliothèque Perl.

Pour se faire, j'ai donc écrit le script suivant :


#!/usr/bin/perl
use RRDs;
$use_system = 1;

$current = time();
$step = 30;
$range = 3600 * 24 * 7;
$start = $current - $range;
print "Début : ".scalar(localtime())."\n";
if($use_system) {
system("rrdtool create test.rrd --start $start --step $step DS:valeur_test:GAUGE:600:U:U RRA:AVERAGE:0.5:1:".($range / $step));
} else {
RRDs::create("test.rrd", "--start", $start, "--step", $step, "DS:valeur_test:GAUGE:600:U:U", "RRA:AVERAGE:0.5:1:".($range / $step));
}

$j = 0.;
$| = 1;
$i = 0;
for($t = $start; $t < $current; $t += $step) {
$value = int(200.5 + cos($j) * 100.);
if($use_system) {
system("rrdtool update test.rrd $t:$value");
} else {
RRDs::update("test.rrd", "$t:$value");
}
$j += 0.001;
$i++;
}
print "Insertion de $i valeurs\n";
if($use_system) {
system("rrdtool graph speed.png --start $start --end $current DEF:def=test.rrd:valeur_test:AVERAGE LINE1:def#000000 -w 1000 -h 400");
} else {
RRDs::graph("speed.png", "--start", $start, "--end", $current,
"DEF:def=test.rrd:valeur_test:AVERAGE", "LINE1:def#000000", "-w", 1000, "-h", 400);
}
print "Fin : ".scalar(localtime())."\n";
system("gwenview speed.png");


En gros, le script génère une sinusoïde que j'affiche ensuite sous gwenview (prenez votre lecteur d'image préféré).

Un rapide test nous donne le résultat suivant :
* via l'utilisation de la bibliothèque :

drayan@robinet:~/nagios/RRD$ ./generate_rrd.pl
Début : Mon May 10 22:45:56 2010
Insertion de 20160 valeurs
Fin : Mon May 10 22:45:57 2010

* via l'utilisation des binaires :

Début : Mon May 10 22:46:08 2010
ERROR: test.rrd: illegal attempt to update using time 1272919568 when last update time is 1272919568 (minimum one second step)
Insertion de 20160 valeurs
1081x449
Fin : Mon May 10 22:48:57 2010


Donc 1 seconde contre environ 3 minutes dans le second cas. On va donc passer par la bibliothèque !

samedi 8 mai 2010

Utilisation de pnp4nagios

pnp4nagios est un ensemble de script perl, PHP et C qui vont vous permettre de récupérer les métriques de nagios (les perfdata) dans des bases RRD. Ces bases vous permettront ensuite de générer des graphiques à l'aide d'une petite interface Web. La force de cet outil est de s'appuyer sur un outil simple et éprouvé : les outils RRD.

Il peut se configurer de trois manières différentes (si on compte la variante à base de NCPD) :
- mode synchrone. Il s'agit du mode le plus simple à mettre en oeuvre.
- mode asynchrone/nagios. Ici, nagios va écrire les perfdatas dans un fichier avant d'être traité par lot à interval régulier par un script pnp4nagios.
- mode asynchrone/NCPD. Ce mode est proche du précédent à la différence que la gestion du traitement se fera à l'aide d'un démon dédié à ce travail.

Comme toujours, le mode de fonctionnement dépendra du nombre d'élément que vous souhaitez surveiller. De mon point de vue, une petite infrastructure (inférieur à un ou deux milliers de services) pourra très bien fonctionner en mode synchrone. Au delà, il faudra se poser la question de mettre en place un mode asynchrone. Sachez que le premier mode asynchrone viendra bloquer nagios pendant les moments d'import des données. Sur très grosse infrastructure avec des surveillances distribués, il sera donc préférable de choisir le dernier mode.

Pour ma part, n'étant pas encore obligé de faire de la surveillance décentralisé (à l'aide de DNX par exemple), j'ai choisi la seconde solution pour son bon compromis performance/complexité. En effet, le dernier mode entrainte forcément l'ajout d'un démon supplémentaire.

Bref, après une petite période de test, je suis en train de commencer à déployer cet outil sur notre infrastructure. J'étudie également l'importation des anciens résultats de notre base ndo/MySQL afin de disposer dès le départ de l'ancien historique. J'ai déjà écrit les scripts d'export de la base et je suis en train de peaufiner les détails. Dès que j'aurais terminé cette petite migration, je viendrai vous en faire part ici même.