Vous êtes peut-être comme moi qui, bien qu'ayant un onduleur MGE, suit dans l'impossibilité d'utiliser le logiciel Personal Solution Pac pour de sombres histoires d'architecture et de dépendances qui ne sont jamais résolues.
J'ai donc pris mon courage à deux mains une bonne fois pour toutes et me suis penché sur la configuration manuelle de NUT.
Et comme je ne voulais pas avoir à tout retrouver en cas de réinstallation, je note tout ici-même.
Tous les fichiers de configuration et leurs chemins correspondent à une distribution sur base RedHat (RHEL, CentOS, Fedora). Il faut certainement adapter pour une Debian-based.
Tout d'abord, il faut bien évidemment installer NUT (Network UPS Tools) et son client. Dans un terminal en root, un simple
# yum install nut nut-client
fera l'affaire.
Pas besoin de faire appel à des dépôts tiers, c'est accessible dans les dépôts de base.
L'avantage de cette méthode c'est que le groupe et l'utilisateur spécifique sont automatiquement créés, ainsi que le "service" et les fichiers de configuration.
Reste qu'il va falloir un peu travailler sur ceux-ci pour que ça fonctionne.
Étape 1 : les fichiers de configuration
On a de la chance, ils sont tous au même endroit : dans /etc/ups/
Commençons par ups.conf, le fichier qui va décrire votre onduleur.
[ellipse] driver = usbhid-ups port = auto desc = "MGE 600 USBS"
Quelques explications :
- ellipse est le petit nom que j'ai décidé de donner à mon onduleur
- usbhid-ups est le nom du driver pour les onduleurs MGE en USB
- auto pour le port, toujours à cause de l'USB
- desc, euh c'est une description, c'est tout
Ensuite, le fichier de configuration du démon : upsd.conf
ACL all 0.0.0.0/0 ACL localhost 127.0.0.1/32 ACL reseau 192.168.0.0/24 ACCEPT reseau ACCEPT localhost REJECT all MAXAGE 25
Grosso modo, on autorise l'accès uniquement à partir de l'hôte et du réseau local.
L'option MAXAGE est là pour prévenir un bug récurrent sur certains onduleur MGE Ellipse en USB.
Maintenant, les utilisateurs autorisés à accéder au démon, dans upsd.users :
# Network UPS Tools: Example upsd.users [admin] password = GrandMaitre allowfrom = localhost reseau actions = SET instcmds = ALL # # # --- Configuring for upsmon # # To add a user for your upsmon, use this example: # [fedups] password = votre_mdp allowfrom = localhost reseau upsmon master
En premier, l'utilisateur qui aura le pouvoir de gérer l'onduleur. À utiliser pour passer des valeurs à l'onduleur ou directement des commandes. Personnellement je ne m'en sers quasiment jamais.
Le deuxième est celui que va utiliser le moniteur upsmon. J'ai fait très original pour le choix du nom : fedups pour fedora et ups, à vous de trouver mieux. Notez bien le mot de passe, il faudra le renseigner plus loin.
Arrivé ici on a un service qui va dialoguer avec notre onduleur ... et c'est tout, rien ne se produira. Ça c'est le rôle de la suite.
Surveillons, surveillons ou le fichier de configuration upsmon.conf
# Network UPS Tools: example upsmon configuration # # This file contains passwords, so keep it secure. # -------------------------------------------------------------------------- RUN_AS_USER nut # -------------------------------------------------------------------------- MONITOR ellipse@localhost 1 fedups votre_mdp master MINSUPPLIES 1 SHUTDOWNCMD "/sbin/shutdown -h +0" # -------------------------------------------------------------------------- # NOTIFYCMD <command> # # upsmon calls this to send messages when things happen # # This command is called with the full text of the message as one argument. # The environment string NOTIFYTYPE will contain the type string of # whatever caused this event to happen. # # Note that this is only called for NOTIFY events that have EXEC set with # NOTIFYFLAG. See NOTIFYFLAG below for more details. # # Making this some sort of shell script might not be a bad idea. For more # information and ideas, see pager.txt in the docs directory. # # Example: NOTIFYCMD /usr/sbin/upssched POLLFREQ 5 POLLFREQALERT 5 HOSTSYNC 15 DEADTIME 15 POWERDOWNFLAG /etc/killpower # -------------------------------------------------------------------------- # NOTIFYMSG - change messages sent by upsmon when certain events occur # # You can change the default messages to something else if you like. # # NOTIFYMSG <notify type> "message" # NOTIFYMSG ONLINE "UPS %s on line power" NOTIFYMSG ONBATT "UPS %s on battery" NOTIFYMSG LOWBATT "UPS %s battery is low" NOTIFYMSG FSD "UPS %s: forced shutdown in progress" NOTIFYMSG COMMOK "Communications with UPS %s established" NOTIFYMSG COMMBAD "Communications with UPS %s lost" NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding" NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced" NOTIFYMSG NOCOMM "UPS %s is unavailable" NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible" # # Note that %s is replaced with the identifier of the UPS in question. # # Possible values for <notify type>: # # ONLINE : UPS is back online # ONBATT : UPS is on battery # LOWBATT : UPS has a low battery (if also on battery, it's "critical") # FSD : UPS is being shutdown by the master (FSD = "Forced Shutdown") # COMMOK : Communications established with the UPS # COMMBAD : Communications lost to the UPS # SHUTDOWN : The system is being shutdown # REPLBATT : The UPS battery is bad and needs to be replaced # NOCOMM : A UPS is unavailable (can't be contacted for monitoring) # NOPARENT : The process that shuts down the system has died (shutdown impossible) # -------------------------------------------------------------------------- # NOTIFYFLAG - change behavior of upsmon when NOTIFY events occur # # By default, upsmon sends walls (global messages to all logged in users) # and writes to the syslog when things happen. You can change this. # # NOTIFYFLAG <notify type> <flag>[+<flag>][+<flag>] ... # NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC # NOTIFYFLAG FSD SYSLOG+WALL NOTIFYFLAG COMMOK SYSLOG+WALL NOTIFYFLAG COMMBAD SYSLOG+WALL NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC NOTIFYFLAG REPLBATT SYSLOG+WALL # NOTIFYFLAG NOCOMM SYSLOG+WALL # NOTIFYFLAG NOPARENT SYSLOG+WALL # # Possible values for the flags: # # SYSLOG - Write the message in the syslog # WALL - Write the message to all users on the system # EXEC - Execute NOTIFYCMD (see above) with the message # IGNORE - Don't do anything # # If you use IGNORE, don't use any other flags on the same line. RBWARNTIME 43200 NOCOMMWARNTIME 300 FINALDELAY 5
Dans l'ordre, on indique à upsmon de tourner en tant qu'utilisateur nut (il est créé par défaut). Ensuite, on indique le ou les onduleurs à surveiller (ligne MONITOR). Vous noterez la relation avec le fichier précédent.
Le fichier est commenté, je passe donc sur le reste. Une petite exception sur le NOTIFYFLAG : Tout ce qui est noté EXEC provoquera une action configurable autre qu'un simple avertissement ou log. C'est donc là que tout se tiendra.
Le dernier fichier de configuration : upssched.conf
Vous avez peut-être noté la ligne :
NOTIFYCMD /usr/sbin/upssched
dans le fichier précédent. C'est ce script qui va déclencher tout le reste et le fichier upssched.conf est ... son fichier de configuration !
# Network UPS Tools - upssched.conf sample file CMDSCRIPT /opt/bin/upssched-cmd PIPEFN /var/run/nut/upssched/upssched.pipe LOCKFN /var/run/nut/upssched/upssched.lock # ============================================================================ # # AT <notifytype> <upsname> <command> # # Define a handler for a specific event <notifytype> on UPS <upsname>. # # <upsname> can be the special value * to apply this handler to every # possible value of <upsname>. # # Run the command <command> via your CMDSCRIPT when it happens. # # Note that any AT that matches both the <notifytype> and the <upsname> # for the current event will be used. # ----------------------------------------------------------------------- # # - EXECUTE <command> # # Immediately pass <command> as an argument to CMDSCRIPT. # # Example: # If any UPS (*) reverts to utility power, then execute # 'ups-back-on-line' via CMDSCRIPT. # # AT ONLINE * EXECUTE ups-back-on-line AT ONBATT * EXECUTE ups-on-battery AT ONLINE * EXECUTE ups-back-on-line
CMDSCRIPT indique l'emplacement du script qui va être appelé et auquel on va passer les arguments command. Personnellement, j'utilise une version modifiée du script généré par MGE OPS (euh pardon, Personal Solution Pac).
J'ai laissé les commentaires sur AT et EXECUTE, le fichier est entièrement commenté à la base. Pas besoin de déclarer une action pour l'extinction, cela a été fait dans le fichier précédent (SHUTDOWNCMD). Dans mon cas, upsmon va passer le relais à upssched à deux occasions :
- l'onduleur est en ligne donc branché (ONLINE)
- l'onduleur est sur batterie donc le secteur a mystérieusement disparu (ONBATT)
Et upssched va passer le relais au script défini dans CMDSCRIPT.
Autrement dit, on a un démon qui tourne en arrière plan et qui gère la communication avec l'onduleur via l'interface et le port décrit dans ups.conf. Ce démon peut être écouté par les utilisateurs défini dans upsd.users et les hôtes définis dans upsd.conf.
Ensuite, on fait tourner le programme de monitoring upsmon qui va passer le relais au script /usr/bin/upssched pour la gestion des évènements. Ce dernier va ensuite faire intervenir le script défini dans CMDSCRIPT pour réaliser des actions ou autre.
Qui a dit qu'on aurait pu faire plus simple ?
Attendez, c'est pas fini !!!
Étape 2 : Traitons tout ça
C'est le rôle du script /opt/bin/upssched-cmd basé sur celui de MGE OPS PSP. Je vous livre celui-ci tel quel avec des essais de notification commentés qui ne marchent pas mais ça me sert de pense-bête.
#!/bin/bash ######################################################## # Generated by MGE UPS SYSTEMS - Personal Solution Pac # # Support script for NUT - upssched utility # ######################################################## # release: 0.1 # ######################################################## # Determine the various paths if [ -d /etc/nut ] then sysConfPath="/etc/nut/" else if [ -d /etc/ups/ ] then sysConfPath="/etc/ups/" fi fi if [ -d /var/run/nut/ ] then statePath="/var/run/nut/" else if [ -d /var/state/ups/ ] then statePath="/var/state/ups/" else if [ -d /var/lib/ups/ ] then statePath="/var/lib/ups/" fi fi fi if [ -f /usr/sbin/upsmon ] then binPath="/usr/bin/" sbinPath="/usr/sbin/" else if [ -f /sbin/upsmon ] then binPath="/bin/" sbinPath="/sbin/" fi fi # Source the wizard.conf file to obtain # specific configuration (ie shutdown criteria/config) if [ -f ${sysConfPath}wizard.conf ] then . ${sysConfPath}wizard.conf else shutdownBatteryLevel=30 shutdownBatteryRuntime=-1 fi # Internal constants False="0" True="1" Ups="ellipse@localhost" case $1 in # Handles shutdown timer criteria (when triggered, # timer has expired, so immediately shutdown) ups-on-battery-timer) logger -t upssched-cmd "Shutdown timer reached: Calling upsmon -c fsd" ${sbinPath}upsmon -c fsd ;; # Handles shutdown criteria based on battery runtime or charge ups-on-battery) sd_batt_level=`expr $shutdownBatteryLevel "!=" -1` sd_batt_runtime=`expr $shutdownBatteryRuntime "!=" -1` #Affiche la perte du secteur sur l'écran #/usr/bin/notify-send -u critical -i /usr/share/icons/ellipsemax.png Onduleur "Perte du secteur" # Envoie un SMS pour information /usr/bin/php /opt/bin/sms.php "Onduleur" "Perte du Secteur" if [ $sd_batt_level == $False ] && [ $sd_batt_runtime == $False ] then echo "No criteria enabled, exiting" exit 0 else while(true) do # Test if we are still needed ups_online="`${binPath}upsc $Ups ups.status | grep OL`" if [ -n "$ups_online" ] then #Affiche le retour du secteur sur l'écran #/usr/bin/notify-send -u critical -i /usr/share/icons/ellipsemax.png Onduleur "Retour du secteur" # Envoie un SMS pour information /usr/bin/php /opt/bin/sms.php "Onduleur" "Retour Secteur" logger -t upssched-cmd "UPS is back online. Aborting..." exit 0 else # Processing criteria "battery charge" if [ $sd_batt_level == $True ] then # Retrieve and compare current battery charge battCharge=`eval '${binPath}upsc $Ups battery.charge'` # And compare it with the criteria if [ `expr $battCharge "<=" $shutdownBatteryLevel` == $True ] then #Affiche l'arrêt pour niveau batterie atteint sur l'écran #/usr/bin/notify-send -u critical -i /usr/share/icons/ellipsemax.png Onduleur "Niveau de Batterie restant atteint : On ferme" # Envoie un SMS pour information /usr/bin/php /opt/bin/sms.php "Onduleur" "Arrêt : Niveau Batterie atteint" logger -t upssched-cmd "BatteryLevel reached ($shutdownBatteryLevel %): Calling upsmon -c fsd" ${sbinPath}upsmon -c fsd fi fi # "battery charge" criteria # Processing criteria "battery runtime" if [ $sd_batt_runtime == $True ] then # Retrieve current remaining runtime remRuntime=`eval '${binPath}upsc $Ups battery.runtime'` # And compare it with the criteria if [ `expr $remRuntime "<=" $shutdownBatteryRuntime` == $True ] then #Affiche l'arrêt pour temps de batterie restant atteint sur l'écran #/usr/bin/notify-send -u critical -i /usr/share/icons/ellipsemax.png Onduleur "Temps de Batterie restant atteint : On ferme" # Envoie un SMS pour information /usr/bin/php /opt/bin/sms.php "Onduleur" "Arrêt : Temps Batterie atteint" logger -t upssched-cmd "BatteryRuntime reached ($shutdownBatteryRuntime s): calling upsmon -c fsd" ${sbinPath}upsmon -c fsd fi fi # "battery runtime" criteria fi # ... still needed # wait 5 seconds before continuing the loop sleep 5 done fi ;; commbad) #Affiche la perte de communication sur l'écran #/usr/bin/notify-send -u low -i /usr/share/icons/ellipsemax.png Onduleur "Perte de la communication avec l'onduleur" ;; commok) #Affiche le retour de communication sur l'écran #/usr/bin/notify-send -u low -i /usr/share/icons/ellipsemax.png Onduleur "Retour de la communication avec l'onduleur" ;; ups-back-on-line) #Affiche le retour du secteur sur l'écran #/usr/bin/notify-send -u critical -i /usr/share/icons/ellipsemax.png Onduleur "Retour du secteur" # Envoie un SMS pour information /usr/bin/php /opt/bin/sms.php "Onduleur" "Retour Secteur" # Remove possible timers /bin/rm -f ${statePath}ups-on-battery /bin/rm -f ${statePath}ups-on-battery-timer ;; *) logger -t upssched-cmd "Unrecognized command: $1" ;; esac
Le fichier wizard.conf généré par MGE OPS PSP n'existe pas dans mon cas, j'ai donc codé en dur les valeurs qui m'intéressent :
shutdownBatteryLevel=30, l'onduleur provoquera l'extinction du PC en arrivant à moins de 30% de batterie restante
shutdownBatteryRuntime=-1, pas de condition sur le temps de maintien de tension sous batterie
Ups="ellipse@localhost", on retrouve le petit nom de mon onduleur
Pour le reste, il suffit de spécifier la ou les commandes que l'on veut exécuter pour chaque cas. En pratique, hors mes essais de notification via notify-send qui foirent, je me contente d'exécuter un script PHP qui envoie un SMS sur mon portable me décrivant ce qui se passe.
Je reviendrai sur la procédure utilisée dans un futur billet.
Et comme je souhaite aussi être prévenu du redémarrage de mon ordinateur s'il a été arrêté et que le courant revient (il est configuré pour redémarrer suite à une coupure de l'alimentation dans le BIOS), j'ai aussi inclus la ligne suivante dans le fichier /etc/rc.d/rc.local :
/usr/bin/php /opt/bin/sms.php "Ordinateur" "Démarrage terminé"
Tout ça a l'air très lourd pour gérer un simple onduleur mais cela prend tout son sens lorsqu'il s'agit de gérer très finement de nombreux modules.
Commentaires