Publié le 02/09/2005 Dans Linux
1. Considérations générales su...
2. Application pratique
3. Installation sous linux
4. Installation sous Windows
5. Affichage de l'état de l'UPS ...
6. » Configuration avancée
7. Conclusion
2. Application pratique
3. Installation sous linux
4. Installation sous Windows
5. Affichage de l'état de l'UPS ...
6. » Configuration avancée
7. Conclusion
Configuration avancée
6.1. Evénements et actions personnaliséesNUT nous laisse la possibilité de paramétrer des actions personnalisées en fonction de certains états de l'UPS. Ceci est utile par exemple pour délencher un shutdown propre immédiatement, sans attendre que la batterie soit presque vide, mais aussi pour envoyer un mail d'avertissement à l'administrateur.
Pour cela, nous devons reprendre le fichier /etc/nut/upsmon.conf et le compléter par quelques options :
# define the ups to monitor and the permissions
MONITOR myups@localhost 1 user mypassword master
# define the shutdown comand
SHUTDOWNCMD "/sbin/shutdown -h now"
# specify the script to execute on event
NOTIFYCMD /root/upsalert
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
MONITOR myups@localhost 1 user mypassword master
# define the shutdown comand
SHUTDOWNCMD "/sbin/shutdown -h now"
# specify the script to execute on event
NOTIFYCMD /root/upsalert
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
Le paramètre "NOTIFYCMD" spécifie un fichier exécutable que l'utilisateur doit créer lui-même (ici un script shell : /root/upsalert) qui sera lancé lorsqu'un événement se produira, tandis que le paramètre "NOTIFYFLAG" définit quel(s) état(s) de l'UPS déclencheront une action personnalisée. Ici il s'agit de l'état "ONBATT" qui correspond au moment où l'UPS se met sur batterie. Les commandes suivantes indiquent les actions à exécuter : SYSLOG écrit une trace de l'événement dans les logs système, WALL envoit un message d'alerte à tous les utilisateurs connectés, et EXEC lance l'exécution du programme spécifié plus haut.
Le code que nous désirons voir exécuter est le suivant (/root/upsalert) :
#!/bin/sh
# send mail to admin
echo "Power is lost, UPS is shutting down servers." | mail -s "UPS ALERT" admin@myserver.com
# write to a specific log file
date=$(date +"%F %T")
echo "$date >> UPS ALERT, shutting down in a few seconds..." >> /var/log/ups.log
# actually send the shutdown signal to master (will broadcast to all slaves)
/sbin/upsmon -c fsd
# send mail to admin
echo "Power is lost, UPS is shutting down servers." | mail -s "UPS ALERT" admin@myserver.com
# write to a specific log file
date=$(date +"%F %T")
echo "$date >> UPS ALERT, shutting down in a few seconds..." >> /var/log/ups.log
# actually send the shutdown signal to master (will broadcast to all slaves)
/sbin/upsmon -c fsd
N'oubliez pas de donner la permission exécutable au script (chmod 755).
A noter que si on veut gérer plusieurs événements, un seul script est autorisé, et il faudra donc un moyen pour détecter le type d'événement à traiter. Pour cela NUT définit un paramètre qui est envoyé au script ($*). Pour plus de détails, je vous renvoie à la documentation officielle, n'ayant pas jugé utile d'employer cette option dans mon cas de figure.
Pour tester notre script, nous ne pouvons évidemment plus simuler une panne par la commande upsmon -c fsd, puisque celle-ci ne change pas l'état de l'UPS, nous n'avons donc d'autre choix que de déconnecter la fiche électrique. Il s'en suit évidemment un shutdown immédiat qui correspond à la dernière instruction du script, et au redémarrage de la machine nous pourrons constater qu'effectivement le mail a bien été envoyé, et qu'il y a une trace dans /var/log/ups.log.
6.2. Actions différées
C'est bien de pouvoir éteindre le serveur avant la décharge de la batterie... mais le faire immédiatement c'est un peu trop tôt ! Idéalement il faudrait réagir seulement si la panne se prolonge pendant un certain laps de temps, par exemple 20 minutes... Heureusement, NUT autorise cette possibilité.
Nous devons encore une fois reprendre le fichier de configuration /etc/nut/upsmon.conf :
# define the ups to monitor and the permissions
MONITOR myups@localhost 1 user mypassword master
# define the shutdown comand
SHUTDOWNCMD "/sbin/shutdown -h now"
# launch the upssched program to execute script with delay
NOTIFYCMD /sbin/upssched
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
MONITOR myups@localhost 1 user mypassword master
# define the shutdown comand
SHUTDOWNCMD "/sbin/shutdown -h now"
# launch the upssched program to execute script with delay
NOTIFYCMD /sbin/upssched
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
Cette fois, au lieu d'indiquer notre script à exécuter, on met le programme "upssched". C'est un utilitaire qui a été ajouté au package de NUT pour gérer l'exécution de scripts en différé. Attention aux flags NOTIFY ! Il est impératif d'ajouter l'événement ONLINE, pour annuler le compte à rebours dès que le courant revient et prévenir le déclenchement du script qui aurait provoqué une extinction des machines alors que ce n'est plus nécessaire (expérience vécue... ).
Pour paramétrer le timing, il faut ajouter un fichier de configuration spécifique /etc/nut/upssched.conf :
# the script to be executed
CMDSCRIPT /root/upsalert
# mandatory fields that must be set before AT commands
PIPEFN /var/run/upssched/upssched.pipe
LOCKFN /var/run/upssched/upssched.lock
# the timers, here 30 sec after the ONBATT (ups on battery) event
AT ONBATT * START-TIMER onbatt 30
# cancel the countdown is power is back
AT ONLINE * CANCEL-TIMER onbatt
CMDSCRIPT /root/upsalert
# mandatory fields that must be set before AT commands
PIPEFN /var/run/upssched/upssched.pipe
LOCKFN /var/run/upssched/upssched.lock
# the timers, here 30 sec after the ONBATT (ups on battery) event
AT ONBATT * START-TIMER onbatt 30
# cancel the countdown is power is back
AT ONLINE * CANCEL-TIMER onbatt
CMDSCRIPT indique le script à exécuter, le même que tout à l'heure.
Les 2 paramètres suivants sont extrêmement importants, sans quoi ça ne marchera jamais. Durant son exécution, upssched a absolument besoin d'écrire temporairement quelques données sur fichier, mais il faut lui spécifier où il peut le faire et régler les permissions appropriées. Suivant les conseils de la documentation, on va lui créer un répertoire dédié /var/run/upssched qu'on devra léguer au groupe "nut" (chown nut.nut pour l'utilisateur et le groupe, pour être sûr) et lui donner l'accès en écriture (chmod 775). Lors de l'installation de NUT, Debian a créé un utilisateur "nut" membre du groupe "nut" : c'est sous cette idendité que sera exécuté upssched.
On indique ensuite le timing sur l'événement ONBATT, * désigne tous les UPS géré par NUT, START-TIMER pour dire que le compte à rebours commence, "onbatt" désigne ici le nom du timer (car il peut y avoir plusieurs événéments à des timings différents, donc il faut un nom pour les différencier), et enfin le chiffre 30 est le timeout en secondes, c'est-à -dire le délai au bout duquel le script sera exécuté.
Mais une exécution différée amène un autre problème : que faire s'il y a un changement d'état pendant le délai ? C'est l'objet de la dernière ligne de configuration qui dit d'annuler le compte à rebours (CANCEL-TIMER onbatt) si l'événement ONLINE survient, c'est-à -dire si le courant est revenu entretemps.
Testons cela ! A nouveau pas moyen de faire autrement que de débrancher l'UPS, mais dès que vous l'avez fait scrutez votre montre : dans 30 secondes environ (suivant l'intervalle de monitoring du démon) l'ordinateur va s'éteindre.
Preuve dans les logs système qui nous indique clairement et à la seconde près le suivi des opérations :
Sep 23 18:20:28 srvtest upsmon[1270]: UPS myups@localhost on battery
Sep 23 18:20:28 srvtest upssched[1276]: Timer daemon started
Sep 23 18:20:29 srvtest upssched[1276]: New timer: onbatt (30 seconds)
Sep 23 18:20:59 srvtest upssched[1276]: Event: onbatt
Sep 23 18:20:59 srvtest upsmon[1270]: Signal 10: User requested FSD
Sep 23 18:20:59 srvtest upsd[1267]: Setting FSD on UPS [myups]
Sep 23 18:21:08 srvtest upsd[1267]: Host 192.168.1.4 disconnected (read failure)
Sep 23 18:21:08 srvtest upsmon[1270]: Executing automatic power-fail shutdown
Sep 23 18:21:08 srvtest upsmon[1270]: Auto logout and shutdown proceeding
Sep 23 18:21:14 srvtest upssched[1276]: Timer queue empty, exiting
Sep 23 18:21:14 srvtest upsd[1267]: Host 127.0.0.1 disconnected (read failure)
Sep 23 18:21:20 srvtest upsd[1267]: Signal 15: exiting
Sep 23 18:21:20 srvtest hidups[1265]: Signal 15: exiting
Sep 23 18:20:28 srvtest upssched[1276]: Timer daemon started
Sep 23 18:20:29 srvtest upssched[1276]: New timer: onbatt (30 seconds)
Sep 23 18:20:59 srvtest upssched[1276]: Event: onbatt
Sep 23 18:20:59 srvtest upsmon[1270]: Signal 10: User requested FSD
Sep 23 18:20:59 srvtest upsd[1267]: Setting FSD on UPS [myups]
Sep 23 18:21:08 srvtest upsd[1267]: Host 192.168.1.4 disconnected (read failure)
Sep 23 18:21:08 srvtest upsmon[1270]: Executing automatic power-fail shutdown
Sep 23 18:21:08 srvtest upsmon[1270]: Auto logout and shutdown proceeding
Sep 23 18:21:14 srvtest upssched[1276]: Timer queue empty, exiting
Sep 23 18:21:14 srvtest upsd[1267]: Host 127.0.0.1 disconnected (read failure)
Sep 23 18:21:20 srvtest upsd[1267]: Signal 15: exiting
Sep 23 18:21:20 srvtest hidups[1265]: Signal 15: exiting
A 18:20:29 le compte à rebours commence, et à 18:20:59 précisément le timer déclenche l'action prévue. Evidemment en utilisation réelle vous pouvez augmenter ce délai ! 15 à 20 minutes sont très bien.
6.3. Hacking
Ce tutoriel aurait pu s'arrêter là ... Mais je voulais vous faire part de l'expérience que j'ai faite avant de découvrir toutes les possibilités de NUT. En fait je cherchais à déclencher un shutdown différé sans attendre que les batteries de l'UPS soient vides. Je pensais que cette option devait se régler dans les paramètres de driver, puis j'ai abandonné et j'ai décidé d'étudier le protocole réseau d'upsmon, qui est décrit dans la documentation. On y voit que les communications se font sur le port TCP 3493 et on trouve notamment la commande suivante : FSD upsname où il faut donc remplacer "upsname" par le nom de l'UPS tel qu'il a été configuré dans upsmon.conf. Grâce au fabuleux programme netcat qui permet d'envoyer n'importe quelles données sur n'importe quel port réseau sur une adresse IP au choix, j'envois cette commande sur l'adresse IP de mon serveur master. Malheureusement ça ne marche pas du premier coup : je reçois un message d'erreur comme quoi je dois d'abord définir le nom d'utilisateur. En gros il ne me reconnaît pas car je ne suis pas loggé. Une lecture plus attentive de la doc me révèle les commandes à utiliser, que j'inscris dans un fichier texte (que je choisis d'appeler ups.cmd) :
USERNAME myuser
PASSWORD mypassword
FSD myups
LOGOUT
PASSWORD mypassword
FSD myups
LOGOUT
J'envois ensuite ces instructions au démon upsmon du serveur par la commande suivante tapée en console (shell) :
cat ups.cmd | nc 192.168.1.5 3493
Et je suis très heureux de constater que ça marche : NUT déclenche un shutdown immédiatement et éteint toutes mes machines ! En fait je viens d'exécuter la commande upsmon -c fsd sans la connaître !
Il est également possible de recevoir la liste des variables d'état de l'UPS, de la même manière que ce que produit la commande upsc myups@localhost, ce qui montre de manière très simple comment réaliser un client NUT. Pour cela, mettez les commandes suivantes dans ups.cmd :
USERNAME myuser
PASSWORD mypassword
LIST VAR myups
LOGOUT
PASSWORD mypassword
LIST VAR myups
LOGOUT
On obtient le résultat suivant :
ovh@server:~$ cat ups.cmd | nc localhost 3493
OK
OK
BEGIN LIST VAR myups
VAR myups battery.charge "100"
VAR myups battery.chemistry "PbAc"
VAR myups battery.runtime "1290"
VAR myups battery.voltage "27.8"
VAR myups driver.name "hidups"
VAR myups driver.parameter.port "/dev/usb/hiddev0"
VAR myups driver.version "2.0.1"
VAR myups ups.delay.shutdown "-1"
VAR myups ups.delay.start "0"
VAR myups ups.load "380"
VAR myups ups.mfr "American Power Conversion"
VAR myups ups.model "Back-UPS BR 800 FW:9.o2 .I USB FW:o2 "
VAR myups ups.serial "QB0406247589 "
VAR myups ups.status "OL"
END LIST VAR myups
OK Goodbye
OK
OK
BEGIN LIST VAR myups
VAR myups battery.charge "100"
VAR myups battery.chemistry "PbAc"
VAR myups battery.runtime "1290"
VAR myups battery.voltage "27.8"
VAR myups driver.name "hidups"
VAR myups driver.parameter.port "/dev/usb/hiddev0"
VAR myups driver.version "2.0.1"
VAR myups ups.delay.shutdown "-1"
VAR myups ups.delay.start "0"
VAR myups ups.load "380"
VAR myups ups.mfr "American Power Conversion"
VAR myups ups.model "Back-UPS BR 800 FW:9.o2 .I USB FW:o2 "
VAR myups ups.serial "QB0406247589 "
VAR myups ups.status "OL"
END LIST VAR myups
OK Goodbye
Ceci démontre la puissance des logiciels open source, qui peuvent être modifiés et adaptés à volonté.