miércoles, 3 de septiembre de 2025

Monitorización de SAI con NUT

NUT (Network UPS Tools) es un software de monitorización de sistemas de alimentación ininterrumpida (SAI) de muchos fabricantes. Yo en este artículo utilizo un Salicru SPS 500 ONE para alimentar un ordenador y lo monitorizo desde el mismo ordenador mediante conexión USB. El software NUT se divide en un servidor que se conecta al SAI y un cliente que se conecta al servidor para monitorizar el SAI. Los dos programas se pueden ejecutar en el mismo ordenador o el cliente se puede conectar al servidor a través de una red.


En Debian podemos instalar el software con apt-get. En el archivo de configuración /etc/nut.conf debemos configurar el modo de funcionamiento. Para monitorizar un SAI conectado al mismo ordenador se utiliza el modo standalone.

# apt-get install nut

# vi /etc/nut/nut.conf

MODE=standalone

En el archivo /etc/nut/ups.conf hay que añadir una sección de configuración para el SAI. En primer lugar se escribe entre corchetes un nombre para identificar al SAI. A continuación se escriben los parámetros de configuración. El parámetro más importante es driver, que indica el controlador a utilizar. Dependiendo del modelo y fabricante tendremos que utilizar un controlador distinto. Para el SAI Salicru SPS 500 ONE se recomienda el controlador nutdrv_qx. A continuación hay que indicar el puerto al que está conectado el SAI, podemos utilizar auto para que se detecte automáticamente. Por último hay parámetros opcionales, algunos de ellos específicos de cada controlador.

# vi /etc/nut/ups.conf

[salicru]
    driver = nutdrv_qx
    port = auto
    desc = "Salicru SPS 500 ONE"

La conexión al servidor se realiza mediante usuarios que debemos configurar en el archivo /etc/nut/upsd.users. Podemos crear un usuario admin para tareas de mantenimiento desde la línea de comandos y un usuario upsmon para la conexión del sistema de monitorización. Con el parámetro instcmds (Instant Commands) indicamos los comandos instantáneos que puede ejecutar el usuario con el comando upscmd. En el usuario para la monitorización tenemos que añadir upsmon y el tipo de conexión. La conexión puede ser primary (primaria) o secondary (secundaria). Si tenemos varios ordenadores alimentados por el SAI y se produce un corte de corriente y agotamiento de la batería, el ordenador con conexión primary es el último en apagarse y se encarga de apagar el SAI.

# vi /etc/nut/upsd.users

[admin]
    password = xxxxxxxxxxxxxxxxxxxxx
    instcmds = ALL

[upsmon]
    password = xxxxxxxxxxxxxxxxxxxxx
    upsmon primary

Una vez que tenemos el usuario creado es posible configurar la monitorización del SAI en /etc/nut/upsmon.conf. Con una directiva MONITOR configuramos la conexión al servidor. Se compone de los siguientes parámetros: nombre-sai@dirección-ordenador, número de fuentes de alimentación (generalmente una), nombre de usuario, contraseña y tipo de conexión. Si el servidor está en el mismo ordenador que el cliente es posible utilizar solo el nombre del SAI.

El sistema de monitorización notifica diferentes eventos como ONLINE cuando el SAI empieza a recibir corriente u ONBATT cuando deja de recibir corriente y toma la electricidad de la batería. Por defecto se registran los eventos en Syslog y se informa a los usuarios del sistema por medio de wall. Con la directiva NOTIFYFLAG podemos modificar los métodos de notificación. Añadiendo EXEC hacemos que la notificación se envíe al comando indicado con la directiva NOTIFYCMD. Mediante la directiva NOTIFYMSG se cambia el mensaje de la notificación.

# vi /etc/nut/upsmon.conf

MONITOR salicru 1 upsmon xxxxxxxxxxxxxxxxxxxxx primary

NOTIFYCMD               /usr/local/bin/nut-notify.sh

NOTIFYMSG ONLINE        "Server On Line"
NOTIFYMSG ONBATT        "Server On Battery"
NOTIFYMSG SHUTDOWN      "Server Shutdown"

NOTIFYFLAG ONLINE       SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT       SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN     SYSLOG+WALL+EXEC

CERTVERIFY 0

Con la directiva CERTVERIFY se activa o desactiva la verificación del certificado digital del servidor. Podemos desactivar la verificación si el servidor se encuentra en el mismo ordenador y no hay peligro de que un usuario del sistema pueda hacer un ataque de intermediario.

El comando de notificación recibe el mensaje de texto y en las variables de entorno NOTIFYTYPE y UPSNAME se puede leer el tipo de notificación y el nombre del SAI. Si utilizamos como comando un "script" Bash debemos usar la variable $* para leer el mensaje completo. En este "script" se puede realizar cualquier tarea necesaria, como por ejemplo enviar una notificación a un teléfono móvil. El comando debe tener permisos de ejecución.

# vi /usr/local/bin/nut-notify.sh

#!/usr/bin/bash

. /usr/local/lib/notifications.sh

send_notification "$*"

# chmod +x /usr/local/bin/nut-notify.sh

Una vez configurado el software hay que reiniciar el servidor y el monitor con systemctl. Si algo no funciona como esperamos puede ser necesario reiniciar el sistema operativo para asegurarnos de que NUT se inicializa satisfactoriamente. Con el comando upsc se ven los parámetros del SAI. En primer lugar está el parámetro battery.charge, que muestra la carga de la batería. Este valor es estimado a partir del voltaje, el SAI Salicru SPS 500 ONE y otros que utilizan el mismo controlador no informan de la carga de la batería. Si queremos tener el valor exacto de carga tendremos que usar un SAI que permita ver este dato.

# systemctl restart nut-server
# systemctl restart nut-monitor

# upsc salicru

battery.charge: 100
battery.voltage: 13.5
battery.voltage.high: 13.00
battery.voltage.low: 10.40
battery.voltage.nominal: 12.0
device.type: ups
driver.debug: 0
driver.flag.allow_killpower: 0
driver.name: nutdrv_qx
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.synchronous: auto
driver.state: quiet
driver.version: 2.8.1
driver.version.data: Voltronic-QS 0.09
driver.version.internal: 0.36
driver.version.usb: libusb-1.0.28 (API: 0x100010a)
input.voltage: 228.7
input.voltage.fault: 228.7
output.current.nominal: 1.0
output.frequency: 50.1
output.frequency.nominal: 50
output.voltage: 228.7
output.voltage.nominal: 230
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.firmware.aux: PM-H
ups.load: 0
ups.productid: 5161
ups.status: OL
ups.type: offline / line interactive
ups.vendorid: 0665

La batería tiene un voltaje nominal de 12 V según se indica en el parámetro battery.voltage.nominal, pero el voltaje real en un momento determinado depende del nivel de carga de la batería y la potencia requerida por los equipos conectados. A mayor carga más alto es el voltaje, a mayor potencia más bajo es el voltaje. Además con el tiempo la batería pierde capacidad de carga.

Para que el nivel de carga se calcule correctamente es necesario indicar al controlador los valores del voltaje con la batería cargada y descargada mediante los parámetros de configuración default.battery.voltage.high y default.battery.voltage.low. Podemos ver el voltaje real de la batería en el parámetro battery.voltage. Para que se muestre correctamente es posible que tengamos que desconectar el SAI de la corriente eléctrica.

battery.charge = (battery.voltage - battery.voltage.low) / (battery.voltage.high - battery.voltage.low) * 100

El SAI informa al sistema de monitorización cuando alcanza un nivel de carga bajo y este procede a apagar el ordenador ejecutando el comando indicado en la directiva SHUTDOWNCMD de /etc/nut/upsmon.conf. Si nuestro SAI no informa correctamente del nivel bajo de batería será necesario ignorarlo con el parámetro de configuración ignorelb y fijar el nivel de carga bajo con el parámetro override.battery.charge.low. Por debajo de este nivel comenzará el apagado del ordenador. En el parámetro ups.status se ve el estado del SAI.

La batería de mi SAI, cuando está completamente cargada y el SAI está desconectado de la red eléctrica, tiene una media de 12,7 V. Algunas veces tiene 12,6 V o 12,8 V pero la mayoría de las veces es 12,7 V. Justo antes de apagarse el SAI el voltaje de la batería es una media de 11,9 V. Aplicando la fórmula de la estimación de la carga salen los valores indicados a continuación:

Voltaje   Carga Estimada
-------   --------------
12.7      100
12.6       88
12.5       75
12.4       63
12.3       50
12.2       37
12.1       25
12.0       12
11.9        0

Si por ejemplo quiero que se apague el ordenador cuando la batería está a mitad de carga y el voltaje es de 12,3 V, debo fijar el nivel bajo de carga en 51. Como el voltaje es un poco variable la estimación no es exacta. Si fijamos muy bajo el nivel de carga puede que no se apague el ordenador a tiempo.

[salicru]

    ..........

    ignorelb
    default.battery.voltage.high = 12.7
    default.battery.voltage.low = 11.9
    override.battery.charge.low = 51
# upsc salicru | grep -E "battery|ignorelb"

battery.charge: 88
battery.charge.low: 51
battery.voltage: 12.6
battery.voltage.high: 12.7
battery.voltage.low: 11.9
battery.voltage.nominal: 12.0
driver.flag.ignorelb: enabled
driver.parameter.default.battery.voltage.high: 12.7
driver.parameter.default.battery.voltage.low: 11.9
driver.parameter.override.battery.charge.low: 51

También podemos apagar el ordenador pasado un tiempo de haberse cortado el suministro eléctrico. Este método presenta problemas si se producen dos cortes muy seguidos y no da tiempo a recargar la batería completamente. En el segundo corte se empieza a contar el tiempo con menos carga y puede suceder que se acabe la carga antes de que pase el tiempo.

Para programar el apagado se usa el comando upssched. Debemos hacer que upsmon ejecute este comando cuando ocurran los eventos indicándolo en la directiva NOTIFYCMD. En la directiva CMDSCRIPT del archivo de configuración /etc/nut/upssched.conf se fija el comando que ejecuta upssched para realizar acciones. Es necesario activar las directivas PIPEFN y LOCKFN para que upssched pueda funcionar.

Mediante directivas AT se programa lo que debe hacer upssched con cada evento. El primer parámetro es el tipo de evento y el segundo el nombre del SAI. Se puede utilizar * para todos los SAI. El nombre debe ser exactamente igual al utilizado en upsmon.conf. Si en upsmon.conf hemos incluido la dirección del ordenador, aquí también debemos incluirla.

El tercer parámetro es el comando a ejecutar. Con START-TIMER se inicia un temporizador con un nombre y un tiempo en segundos. Al completarse el tiempo se ejecuta el comando indicado en CMDSCRIPT y se le pasa el nombre del temporizador como parámetro. Con el comando CANCEL-TIMER se cancela un temporizador. Opcionalmente, si no es posible cancelar el temporizador porque ya se ha completado el tiempo, se ejecuta CMDSCRIPT con el nombre de una acción a realizar. EXECUTE ejecuta CMDSCRIPT inmediatamente con el nombre de una acción.

Si queremos apagar el ordenador 10 minutos después de cortarse el suministro eléctrico, podemos crear con START-TIMER un temporizador de nombre shutdown que comience al recibir el evento ONBATT y transcurridos 600 segundos ejecute el comando CMDSCRIPT. Si se restablece el suministro eléctrico y se recibe el evento ONLINE es necesario cancelar el temporizador shutdown con CANCEL-TIMER. Para enviar una notificación al recibirse los eventos ONBATT y ONLINE se ejecuta inmediatamente CMDSCRIPT usando EXECUTE.

# vi /etc/nut/upsmon.conf

NOTIFYCMD /usr/sbin/upssched


# vi /etc/nut/upssched.conf

CMDSCRIPT /usr/local/bin/nut-notify-shutdown.sh
PIPEFN /run/nut/upssched/upssched.pipe
LOCKFN /run/nut/upssched/upssched.lock

AT ONBATT salicru START-TIMER shutdown 600
AT ONLINE salicru CANCEL-TIMER shutdown

AT ONBATT salicru EXECUTE onbatt
AT ONLINE salicru EXECUTE online

El comando indicado en CMDSCRIPT recibe como primer parámetro el nombre del temporizador o las acciones de CANCEL-TIMER y EXECUTE. Al recibir online u onbatt debe enviar una notificación y al recibir shutdown, además de enviar una notificación, debe ordenar a upsmon que apague el ordenador.

# vi /usr/local/bin/nut-notify-shutdown.sh

#!/usr/bin/bash

. /usr/local/lib/notifications.sh

case $1 in

    online)
        send_notification "Server On Line"
        ;;

    onbatt)
        send_notification "Server On Battery"
        ;;

    shutdown)
        send_notification "Server Shutdown"
        upsmon -c fsd
        ;;
esac


# chmod +x /usr/local/bin/nut-notify-shutdown.sh

Otra forma de apagar el ordenador es ejecutar un comando desde upsmon que se encargue de monitorizar el voltaje y apagar el ordenador cuando este haya bajado hasta un límite fijado. A continuación se muestra un ejemplo con Bash. Cuando el comando recibe el evento ONBATT comienza a leer el voltaje cada varios segundos utilizando upsc. Al alcanzarse el voltaje límite se ordena a upsmon que apague el ordenador.

Si antes de llegar al límite se ejecuta otra vez el comando con el evento ONLINE, es necesario terminar la ejecución anterior para detener la monitorización. Esto se consigue enviando la señal SIGTERM a todos los procesos de ejecución del comando usando killall. Con trap se le indica al intérprete de comandos que capture la señal SIGTERM y al capturarla finalice la ejecución con exit. Bash no permite comparar números con decimales, es necesario usar un programa como bc. Por medio de basename se extrae de la variable $0 el nombre del comando.

#!/usr/bin/bash

. /usr/local/lib/notifications.sh

SHUTDOWN_VOLTAGE=12.3
POLLING_FREQUENCY=5

trap "exit 0" SIGTERM

if [ $NOTIFYTYPE = "ONLINE" ]
then

    send_notification "$*"
    killall -s SIGTERM $(basename $0)

elif [ $NOTIFYTYPE = "ONBATT" ]
then

    send_notification "$*"

    while true
    do
        voltage=$(upsc $UPSNAME battery.voltage 2> /dev/null)

        if [ $(echo "$voltage <= $SHUTDOWN_VOLTAGE" | bc) = 1 ]
        then

            send_notification "Server Shutdown"
            upsmon -c fsd 

        fi

        sleep $POLLING_FREQUENCY

    done
fi

El comando upscmd lista y ejecuta los comandos instantáneos que permita el SAI, utilizando el usuario admin. Por ejemplo con el comando beeper.toggle podemos activar o desactivar los pitidos. En la documentación podemos encontrar más información para ajustar el funcionamiento de NUT a nuestras necesidades.

# upscmd -l salicru

Instant commands supported on UPS [salicru]:

beeper.toggle - Toggle the UPS beeper
driver.killpower - Tell the driver daemon to initiate UPS shutdown; should be unlocked with driver.flag.allow_killpower option or variable setting
driver.reload - Reload running driver configuration from the file system (only works for changes in some options)
driver.reload-or-error - Reload running driver configuration from the file system (only works for changes in some options); return an error if something changed and could not be applied live (so the caller can restart it with new options)
driver.reload-or-exit - Reload running driver configuration from the file system (only works for changes in some options); exit the running driver if something changed and could not be applied live (so service management framework can restart it with new options)
load.off - Turn off the load immediately
load.on - Turn on the load immediately
shutdown.return - Turn off the load and return when power is back
shutdown.stayoff - Turn off the load and remain off
shutdown.stop - Stop a shutdown in progress
test.battery.start.quick - Start a quick battery test


# upscmd salicru beeper.toggle

Username (root): admin
Password: 
OK


# upsc salicru ups.beeper.status

disabled

No hay comentarios:

Publicar un comentario