Affichage des articles dont le libellé est script. Afficher tous les articles
Affichage des articles dont le libellé est script. Afficher tous les articles

mercredi 13 mars 2013

Mécanisme de hook de SVN


Je sais, vous allez me dire que SVN est vieillot et que de toute façon, en bon geek qui se respecte, ça fait longtemps que vous êtes passé sous git.

Mais voilà, si vous n'êtes pas encore complètement convaincu que SVN n'est pas une solution si mauvaise que ça et que vous utilisez ça chez votre client/employeur, j'ai quelques astuces pour vous.

Tout d'abord, les hooks sont présent dans le répertoire hooks de votre repository. De base, votre repository SVN, à sa création, vient avec un template pour toutes les opérations de hooks possible sous SVN. Ça se présente sous la forme suivante :


ls *.tmpl
post-commit.tmpl
post-unlock.tmpl
pre-revprop-change.tmpl
post-lock.tmpl
pre-commit.tmpl
pre-unlock.tmpl
post-revprop-change.tmpl
pre-lock.tmpl
start-commit.tmpl

Comme vous pouvez le constater, toutes les opérations possible et imaginable sont disponible. Personnellement, j'ai eu l'occasion d'en mettre deux en oeuvre :

  • pre-revprop-change : lancé avant une modification sur une révision ;
  • post-commit : lancé au moment de la fin d'un commit.


Ces hooks vont servir à changer/régler le comportement de votre repository à l'aide de script. Pour les mettre en place, rien de plus simple :

  • Faîtes un script dans le langage qui vous amuse (même si j'aurais tendance à privilégier un script shell Unix tout simple) ;
  • Copier/lier ce script dans le répertoire du hooks en respectant le nom de l'opération à laquelle vous voulez le lier.

Exemple de hooks SVN : pre-revprop-change


Prenons le cas du pre-revprop-change. Ce script est lancé pour vérifier que l'opération de modification d'une révision de votre repository est bien autorisé. Je sais, vous aller me dire que ce type de demande vous parez étrange. Mais comme chacun sait, le client est roi et à coeur vaillant, rien d'impossible !

Dans le cas présent, nous allons justement restreindre cette opération à la modification du message de log de votre révision. Nous allons également interdire que cette modification puisse se faire par un autre utilisateur que celui à l'origine de la modification.

Sans plus attendre, voici donc le fameux script en charge de cette modification :

#!/bin/bash
REPOS="$1"
REV="$2"
USER="$3"
PROPNAME="$4"
ACTION="$5"

if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ] && \
   [ `svnlook author -r "$REV" "$REPOS"` = "$USER" ]; then
  exit 0
fi

echo "Changing revision properties other than svn:log is prohibited" >&2
exit 1

Le principe est simple :
  • On vérifie bien que nous n'allons modifier que le message de la révision (PROPNAME=svn:log) ;
  • L'action est une modification (ACTION=M) ;
  • Enfin, l'auteur de la modification est bien celui à l'origine du commit (svnlook author ... = $USER).
De là, si ces conditions sont remplies, on renvoie un exit 0 et SVN considère que l'opération est valide.

Dans les autres cas, nous renvoyons exit 1 et SVN refusera de lancer la modification.

Couplage avec Jenkins à l'aide d'un événement de post-commit

Prenons maintenant un autre cas : vous voulez coupler votre repository SVN avec un moteur d'intégration continue (type Jenkins) afin de lancer automatiquement vos constructions sans pour autant avoir à poller régulièrement votre repository SVN tout le temps. Ici, l'utilisation d'un évènement de post-commit fera parfaitement l'affaire et pourra lancer automatiquement votre job de construction.

Pour se faire, nous allons créer le script suivant que nous lierons ensuite dans le répertoire hooks avec comme nom post-commit (bien s'assurer également qu'il est exécutable) :

#!/bin/bash
log="/tmp/post_commit.log"
url_jenkins="http://127.0.0.1:8080/job/makeApp-generic/buildWithParameters?token=makeApp"

REPOS="$1"
TRANS="$2"

exec  > $log
exec 2> $log

repository=$(basename $REPOS)

# Définition des paths des différents binaires
for tag in $(svnlook changed -r $TRANS $REPOS | \
             sed 's/tags\//' | awk '{ print $2 }' | \
             sed 's/\/.*//g' | sort -u)
do
  if [ $tag = "trunk" ]; then tag=HEAD ; fi
  echo "Lancement de la construction de '$repository' (tag='$tag')."
  curl "$url_jenkins&application=$repository&tag=$tag" 2> /dev/null
done
NB : Il va sans dire qu'il faudra que votre serveur Jenkins soit en mesure d'accepter le job qui s'appelle makeApp-generic et surtout que vous ayez créé un token d'appel associé pour pouvoir le lancer avec un curl. Tient, je sens que je vais faire un article sur Jenkins dans peu de temps :).

En gros, le script va simplement regarder les répertoires des fichiers qui vont être modifié et, en fonction de ça, lancer une construction (avec les appels curl) auprès de Jenkins. Dans notre exemple, si la modification se fait sur le trunk, le tag est changé en HEAD.

Il ne nous reste plus maintenant qu'à faire une modification dans notre repository et vérifier que le build s'est bien passé en consultat la log /tmp/post_commit.log :

cat /tmp/post_commit.log
Lancement de la construction de 'test' (tag='HEAD').

Voilà, ça sera à peu près tout pour aujourd'hui. A bientôt pour de nouvelle aventure !

vendredi 26 octobre 2012

Plugin de suivi des PDUs

Il y a peu de temps de ça, j'ai eu à mettre en place un suivi des PDUs (Power Distribution Unit) pour un de mes clients. En faisant bien attention de ne pas réinventer la roue, je me suis donc appuyé sur le script développé par boreal labs (http://www.boreal-labs.com/joomla/index.php/en/downloads-menu/view.download/18-pdu/9-checkpwnetrpduload.html). Ci-dessous un petit exemple d'exécution de ce dernier :


./check_pwnet_rpdu_load.pl -H 192.168.0.1 -C public -b 1,2 -m A -w n,12 -c 16,o
PWNET_RPDU_LOAD OK - PDU 'PDU-IT-R5-A' bank #1 load = 3.3A; bank #2 load = 0.0A; | PDUBank1Load=3.3A;13.0;16.0;0;16 PDUBank2Load=0.0A;12.0;16.0;0;16


Une fois intégré dans nagios, mon ami PNP a commencé à produire le résultat suivant :

Seulement voilà, certains PDUs avaient un capteur de température/humidité et j'avais besoin de faire un suivi là dessus. C'est donc à cette occasion, j'ai écrit un script permettant de remonter ces informations. Ce script est disponible à l'adresse suivante : http://code.google.com/p/plugin-nagios-yannig/source/browse/trunk/pdu/check_pdu_sensors.pl

Il vous faudra récupérer la mib du constructeur (le fichier powernet405.mib) et le rendre disponible à snmpwalk (en renseignant son emplacement avec la variable d'environnement MIBDIRS par exemple). Ci-dessous un exemple de test de communication :


./check_pdu_sensors.pl -H 192.168.0.1 -C public 
Temperature/Humidity sensor status is OK - temperature = 22.4°C, humidity = 56%|temperature=22.4 humidity=56%


Ce dernier va vous renvoyer la température et/ou l'humidité (fonction du type de capteur sur votre matériel) à un instant T de votre PDU. Le résultat prend la forme suivante :

J'ai ensuite intégré tout ceci dans nagios et l'ami PNP a commencé à produire des graphiques assez sympas. En voici ci-dessous un petit exemple de suivi sur 2 semaines de l'humidité :


dimanche 11 septembre 2011

Création d'un timelapse

Depuis tout petit, j'ai toujours été intéressé par les étoiles et notamment les superbes images nous faisant découvrir les galaxies, les étoiles mortes, les nébuleuses etc. Paradoxalement, je ne m'étais jamais trop posé la question de faire ces observations par moi même puisque bien d'autre avant moi l'avait fait et - de mon point de vue - l'avait très bien fait.

Mais voilà, par un bel été il y a quelques années, ma mère m'a fait découvrir les anneaux de Saturne directement à l'aide de son petit télescope. C'est à ce moment que j'ai réalisé qu'il serait intéressant de contempler par moi même certain phénomène. Pour toute ces raisons (et pour d'autre comme par exemple la naissance de mon petit dernier), je me suis intéressé dans l'achat d'un appareil photo réflex et les techniques de photographie de type timelapse.

Ah, j'oubliais de vous préciser un truc : je n'utilise que des logiciels libre et ma machine principale héberge un Linux depuis des années. Pour ces raisons, j'essaye de faire partager ma petite expérience sur le sujet avec d'autre. Par la suite, nous utiliserons les logiciels suivant :
  • gphoto : il nous aidera à faire nos prises de vue à espace régulier. Je recommande néanmoins l'utilisation d'un intervalomètre pour éviter de se traîner un portable pendant une séance de photo ;
  • convert : outil de convertion d'image en ligne de commande ;
  • mencoder : outil de création de fichier vidéo.

Prendre des photos à intervalle régulier

Première chose, il faut utiliser un trépied afin que le cadre de vos photos reste identique de bout en bout. Il faut également désactiver l'autofocus de l'appareil ainsi que le stabilisateur d'image si vous en avez un. Fixer maintenant un élément qui vous intéresse et commencez à prendre vos photos à intervalle régulier. Pour se faire vous pouvez soit passer par un intervalomètre soit par le logiciel gphoto. En effet, ce dernier vous permet de prendre des photos directement à l'aide d'un ordinateur. Ci-dessous un exemple de ligne de commande :
gphoto2  --auto-detect --capture-image-and-download -I 1
Ci-dessous une petite explication des options présentes :
  • L'option --auto-detect à pour rôle d'inviter gphoto à utiliser le premier appareil détecté ;
  • L'option --capture-image-and-download invite gphoto à prendre une photo et à la télécharger automatiquement sur le PC ;
  • Enfin, l'option -I 1 indique le temps de pause entre chaque photo.
A la fin de votre séance de photo, vous devriez obtenir quelques centaines d'image que nous allons mettre maintenant bout à bout dans une vidéo.

Création de la vidéo

Nous allons procéder en deux étapes :
  • Retailler les photos ;
  • Assembler les photos dans une vidéo.
Pour la première étape nous allons utiliser l'outil convert de imagemagick. Nous allons également utiliser un petit bout de shell pour lancer cette convertion en boucle :
yannig@portable:~/Images/2011-09/timelapse/resize$ for i in ../*.JPG
do
  echo $i
  convert -resize 1440 $i $(basename $i)
done
L'option -resize 1440 indique à l'outil convert la taille désiré pour le fichier de résultat. Par défaut, la retaille se fait en préservant l'aspect de la photo.

NB : Pour éviter de tout mélanger, j'ai mis le résultat de la conversion dans un sous-répertoire resize.

Passons maintenant à la création de la vidéo à l'aide de mencoder (à lancer dans le répertoire contenant les fichiers retaillés) :
mencoder "mf://*.JPG" -mf fps=15:type=jpg -ovc x264 -x264encopts bitrate=3000 -o video-resultat.flv
Encore une fois, étudions ensemble les options de mencoder :
  • "mf://*.JPG" : donne le patron des fichiers à prendre en compte pour créer la vidéo ;
  • -mf fps=15:type=jpg : donne des informations sur la cadence désirée pour la vidéo ;
  • ovc x264 -x264encopts bitrate=3000 : information sur les paramètres d'encodage de la vidéo ;
  • -o video-resultat.flv : explicite le nom du fichier résultat.

Vidéo de résultat

Ci-dessous un petit exemple de ce que peu donner une vidéo réalisé avec ces outils :



Pour informations, cette vidéo à été réalisé avec 382 photos. Ces dernières ont été assemblées à une cadence de 25 images par secondes. Chaque image a été prise en mode automatique sur un Canon EOS 550D avec un intervalle de 10 secondes entre chaque prise de vue.

En espérant que tout ceci vous inspire !

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 :)