Gestionando un SAI desde OpenBSD con NUT
Historia
3 Agosto 2005: primera versión pública
Índice
- Introducción
- Instalación de NUT
- Apagado del SAI
- Trabajando con upssched
- Despedida
Introducción
Este documento es una pequeña receta para configurar un SAI
PowerMust 600
Plus en
OpenBSD empleando
NUT.
En primer lugar hay que quitar de /etc/boot.conf
la linea que permite ver el
arranque en el puerto serie (si existe), así como la posible configuración en
/etc/ttys
que nos da una terminal serie, sino no podremos controlar el SAI
desde ahí. Esto es habitual en servidores sin teclado ni monitor, así que
cuidado.
En caso de tener alguna configuración de las descritas, reiniciamos el
servidor para poder usar el interfaz por el puerto RS-232
con el protocolo
smart APC (según la
documentacuión), sin que interfiera la configuración anterior, y nos ponemos a
mirar las opciones que tenemos en OpenBSD.
Instalación de NUT
El SAI
es un YUKAI PowerMust 600 Plus
(600VA/360W), una opción económica y
suficiente para mis necesidades. En realidad hice una mala compra, porque no
comprobé compatibilidades :(. Menos mal que ha habido algo de suerte (poca).
En los ports (OpenBSD 3.6) tenemos upsd
, apc-upsd
y
NUT. Todos productos soportan el procotolo
que emplea el SAI
(aparentemente), aunque solo he encontrado una página web
actualizada para NUT
, y además resulta que los fabricantes introducen
variaciones en el protocolo… así que necesitamos un manejador específico.
Como NUT
soporta mi SAI
con la versión 2.0.1 y posteriores (con el driver
para PowerMust 600VA
Plus), pero en los
ports
está una versión vieja, me toca actualizar el port a mano o aplicar
el parche para mi versión de NUT
. He elegido esta segunda opción.
# export CVSROOT=anoncvs@anoncvs3.usa.openbsd.org:/cvs
# export CVS_RSH=/usr/bin/ssh
# cd /usr
# mkdir -p ports/sysutils
# cvs -z -q get -rOPENBSD_3_6 ports/sysutils/nut
cvs server: Updating ports/sysutils/nut
...
# cd ports/sysutils/nut/
# wget http://students.fct.unl.pt/~cer09566/nut/files/nut-1.4.2-powermust0.9.patch
# FLAVOR=no_cgi make patch
...
# cd w-nut-1.4.1-no_cgi/nut-1.4.1/
# patch -p1 < ../../nut-1.4.2-powermust0.9.patch
...
# cd ../..
(editamos pkg/PLIST y añadimos bin/powermust detrás de bin/powercom)
# FLAVOR=no_cgi make package
...
He resumido la salida de los distintos comandos, espero que aún así sea claro :P.
Al instalar el paquete nos indica que ha creado el usuario _nut
, dónde ha
dejado los ficheros de configuración (en /etc/nut/
) y un ejemplo para poner
el arranque en /etc/rc.local
.
Configuración de NUT
Ahora voy a describir los pasos habituales para configurar NUT
.
Necesitamos iniciar el manejador del SAI
, el demonio que obtiene la
información del manejador, y un monitor que realize acciones cuando haga falta
(nos quedamos sin batería).
Editamos /etc/nut/ups.conf
y ponemos los datos del SAI
:
[bsups]
driver=powermust
port=/dev/tty00
desc="Blackshell"
Comprobamos que el SAI
se detecta correctamente:
# upsdrvctl -u _ups start
Network UPS Tools - UPS driver controller 1.4.1
Network UPS Tools - Mustek PowerMust UPS driver 0.9 (1.4.1)
Carlos Rodrigues (c) 2003, 2004
Serial port read timed out
Serial port read ok again
Mustek PowerMust UPS detected.
Echamos un vistazo /etc/nut/upsd.conf
, aunque por defecto solo permite el
acceso a localhost
así que en un principio no hace falta tocar nada.
Añadimos un usuario a /etc/nut/upsd.users
para posterior uso con upsmon
:
[muser]
password=pass
allowfrom=localhost
upsmon master
Preparamos los ficheros de configuración para el usuario que correrá upsd
(en el port tiene el grupo dialer
), y arrancamos el demonio:
# chown root:dialer /etc/nut/upsd.conf /etc/nut/upsd.users
# chmod 640 /etc/nut/upsd.conf /etc/nut/upsd.users
# upsd -u _ups
Network UPS Tools upsd 1.4.1
Connected to UPS [bsups]: powermust-cua00
Synchronizing...done
Ahora ya podemos empezar a hacer preguntas:
# upsc bsups@localhost
battery.charge: 100.0
battery.voltage: 13.8
battery.voltage.nominal: 12.0
driver.name: powermust
driver.parameter.port: /dev/cua00
driver.version: 1.4.1
driver.version.internal: 0.9
input.voltage: 230.5
input.voltage.fault: 230.0
input.voltage.maximum: 232.5
input.voltage.minimum: 223.0
output.frequency: 49.7
output.voltage: 230.5
output.voltage.target.battery: 230.0
ups.delay.shutdown: 2
ups.delay.start: 3
ups.load: 4.0
ups.mfr: Mustek
ups.model: PowerMust
ups.status: OL
Perfecto. Esta información es útil, pero lo que estoy buscando es que el
servidor se apague cuando el SAI
se quede sin baterias. Para eso necesitamos
upsmon
.
Su configuración está en /etc/nut/upsmon.conf
y tendremos que añadir una
linea para nuestro SAI
:
MONITOR bsups@localhost 1 muser pass master
El resto se puede quedar por defecto, destacando SHUTDOWNCMD
para indicar
qué comando ejecutar para detener la máquina (sin apagarla, de eso se debe
encargar el SAI
, cuidado con no tener activado powerdown
en nuestro
/etc/rc.shutdown
) .
En este punto es interesante configurar algunas notificaciones, para que se nos avise de los eventos más importantes.
Ponemos en /etc/nut/upsmon.conf
la variable NOTIFYCMD
a
/usr/local/bin/upsnotify
. Creamos un script tal que:
#!/bin/sh
# recordar hacer chmod +x
echo ${NOTIFYTYPE}: $* | mail -s "$UPSNAME NUT Notify" reidrac
Añadimos a /etc/nut/upsmon.conf
las notificaciones que creamos convenientes
e indicamos vía NOTIFYFLAG
cómo deben informarnos:
NOTIFYMSG ONBATT "%s is on battery"
NOTIFYMSG ONLINE "%s is back online"
NOTIFYMSG LOWBATT "%s has a low battery!"
NOTIFYMSG SHUTDOWN "System is being shutdown!"
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG ONLINE SYSLOG
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
Aseguramos el fichero de configuración y arrancamos upsmon
:
# chown root:dialer /etc/nut/upsmon.conf
# chmod 640 /etc/nut/upsmon.conf
# upsmon -u _ups
Network UPS Tools upsmon 1.4.1
Using power down flag file /etc/killpower
UPS: bsups@localhost (master) (power value 1)
Ahora actualizo mi /etc/rc.local
como sigue:
...
# nut
if [ X"${nut_ups}" != X"NO" ]; then
echo -n " nut"
# dentro del arranque de nut
# para que funcione upssched
# y para que pueda escribir upsmon
mkdir -p /var/run/ups
chown _ups:dialer /var/run/ups
/usr/local/bin/upsdrvctl -u _ups start > /dev/null
/usr/local/sbin/upsd -i 127.0.0.1 -u _ups > /dev/null 2>&1
/usr/local/sbin/upsmon -u _ups > /dev/null 2>&1
fi
...
Y activo NUT
en /etc/rc.conf.local
con nut_ups=""
(con “NO” lo
desactivaríamos).
Apagado del SAI
Desde la documentación se recomienda que añadamos al final de
/etc/rc.shutdown
algo como:
# OJO: POWERDOWNFLAG en upsmon.conf indica el fichero a comprobar
if [ -f /etc/killpower ]; then
echo "Killing the power, bye!"
/usr/local/bin/upsdrvctl shutdown
fi
De esta forma es nuestra máquina la que indica al SAI
que debe cortar la
corriente. Cuando vuelva la energía, el SAI
despertará y arrancará el
servidor.
Hay que tener en cuenta que nuestro SAI
no espera a que acabe de cerrarse el
sistema, y /etc/rc.shutdown
se ejecuta con todos los discos montados
normalmente y todos los procesos funcionando. Apagar así no es nada saludable.
No hay una solución fácil a este problema. Mi propuesta: sincronizamos el disco y montamos todo lo necesario en modo solo lectura.
Además hay que hacer una pequeña adaptación para que funcione el script con nuestro usuario sin privilegios, incluyendo también un hack para que el shutdown funcione. El script quedaría:
# OJO: POWERDOWNFLAG debe ser /var/run/ups/killpower
if [ -f /var/run/ups/killpower ]; then
echo "Killing the power, bye!"
# sino paramos la instancia en funcionamiento
# no podemos hacer shutdown
/usr/local/bin/upsdrvctl stop
sleep 3
# estabilizamos el disco (cuidado si hay más particiones)
/bin/sync
/sbin/umount -a
/sbin/mount -r /
/sbin/mount -r /var
/sbin/mount -r /tmp
/sbin/mount -r /usr
/usr/local/bin/upsdrvctl shutdown
fi
Con esto se minimiza el impacto del apagado ya que el disco está sincronizado y las particiones montadas en solo lectura.
Ahora solo queda probar el invento cerrando la corriente que llega al SAI
(el botón de la regleta es pefecto :D), esperamos a que se descargue la
batería y volvemos a dar la corriente.
Al volver a arrancar el servidor comprobaremos que se apagó normalmente (por
las notificaciones, porque no aparecerá en el dmesg
el peligroso mensaje:
WARNING: / was not properly unmounted, etc.).
Trabajando con upssched
Hasta aquí si todo marcha bien (que gracia, como si no fuera suficientemente
complicado :D). Pero resulta que mi SAI
no funciona como debería (tiene dos
años ya) y no llega a dar avisos para nivel de batería baja (pitido cada 0.5
segundos). En lugar de eso, se apaga… así que upsmon
no llega a hacer su
trabajo adecuadamente.
Vamos a utilizar upssched
para que gestione un temporizador durante 2
minutos y dispare el apagado una vez pasado ese tiempo. No es una solución
óptima pero nos permitirá aguantar varios apagones de ese tiempo relativamente
seguidos (sin tiempo para recuperar la batería).
Cambiamos ligeramente la configuración en /etc/nut/upsmon.conf
:
**NOTIFYCMD /usr/local/sbin/upssched**
NOTIFYMSG ONBATT "%s is on battery"
NOTIFYMSG ONLINE "%s is back online"
NOTIFYMSG LOWBATT "%s has a low battery!"
NOTIFYMSG SHUTDOWN "System is being shutdown!"
NOTIFYFLAG ONBATT SYSLOG+EXEC
**NOTIFYFLAG ONLINE SYSLOG+EXEC**
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
Los cambios están en negrita. Ahora editamos /etc/nut/upssched.conf
:
PIPEFN /var/run/ups/upssched.pipe
LOCKFN /var/run/ups/upssched.lock
CMDSCRIPT /usr/local/bin/upssched-cmd
AT ONBATT * START-TIMER ONBATT 120
AT ONLINE * CANCEL-TIMER ONBATT
AT LOWBATT * EXECUTE LOWBATT
AT SHUTDOWN * EXECUTE SHUTDOWN
Creamos el /usr/local/bin/upssched-cmd
con el siguiente contenido:
#!/bin/sh
# recordar chmod +x
case $1 in
ONBATT)
echo ONBATT TIMEOUT | mail -s "UPS Notify" reidrac
/usr/local/sbin/upsmon -c fsd
;;
LOWBATT)
echo LOWBATT | mail -s "UPS Notify" reidrac
;;
SHUTDOWN)
echo SHUTDOWN | mail -s "UPS Notify" reidrac
;;
*)
logger -t upssched-cmd "Unrecognized command: $1"
;;
esac
De esta forma se apagará la máquina y el SAI
tras 2 minutos funcionando con
la batería, cancelándose este temporizador en caso de volver la corriente en
ese plazo de tiempo.
Despedida
Ahora ya puedo dejar el servidor con el piloto automático e irme de vacaciones sin miedo a que un corte prolongado de electricidad fastidie alguna pieza vital del hardware de la máquina ;).
En esta receta he cubierto la configuración habitual (más algún hack), y
cómo programar apagados en caso de que nuestro SAI
no se comporte
adecuadamente.
Copyright (C) 2005 Juan J. Martinez <reidrac at usebox.net>
Se permite la copia textual y distribución de este documento en su totalidad,
por cualquier medio, siempre y cuando se mantenga esta nota de copyright.