NUT - Network UPS Tools
Introducción
El programa NUT sirve para monitorizar UPS (sistemas de alimentación ininterrumpida) de diferentes fabricantes y con distintos sistemas de comunicación, y proporcionar un API común a todos ellos.
En el esquema más básico encontramos un ordenador alimentado por una UPS y conectado a ella para monitorizarla, por lo que tendrá funcionando sobre ella varios programas:
- El programa controlador de la UPS (
/lib/nut/newhidusb
en el ejemplo de más abajo), que es el que habla con el dispositivo. - El demonio de comunicación entre el controlador y el exterior,
/sbin/upsd
, que mantiene un caché de estado para que la respuesta tenga la mínima latencia. También se encarga de comunicar las órdenes administrativas al dispositivo. - El monitorizador,
/sbin/upsmon
, y el encargado de apagar el sistema cuando se dan las condiciones adecuadas.
Si una UPS alimenta a más de un ordenador sólo uno de ellos puede
comunicarse con ella directamente. Tendrá, por tanto, el demonio upsd
, el
controlador del dispositivo, y el programa upsmon
en modo maestro
(master). El resto únicamente tendrán funcionando upsmon
pero en modo
esclavo (slave).
Escenarios
Existen dos elementos clave:
- Una UPS comunicada con un ordenador.
- Una UPS alimentando a un ordenador.
A nivel de ordenador individual nos encontramos alguno de estos escenarios:
- Comunicado con una UPS pero no alimentado por ella.
- Alimentado por una UPS pero no comunicado con ella.
- Alimentado por una UPS y comunicado con ella.
Sólo comunicado
Este es un caso un tanto especial, pero que puede darse en instalaciones grandes cuando se centraliza el software de control, ó cuando se pretende monitorizar el funcionamiento de una ó varias (vía knutclient, por ejemplo).
Alimentado y no comunicado
Bastante común cuando una UPS tiene varias salidas energéticas y una única vía de comunicación. Si una de las máquinas se comunica con ellas, las demás tendrán que conformarse con consultar remótamente el controlador.
Bastará con que tengan funcionando el programa upsmon
en modo esclavo.
Alimentado y comunicado
Es normal es que exista al menos una máquina que reciba la energía de una
UPS y además se comunique con ella. Tendrá que tener funcionando el
controlador hardware, upsd
y upsmon
en modo maestro.
Maestro y esclavo
Son los dos roles bajo los que puede funcionar el programa de monitorización
upsmon
.
El rol maestro conviene usarlo cuando está funcionando en la misma máquina que
el programa upsd
; bajo esta circunstancia se encarga entonces de recibir los
eventos de la UPS, de avisar a los demás del cierre forzoso, de esperar
(no indefinidamente) a que los esclavos cierren sus sistemas, y de apagar la
propia UPS mediante una orden concreta.
El rol esclavo, por contra, se debería emplear cuando se recibe la energía de una UPS pero no se tiene su control directo; en este caso confíamos en que el proceso que actúa como maestro nos indique cuando tenemos que cerrar, y así nos ocupamos únicamente de nuestro sistema.
Instalación del software
Hablando de la distribución estable de Debian, actualmente Debian Etch, los paquetes que se necesitan se limitan a:
- nut que contiene tanto los controladores como los servidores de monitorización.
- nut-usb que incluye controladores para las UPS conectables vía USB.
- nut-cgi en el caso de que queramos monitorizar vía web.
Configuración
Los archivos de configuración se incluyen en el directorio de ejemplos del
paquete, y basta con copiarlos a /etc/nut
para empezar a trabajar sobre
ellos. Contienen bastante documentación, ampliable gracias a las páginas de
manual, y son bastante sencillos de entender.
Además el proyecto incluye abundante documentación y muchas referencias a otras fuentes, como un artículo de Carla Schroder.
El paquete Debian efectúa bastantes tareas de instalación, incluyendo la
creación de un usuario y un grupo nut
, que será el encargado de hacer
funcionar la instalación, a excepción del usuario root
que sólo se emplea
para lanzar el comando de cierre de sistema cuando la ocasión lo requiere.
[!] Los siguientes archivos de configuración deben tener como propietarios a
root.nut
y permisos de acceso limitados a 0640
, dado que contienen
contraseñas de acceso a los servicios.
Definición del controlador
El archivo /etc/nut/ups.conf
describe las UPS que estamos monitorizando.
Una vez que hemos seleccionado el controlador adecuado para la UPS,
se le abre una sección en él, incluyendo una descripción, un puerto de
conexión y otros parámetros que puedan ser necesarios, y que dependen del
controlador en sí.
En mi caso el archivo queda así:
[servers]
driver = newhidups
port = auto
desc = "UPS de servidores"
Para probar su funcionamiento se emplea lo siguiente:
maginot:/etc/nut# /sbin/upsdrvctl start
Network UPS Tools - UPS driver controller 2.0.4
Network UPS Tools: New USB/HID UPS driver 0.28 (2.0.4)
Detected a UPS: American Power Conversion/Smart-UPS 1000 RM FW:616.3.I USB
FW:8.1
Using subdriver: APC/CyberPower HID 0.9
maginot:/etc/nut#
Cuando todo ha ido bien el programa pasa a segundo plano, y en caso de encontrar errores emitirá mensajes más o menos descriptivos de la situación. Puede ser necesario seleccionar otro controlador, modificando el archivo, ó verificar que tenemos permisos de acceso al dispositivo.
Para detenerlo emplearemos:
# /sbin/upsdrvctl stop
Network UPS Tools - UPS driver controller 2.0.4
Stopping UPS: servers
maginot:/etc/nut#
Configuración del interlocutor
El programa upsd
sirve de pasarela de datos entre los controladores de las
UPS y los clientes, incluyendo los monitores de estado (upsmon
).
El control de acceso al mismo se efectúa dentro del archivo
/etc/nut/upsd.conf
, y consiste en crear listas de acceso ACL
y permitir ó
denegar acceso a las mismas.
En mi caso he creado un ACL para la red local y le he dado permiso de acceso a la UPS.
ACL all 0.0.0.0/0
ACL localhost 127.0.0.1/32
ACL localnet 192.168.0.0/24
ACCEPT localhost
ACCEPT localnet
REJECT all
Definiendo usuarios
El archivo /etc/nut/upsd.users
se emplea para crear usuarios y asignarles
privilegios de acceso a la UPS.
Para crear un administrador, por ejemplo, se le abre una sección como ésta:
[myadmin]
password: XXXXXX
allowfrom = localnet
actions = SET
instcmds = ALL
upsmon master
La documentación (ver la página de manual de upsd.users) explica bastante bien las opciones; únicamente resalto aquellas que más me han interesado:
- La claúsula allowfrom hace referencia a los ACL desde los que puede conectarse el usuario.
- La claúsula
upsmon
indica si el usuario puede emplearse desde el programa de monitorización. Es conveniente en este caso definir un usuario con menos privilegios para ello que un administrador.
Verificando la instalación
Tras arrancar los demonios de control de NUT
, en Debian mediante
/etc/init/nut start
, y no encontrar fallos en el proceso, procedemos con los
siguientes comandos para verificar que funciona:
victor@maginot:~ $ upsc servers@maginot ups.status
OL
La respuesta OL significa on line y es la que indica que todo va bien;
otras respuestas pueden ser OB (on battery) y LB (low battery), y eso
significa que hay algo incorrecto con el controlador seleccionado. Es mejor
detener el controlador con upsdrvctl stop
, seleccionar otro y repetir la
secuencia.
Para obtener todos los parámetros de la UPS empleamos una orden parecida:
victor@maginot:~ $ upsc servers@maginot
battery.charge: 100
battery.charge.low: 10
battery.charge.warning: 50
battery.mfr.date: 2006/08/10
battery.runtime: 600
battery.runtime.low: 120
battery.temperature: 33
battery.type: PbAc
battery.voltage: 27.3
battery.voltage.nominal: 24.0
driver.name: newhidups
driver.parameter.port: auto
driver.version: 2.0.4
driver.version.data: APC/CyberPower HID 0.9
driver.version.internal: 0.28
input.voltage: 224.6
output.voltage: 224.6
output.voltage.target.line: 230.0
ups.beeper.status: enabled
ups.delay.shutdown: -1
ups.firmware: 616.3.I
ups.firmware.aux: 8.1
ups.load: 57.2
ups.mfr: American Power Conversion
ups.mfr.date: 2006/08/10
ups.model: Smart-UPS 1000 RM
ups.serial: AS0633111517
ups.status: OL
ups.test.result: No test initiated
victor@maginot:~ $
Monitorización esclava
Si un ordenador está alimentado por la UPS, pero no se comunica con ella, debe tener al menos instalado el monitor en modo slave, de manera que pueda reaccionar frente a los sucesos que le ocurran a ésta.
Definimos a la máquina que tiene conexión directa con la UPS como maestra, y a las demás como esclavas, y efectuamos lo siguiente:
En la máquina maestra creamos un acceso (usuario, contraseña y privilegios) al demonio
upsd
, en el archivo/etc/nut/upsd.users
:[upsmon] password = XXXXX allowfrom = localnet upsmon slave
En la máquina esclava, tras instalar únicamente el paquete nut, configuramos el programa
upsmon
con una entrada en su archivo/etc/nut/upsmon.conf
tal como esta:MONITOR servers@maginot 1 upsmon XXXXX slave
En la que le indicamos que está siendo alimentado por la UPS llamada
servers@maginot
, y que debe conectarse a ella con el usuario upsmon en modo esclavo.Reiniciamos ambos servicios, tanto en la máquina maestra como en la esclava, y verificamos en los registros del sistema que todo haya ido bien:
# tail /var/log/daemon.log ... Jul 24 11:16:07 alejandria upsmon[3249]: Startup successful ...
[!] upsd escucha por defecto en el puerto 3493/tcp, así que si existen cortafuegos activos será necesario retocarlos para permitir este tipo de conexiones.
Apagado del sistema
Fallo en la alimentación eléctrica
La secuencia de hechos ante un fallo de alimentación es la siguiente:
- La UPS comienza a alimentar desde la batería.
- La batería se descarga hasta que alcanza el nivel crítico.
- El programa
upsmon
maestro recibe el evento desde el demonioupsd
y activa el indicador FSD (forced shutdown ó cierre forzoso) en la UPS para indicar a todos los monitorizadores en modo esclavo que en breve se perderá la energía. - Los monitorizadores esclavos verán dicho indicador y harán lo siguiente:
- Generan un evento NOTIFY_SHUTDOWN.
- Esperan los segundos indicados por la variable FINALDELAY (generalmente 5).
- Ejecutan el programa de cierre indicado en la variable SHUTDOWNCMD.
- Se desconectan de la UPS (del demonio
upsd
) cuando el procesoinit
les envía la señal de cierre.
- El monitorizador maestro espera unos segundos (indicados en la variable
HOSTSYNC que suele contener 15) a que todos los monitorizadores esclavos
se desconecten de la UPS. Si pasado este tiempo quedan algunos conectados
upsmon
continúa con el cierre del sistema y los ignora. - El proceso de cierre en el sistema maestro lo realiza el programa
upsmon
y es el siguiente:- Genera el evento NOTIFY_SHUTDOWN.
- Espera los segundos indicados por la variable FINALDELAY (generalmente 5).
- Crea el archivo indicador contenido en la variable POWERDOWNFLAG
(normalmente es
/etc/killpower
). - Ejecuta el programa de cierre indicado en la variable SHUTDOWNCMD.
- En la mayor parte de los sistemas el proceso
init
debe tomar el control en esta parte, matar a los procesos, sincronizar y desmontar los sistemas de archivos y montar algunos como sólo lectura. - Si se configura adecuadamente
init
debería en este punto invocar a nuestro programa especial de cierre, el cuál comprobará la existencia del archivo indicador y enviará la orden de cierre a la propia UPS, posiblemente empleando el programaupsdrvctl
. - La UPS corta la alimentación y el tiempo transcurre.
- La energía eléctrica vuelve y la UPS se enciende de nuevo.
- Las máquinas reciben alimentación y reinician.
[!] Estos dos últimos pasos son algo más comlicados de efectuar, y en mis sistemas aún no he conseguido que sea así, dadas las diferentes BIOS de que disponen.
Disposiciones
Esta es la parte más importante de todas; sin ella las UPS sólo retrasarán unos minutos la caída y el fallo de las máquinas que alimentan.
Una vez tengamos en marcha el monitorizador maestro (upsmon) y los esclavos, el controlador de la UPS y el interlocutor de datos (upsd), procedemos con lo siguiente:
En las máquinas bajo monitorización podemos definir un archivo a modo de indicador que será creado por upsmon en caso de cierre forzoso. Dicho archivo debería estar en un sistema de archivos montado cuando los programas de cierre del sistema estén funcionando, o no servirá de nada.
La directiva que debe añadirse al archivo
/etc/nut/upsmon.conf
es:POWERDOWNFLAG /etc/killpower
Modificamos los programas de cierre de sistema de manera que tengan en cuenta este archivo, y de esta forma sepan distinguir entre un cierre normal y uno provocado por las prisas del inminente corte de energía.
Un ejemplo podría incluír el apagado hardware de la UPS empleando el programa
/usr/bin/upsdrvctl
:if [ -f /etc/killpower ]; then /usr/bin/upsdrvctl shutdown fi
No es necesario borrar este archivo durante el arranque del sistema. upsmon se encargará de ello en cuanto tenga oportunidad.
Testeo
Probar el cierre ordenado de un sistema es un tanto complicado, y no existen demasiadas ayudas para ello.
El programa upsdrvctl
ofrece una opción que puede ayudar un poco; se trata
del parámetro -t
y da el siguiente resultado cuando se le invoca:
maginot:~# upsdrvctl -t shutdown
Network UPS Tools - UPS driver controller 2.0.4
*** Testing mode: not calling exec/kill
exec: /lib/nut/newhidups -a servers -k
Situaciones especiales
Carreras
¿ Qué ocurre cuando vuelve la energía y aún estamos en la fase de cierre de
sistemas ? Esto es lo que el autor de NUT
llama enery race y da algunas
indicaciones en la documentación sobre cómo las encara.
Funcionando dentro de un chroot
El punto débil de NUT
son los controladores, los programas que se
comunican con las UPS; deben estar actualizados para impedir fallos de
comunicación, como los que se puede encontrar en la rama '2.0' con los
dispositivos USB
, que echen abajo el sistema al completo, dado que si no
sabemos nada del dispositivo todo lo demás sobra.
Mis servidores funcionan con la rama estable de Debian y no me gusta emplear versiones backport si puedo evitarlo, así que hace poco me he encontrado con un problema grave que he resuelto empleando un entorno cerrado (chroot), y algunos programas que he escrito a propósito.
La versión de NUT
en Debian Etch era la 2.0.4 y para gestionar una UPS
APC Back-UPS RS 1000 tenía que emplear el controlador
newhidups
, el cual moría una decena de veces al día por un fallo de
segmentación, lo que me obligaba a reiniciarlo manualmente por un lado, y a
suprimir cualquier mensaje alarmista por otro dadas las quejas de los
usuarios, que no sabían a qué atenerse con ello.
La primera medida que tomé fue cederle el control de ejecución a monit, y todo funcionó más o menos bien durante unas semanas hasta que empecé a ver un mensaje como este
usb 1-8: usbfs: process 4312 (newhidups) did not claim interface 0 before use
inundando los registros del sistema. Y lo peor era que el proceso se multiplicaba en memoria y monit no era capaz de gestionar nada.
Viendo que en la versión inestable de Debian el problema de los fallos de segmentación se solucionaba, y que intentar emplear una versión backport no era práctica, pues se necesitaban versiones muy superiores de librerías básicas del sistema, me decidí a emplearla.
Para ello he completado los siguientes pasos:
- Construir un entorno cerrado con schroot.
- Instalar el software base de una rama Debian Sid, entrar en sesión, instalar el paquete nut y salir del chroot.
- Montar algunos directorios especiales como
/var/run/nut
y/proc/bus/usb
. - Copiar la configuración de
NUT
en el chroot. Arrancar los programas en el entorno Debian Sid desde el entorno Debian Etch:
# chroot -c sid /etc/init.d/nut start
Pero dado que es bastante engorroso hacerlo a mano lo he automatizado con un par de programas.
- nut-chroot-setup es el encargado de preparar el entorno.
- nut-chroot-ctl invoca al programa
/etc/init.d/nut
dentro delchroot
, y es muy útil para emplearlo con monit sin más cambios que las opciones que definen los programas que inician y terminan el servicio.
Hasta ahora no he tenido problemas con el controlador, se le puede llamar
desde el cliente con versión 2.0
sin inconvenientes y el resto de la red no
ha notado nada más que una mayor información desde la UPS.