"Después del juego es antes del juego"
Sepp Herberger

Mostrando las entradas para la consulta nut ordenadas por relevancia. Ordenar por fecha Mostrar todas las entradas
Mostrando las entradas para la consulta nut ordenadas por relevancia. Ordenar por fecha Mostrar todas las entradas

miércoles, 5 de marzo de 2025

Monitorización del SAI con nut en Debian 12.

Ya hemos tratado varias veces en el pasado de este blog el tema de la monitorización del SAI del servidor desde Debian. Vamos a hacer ahora una recopilación de todo lo aplicado otras veces montado sobre Debian 12, que es el sistema que usamos a día de hoy. Vamos allá.

SAI que tenemos: un Salicru SPS One, que conectado por USB se detecta así:
# lsusb
...
Bus 002 Device 004: ID 0665:5161 Cypress Semiconductor USB to Serial
...
Paquetes a instalar:
# apt-get install nut-client nut-server nut-cgi
Antes de empezar la configuración se aconseja tener un servidor de correo activo para poder enviar los mensajes de cambio de estado del SAI. En el Apartado 2 de esta entrada del blog cuento como montar el sistema que mejor me ha funcionado: postfix reenviando los correos a través de una cuenta de gmail.com

Vamos ahora a ver los distintos ficheros de configuración. El primero es ups.conf, que tiene los datos para conecar al SAI. Una buena manera de saber que ponemos aquí es usar la salida del comando "nut-scanner".
# cat /etc/nut/ups.conf
maxretry = 3
[salicru]
driver = "nutdrv_qx"
port = "auto"
vendorid = "0665"
productid = "5161"
product = "HID UPS"
serial = ""
vendor = "HID UPS"
Los otros ficheros quedarían:
# cat /etc/nut/upsd.conf 
LISTEN 127.0.0.1
LISTEN 172.1.1.2 # PONER LA IP de la maquina donde se ejecuta la monitorización
LISTEN 0.0.0.0 3493
# cat /etc/nut/upsd.users
[admin]
password = mipasswordfavorita
actions = set
actions = fsd
instcmds = ALL
upsmon primary
# cat /etc/nut/hosts.conf 
MONITOR salicru@localhost "SAI Salicru Servidor"
# cat /etc/nut/nut.conf
MODE=standalone
# cat /etc/nut/upsmon.conf 
RUN_AS_USER nut
MONITOR salicru@localhost 1 admin mipasswordfavorita primary
MINSUPPLIES 1
SHUTDOWNCMD "/usr/local/bin/apagar_servidores.sh"
NOTIFYCMD "/sbin/upssched"
NOTIFYMSG ONLINE "UPS: Normal state"
NOTIFYMSG ONBATT "UPS: On battery"
NOTIFYMSG LOWBATT "UPS: Battery low"
NOTIFYMSG FSD "UPS: Starting shutdown"
NOTIFYMSG COMMOK "UPS: Communication restored"
NOTIFYMSG COMMBAD "UPS: Communication lose"
NOTIFYMSG SHUTDOWN "UPS: Shutting down"
NOTIFYMSG NOCOMM "UPS: No communication"
NOTIFYMSG REPLBATT "UPS: Replace battery"
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
# cat /etc/nut/upsset.conf 
# Network UPS Tools - upsset.conf sample file
#
# This file is provided to ensure that you do not expose your upsd server
# to the world upon installing the CGI programs.  Specifically, it keeps
# the upsset.cgi program from running until you have assured it that you
# have secured your web server's CGI directory.
#
# By default, your web server will probably let anyone access upsset.cgi
# once it is installed.  This means that anyone could attempt to crack
# upsd logins since they would appear to be coming from your web server,
# rather than the outside world, slipping through any ACL/ACCESS definitions.
#
# For this reason, you *MUST* first secure your CGI programs before
# enabling upsset in this configuration file.  If you can't do this in
# your web server, then you should *not* run this program.
#
# For Apache, the .htaccess file can be used in the directory with the
# programs.  You'll need something like this:
#
#   <Files upsset.cgi>
#       deny from all
#       allow from your.network.addresses
#   </Files>
#
# You will probably have to set "AllowOverride Limit" for this directory in
# your server-level configuration file as well.
#
# If this doesn't make sense, then stop reading and leave this program alone.
#
# Assuming you have all this done (and it works), then you may uncomment
# the line below and start using upsset.cgi through your web browser.
#
###
I_HAVE_SECURED_MY_CGI_DIRECTORY
###
# cat /etc/nut/upssched.conf
CMDSCRIPT  /usr/local/bin/avisoups.sh
PIPEFN /tmp/upssched.pipe
LOCKFN /tmp/upssched.lock
AT ONBATT * START-TIMER  ups-on-battery-shutdown  600
AT ONLINE * CANCEL-TIMER  ups-on-battery-shutdown
AT ONBATT * START-TIMER ups-on-battery 5
AT ONLINE * CANCEL-TIMER ups-on-battery
AT ONLINE * EXECUTE ups-back-on-line
AT REPLBATT * EXECUTE ups-change_battery
AT LOWBATT * EXECUTE ups-low-battery
AT COMMOK * EXECUTE ups-comunication-ok
AT COMMBAD * EXECUTE ups-comunication-bad
AT NOCOMM * EXECUTE ups-nocomm
AT FSD * EXECUTE ups-fsd
AT SHUTDOWN * EXECUTE ups-shutdown
Para probar que funciona podemos reiniciar los servicios e intentar conectar manualmente con SAI a ver si nos da los datos de carga, voltaje y demás:
# service nut-server restart
# service nut-monitor restart
# upsc salicru
Init SSL without certificate database
battery.charge: 100
battery.voltage: 27.10
battery.voltage.high: 26.00
battery.voltage.low: 20.80
battery.voltage.nominal: 24.0
device.type: ups
driver.name: nutdrv_qx
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.product: HID UPS
driver.parameter.productid: 5161
driver.parameter.serial: 
driver.parameter.synchronous: auto
driver.parameter.vendor: HID UPS
driver.parameter.vendorid: 0665
driver.version: 2.8.0
driver.version.data: Mustek 0.07
driver.version.internal: 0.32
driver.version.usb: libusb-1.0.26 (API: 0x1000109)
input.current.nominal: 6.0
input.frequency: 50.1
input.frequency.nominal: 50
input.voltage: 232.7
input.voltage.fault: 232.7
input.voltage.nominal: 230
output.voltage: 234.8
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 10
ups.productid: 5161
ups.status: OL
ups.type: offline / line interactive
ups.vendorid: 0665
Con lo anterior se ha instalado un interface web al que podemos acceder en la URL: "http://ip-maquina/cgi-bin/nut/upsstats.cgi?host=salicru@localhost". De los diferentes ficheros .cgi que permiten gestionar vía web el SAI me gusta dejar, por temas de seguridad, el fichero "upsset.cgi" sin permisos:
 ls -l /usr/lib/cgi-bin/nut/
total 140
-rwxr-xr-x 1 root root 45416 ene 25  2023 upsimage.cgi
-rwx------ 1 root root 43336 ene 25  2023 upsset.cgi
-rwxr-xr-x 1 root root 47456 ene 25  2023 upsstats.cgi
Ahora muestro los scripts que uso para manejar los eventos y comunicarlos al servidor:
# cat /usr/local/bin/apagar_servidores.sh
#!/bin/bash
# Ejecutado desde  upsmon.conf cuando se la la orden de apagado de servidores.

function mailSend() {

   echo "$2" | mail -s "$1" -a "From: Avisos.ies <tu.correo@gmail.com>"  tu.correo@educarex.es

}

FECHA=$(date)
estado=$(upsc salicru ups.status 2> /dev/null)
en_bateria=$(echo $estado | tr ' ' '\n' | grep "OB")

if [ -z $en_bateria ]  #Si en up.status no parece OB, no estamos en bateria. Es un SHUTDOWNCMD innecesario
then
   MESSAGE_MAIL="Evento SHUTDOWNCMD pero estado $estado. No apagamos el servidor"
   mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Evento SHUTDOWNCMD"
   echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log  # /var/log/sai.log permisos 644 y nut:nut
else
   MESSAGE_MAIL="Apagado servidor por evento SHUTDOWNCMD"
   mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Evento SHUTDOWNCMD"
   echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log  # /var/log/sai.log permisos 644 y nut:nut
   ssh root@tercero "/sbin/shutdown -h +0"
   sleep 10
   /sbin/shutdown -h +0
fi

exit 0
# cat /usr/local/bin/avisoups.sh
#!/bin/bash

function mailSend() {

   echo "$2" | mail -s "$1" -a "From: Avisos.ies <tu.correo@gmail.com>"  tu.correo@educarex.es

}

MESSAGE_MAIL=""
EVENT_TYPE=$1
APAGADO=0
FECHA=$(date)

case "$EVENT_TYPE" in
    "ups-on-battery-shutdown")
        MESSAGE_MAIL="UPS on battery: shutdown now"
        APAGADO=1
        ;;
    "ups-on-battery")
        MESSAGE_MAIL="UPS on battery: warning"
        ;;
    "ups-comunication-bad")
        MESSAGE_MAIL="Communications with UPS lost"
        ;;
    "ups-change_battery")
        MESSAGE_MAIL="UPS battery needs to be replaced"
        ;;
    "ups-back-on-line")
        MESSAGE_MAIL="UPS on line power"
        ;;
    "ups-low-battery")
        MESSAGE_MAIL="UPS battery is low"
        ;;
    "ups-comunication-ok")
        MESSAGE_MAIL="Communications with UPS established"
        ;;
    "ups-nocomm")
        MESSAGE_MAIL="No communication with UPS"
        ;;
    "ups-fsd")
        MESSAGE_MAIL="UPS FSD: forced shutdown received"
        APAGADO=1
        ;;
    "ups-shutdown")
        MESSAGE_MAIL="UPS shutdown: shutdown received"
        APAGADO=1
        ;;
esac

mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Event $EVENT_TYPE de SAI Virgen de Guadalupe:"
echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log

if [ $APAGADO = "1" ]
then
    sleep 30
    /usr/local/bin/apagar_servidores.sh
fi
Por último, si tenemos monit podemos controlar que los servicios están levantados:
# cat /etc/monit/conf.d/monitrc.nut
check process nut-monitor with pidfile /var/run/nut/upsmon.pid
   group nut
   start program = "/bin/systemctl start nut-monitor.service"
   stop  program = "/bin/systemctl stop nut-monitor.service"
   if not exist then restart
   if 5 restarts within 5 cycles then timeout

check process nut-server matching "/lib/nut/upsd"
   group nut  
   start program = "/bin/systemctl start nut-server.service"
   stop  program = "/bin/systemctl stop nut-server.service"
   if not exist then restart
   if 5 restarts within 5 cycles then timeout
Y con esto lo tenemos ya, el porqué de todas las cosas que se configuran en estos ficheros está explicado en los anteriores artículos dedicados a nut en este blog. Espero que este sea la entrada definitiva.

viernes, 7 de noviembre de 2014

Controlar nuestro SAI con nut (Parte 1)

En nuestra querida Extremadura se nos va mas de lo deseado la  corriente eléctrica (y eso que sólo consumimos el 25% de lo que generamos: en casa de herrero, cuchillo de palo) y es imprescindible un SAI para tener protegidos los servidores, el switch troncal y el router de salida a Internet. Y si el SAI lo controlamos desde uno de los servidores, mejor que mejor, pues así podremos estar avisados y llevar un registro de todo lo que pasa.
Antes de nada, hacer una distinción que no conocía y que me trajo muchos quebraderos de cabeza. Ladies and gentlemen: hay dos/tres clases de SAI.
  • Pasivo u offline: en este SAI la corriente entra de fuera y se bifurca en dos líneas paralelas, una que va a las salidas del SAI y otra que va a la batería. Cuando hay un corte de corriente la línea directa que va a la salida pierde la potencia y la batería tiene que activarse y empezar a suministrar energía. Este proceso tarda unos milisegundos llamado "tiempo de transferencia" y genera una onda cuadrada. Si el ordenador que hay conectado a la salida es demasiado sensible (por ejemplo, un servidor HP que tengo) a estas variaciones de la señal, se pondrá en modo standby e interrumpirá su funcionamiento normal. Es decir, que el SAI no servirá de nada y hasta que me di cuenta de esto estuve comiéndome el coco pensando que la fuente de alimentación del servidor era defectuosa.
  • Activo u online: en este SAI la corriente entra de fuera, pasa a la batería y luego a la salida. Es decir, la salida siempre está recibiendo energía de la batería. Si hay un corte no pasa nada: la batería sigue suministrando energía como antes sin que haya ningún tipo de distorsión. Estos SAIs son mas caros, pero no van a darnos problemas con ningún tipo de servidor.
  • Line interactive (añadido 23/11/2015): es un sistema intermedio entre los dos anteriores, basado en utilizar la batería para regular rápidamente las variaciones de tensión.
Prosigamos. Una vez montada la parte eléctrica del SAI y viendo que funciona, tenemos que enchufarlo por el cable USB  al PC que lo va a controlar. Una vez enchufado hacemos lsusb para saber como se identifica. En mi caso la salida es:
Bus 005 Device 024: ID 06da:0003 Phoenixtec Power Co., Ltd 1300VA UPS
Esto debemos anotarlo para buscar luego en Google el driver de nuestro SAI. Yo he buscado "06da:0003 nut driver" en Google, obteniendo varios enlaces con el referencias al driver nut a usar. En unos hablaban del megatec_usb y en otros del blazer_usb. Me decanté por el segundo y acerté.
Ahora procederemos a instalar los paquetes necesarios para el control: nut, nut-cgi, nut-client y nut-server. Nut es un sistema cliente-servidor, formado por un servidor (upsd-upsdrvctl) y uno o varios clientes (upsmon). Esto permite que el SAI sea monitorizado desde un ordenador al que está conectado por cable usb o serie, pero los resultados de esa monitorización estén disponibles en varios equipos (ya que normalmente un SAI suministra energía a varias máquinas). Nosotros vamos a usar un esquema simple en que solo tenemos un servidor y un cliente, alojados en el mismo PC y él se ocupa de todo.
Una vez instalados los paquetes, vamos a configurarlos. Empezamos editando /etc/nut/ups.conf:
[salicru]
driver = blazer_usb
desc = "SAI Salicru"
port = auto
vendorid = 06da
productid = 0003
bus = "005"
Comentemos:
  • [salicru]: nombre que vamos a dar al SAI para manejarlo luego.
  • desc: descripción del SAI.
  • driver: driver a usar.
  • port: puerto a usar, normalmente "auto" es suficiente. En el caso de SAIs conectados por el puerto serie podríamos tener que poner /dev/ttySX
  • vendorid, productid: los identificadores USB del SAI, mostrados con el lsusb.
  • bus: el bus USB donde va conectado el SAI, mostrado con el lsusb.
Siguiente fichero: /etc/nut/upsd.conf
ACL localhost 127.0.0.1/32
ACL local_network 172.19.231.0/24
ACL all 0.0.0.0/0

ACCEPT monitor localhost
ACCEPT local_network
REJECT all all
Aquí ponemos la red de nuestro centro (marcado en rojo). Simplemente es para decir desde que parte de la red va a permitir nut que se hagan conexiones para controlar el estado del SAI.

Nota 23/11/2015: bueno, pues resulta que esta configuración está deprecated(=viejuna). Ahora la nueva sintaxis es esta descrita aquí. Basicamente con
LISTEN ip [puerto] 
indicamos a través de su IP por cual interface de red/puerto se aceptarán peticiones, en nuestro caso sería:
LISTEN 127.0.0.1
LISTEN 172.19.231.X

Siguiente fichero, /etc/nut/upsd.users:
[admin]
password = pwd_admin
allowfrom = localhost local_network
actions = SET
instcmds = ALL

[control]
password = pwd_control
allowfrom = localhost local_network
upsmon master
Son los usuarios para acceder remotamente al proceso servidor que controla el SAI desde los clientes. Lo dejamos tal cual está aquí.

Otro fichero más, /etc/nut/upsmon.conf:
MONITOR salicru@localhost 1 control pwd_control master
RUN_AS_USER nut
MINSUPPLIES 1
SHUTDOWNCMD "/root/scripts/apagar_servidores.sh"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower

NOTIFYCMD "/sbin/upssched"

NOTIFYMSG ONLINE "UPS: Normal state"
NOTIFYMSG ONBATT "UPS: On battery"
NOTIFYMSG LOWBATT "UPS: Battery low"
NOTIFYMSG FSD "UPS: Starting shutdown"
NOTIFYMSG COMMOK "UPS: Communication restored"
NOTIFYMSG COMMBAD "UPS: Communication lose"
NOTIFYMSG SHUTDOWN "UPS: Shutting down"
NOTIFYMSG REPLBATT "UPS: Replace battery"

NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC

RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 0

Siguiente fichero, /etc/nut/upsset.conf:
# Network UPS Tools - upsset.conf sample file
deny from all
allow from 172.19.231.0
Aqui va el rango de direcciones de red que van a poder acceder a la página web que muestra el estado del SAI. En nuestro caso, toda nuestra red, que cada cual ponga aquí lo que estime oportuno.
Siguiente fichero, /etc/nut/hosts.conf:
# Network UPS Tools: example hosts.conf
#
# This file is used to control the CGI programs.  If you have not
# installed them, you may safely ignore or delete this file.
#
# -----------------------------------------------------------------------
#
# upsstats will use the list of MONITOR entries when displaying the
# default template (upsstats.html).  The "FOREACHUPS" directive in the
# template will use this file to find systems running upsd.
#
# upsstats and upsimage also use this file to determine if a host may be
# monitored.  This keeps evil people from using your system to annoy
# others with unintended queries.
#
# upsset presents a list of systems that may be viewed and controlled
# using this file.
#
# -----------------------------------------------------------------------
#
# Usage: list systems running upsd that you want to monitor
#
# MONITOR  ""
#
# Examples:
#
# MONITOR myups@localhost "Local UPS"
# MONITOR su2200@10.64.1.1 "Finance department"
# MONITOR matrix@shs-server.example.edu "Sierra High School data room #1"
MONITOR salicru@localhost "SAI Salicru IES Virgen de Guadalupe
Aquí va el nombre del SAI (o los SAIs) que será monitorizado y mostrado en el interfaz web de nut.

Siguiente fichero, /etc/nut/nut.conf:
# Network UPS Tools:  nut.conf
#
##############################################################################
# General section
##############################################################################
# The MODE determines which part of the NUT is to be started, and which
# configuration files must be modified.
#
# This file try to standardize the various files being found in the field, like
# /etc/default/nut on Debian based systems, /etc/sysconfig/ups on RedHat based
# systems, ... Distribution's init script should source this file to see which
# component(s) has to be started.
#
# The values of MODE can be:
# - none: NUT is not configured, or use the Integrated Power Management, or use
#   some external system to startup NUT components. So nothing is to be started.
# - standalone: This mode address a local only configuration, with 1 UPS
#   protecting the local system. This implies to start the 3 NUT layers (driver,
#   upsd and upsmon) and the matching configuration files. This mode can also
#   address UPS redundancy.
# - netserver: same as for the standalone configuration, but also need
#   some more network access controls (firewall, tcp-wrappers) and possibly a
#   specific LISTEN directive in upsd.conf.
#   Since this MODE is opened to the network, a special care should be applied
#   to security concerns.
# - netclient: this mode only requires upsmon.

MODE=standalone
# set upsd specific options. use "man upsd" for more info
UPSD_OPTIONS=""
# set upsmon specific options. use "man upsmon" for more info
UPSMON_OPTIONS=""
La variable MODE=standalone indica que tenemos un solo SAI y que es controlado por el PC al que está conectado localmente por el puerto USB.
Siguiente fichero, /etc/nut/upssched.conf:
# Network UPS Tools - upssched.conf

CMDSCRIPT  /root/scripts/avisoups.sh

##Hay que crear la ruta /var/run/nut/upssched/ si no existe con propietario nut:nut
#PIPEFN /var/run/nut/upssched/upssched.pipe
#LOCKFN /var/run/nut/upssched/upssched.lock
#Añadido 18/12/2015: por algún extraño motivo, la ruta 
#/var/run/nut/upssched/ es borrada periódicamente por el sistema con lo cual
#upssched deja de funcionar. La solución mas cómoda es usar /tmp/ para almacenar 
#ambos ficheros:
PIPEFN /tmp/upssched.pipe
LOCKFN /tmp/upssched.lock

# Si hay corte de corriente, se lanza un timer que esperará 300 segundos (5 minutos)
# antes de apagar
AT ONBATT * START-TIMER  ups-on-battery-shutdown  300
# Si vuelve la corriente, se cancela el timer
AT ONLINE * CANCEL-TIMER  ups-on-battery-shutdown

# Si hay corte de corriente, se lanza un timer que esperará 15 segundos
# antes de notificarlo

AT ONBATT * START-TIMER ups-on-battery 15
AT ONLINE * CANCEL-TIMER ups-on-battery

#En los siguientes eventos, llama al script de notificacion para que lo procese.
AT ONLINE * EXECUTE ups-back-on-line
AT REPLBATT * EXECUTE ups-change_battery
AT LOWBATT * EXECUTE ups-low-battery
AT COMMOK * EXECUTE ups-comunication-ok
AT COMMBAD * EXECUTE ups-comunication-bad
Nota 18/12/2015: como se puede ver en el listado anterior, he cambiado

PIPEFN /var/run/nut/upssched/upssched.pipe
LOCKFN /var/run/nut/upssched/upssched.lock

por

PIPEFN /tmp/upssched.pipe
LOCKFN /tmp/upssched.lock

ya que la ruta /var/run/nut/upssched/ es borrada periódicamente por el sistema de forma misteriosa, inhabilitando upssched. Usando tmp ya no habrá problema ya que esa ruta existe siempre y puede escribir cualquier proceso en ella.
Aquí empieza lo bueno, expliquemos:
  • CMDSCRIPT: ruta al script se ejecuta al saltar un evento del SAI, en nuestro caso /root/scripts/avisoups.sh.
  • PIPEFN, LOCKFN: rutas a ficheros creados por el servicio nut. Los quedamos tal como están, asegurándonos de que existe la carpeta /var/run/nut/upssched/ con propietario nut:nut
  • AT ONBATT * START-TIMER  ups-on-battery-shutdown  300: indicamos que cuando empiece a funcionar la batería (es decir, haya un corte de corriente) se define un temporizador de 300 segundos, al cabo del cual se dispara un evento ups-on-battery-shutdown.
  • AT ONLINE * CANCEL-TIMER  ups-on-battery-shutdown: si vuelve la corriente, se cancela el temporizador anterior.
  • AT ONBATT * START-TIMER ups-on-battery 15: ídem, pero damos un timeout de 15 segundos.
  • AT ONLINE * EXECUTE ups-back-on-line : cuando el estado del SAI cambie a online se genera un evento ups-back-online. Ídem para el resto de eventos del SAI.
Cuando sucede uno de los eventos controlados en el fichero anterior, se llama al script /root/scripts/avisoups.sh pásandole como parámetro el nombre del evento en cuestión, que recogerá en $1
Contenido de /root/scripts/avisoups.sh:
#!/bin/bash

source mail.sh

MESSAGE_MAIL=""
EVENT_TYPE=$1
APAGADO=0
FECHA=$(date)

case "$EVENT_TYPE" in
    "ups-on-battery-shutdown")
        MESSAGE_MAIL="UPS on battery: shutdown now"
        APAGADO=1
        ;;
    "ups-on-battery")
        MESSAGE_MAIL="UPS on battery: warning"
        ;;
    "ups-comunication-bad")
        MESSAGE_MAIL="Communications with UPS lost"
        ;;
    "ups-change_battery")
        MESSAGE_MAIL="UPS battery needs to be replaced"
        ;;
    "ups-back-on-line")
        MESSAGE_MAIL="UPS on line power"
        ;;
    "ups-low-battery")
        MESSAGE_MAIL="UPS battery is low"
        ;;
    "ups-comunication-ok")
        MESSAGE_MAIL="Communications with UPS established"
        ;;
esac

mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Event $EVENT_TYPE de SAI Virgen de Guadalupe:"
echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log

if [ $APAGADO = "1" ]
then
    sleep 30
    /root/scripts/apagar_servidores.sh
fi
Como vemos, recoge el evento, construye un mensaje de correo y lo envia con la funcion mailSend. Adicionalmente, lo registra en /var/log/sai.log, para permitir su posterior consulta.
Destacar que si se ha disparado el evento "ups-on-battery-shutdown" es indicativo de que lleva 5 minutos cortada la corriente y para evitar males mayores ordenamos un apagado ordenado de los servidores a través del script /root/scripts/apagar_servidores.
En /root/scripts/mail.sh tenemos la función mailsend, que ya hemos usado en otras entradas del blog. Hay que configurar este comando con el usuario, contraseña y destinatario pertinentes:
function mailSend() {

    mailsend -smtp smtp.gmail.com \
        -port 587 \
        -starttls -auth \
        -user micuenta@gmail.com \
        -pass mipassword \
        -f micuenta@gmail.com \
        -t micuenta@gmail.com \
        -sub "$1" -M "$2"
}
El script de apagado de servidores, /root/scripts/apagar_servidores.sh es:
#!/bin/bash

source mail.sh

FECHA=$(date)
MESSAGE_MAIL="Apagando servidores ahora mismo desde el script /root/scripts/apagar_servidores.sh."

mailSend  "$FECHA => $MESSAGE_MAIL" "Aviso Servidor Virgen de Guadalupe"
echo "$FECHA => $MESSAGE_MAIL" >> /var/log/sai.log

ssh root@servidor "/sbin/shutdown -h +0"
sleep 1
ssh root@ldap "/sbin/shutdown -h +0"
sleep 1
/sbin/shutdown -h +0
En esta caso apagamos los servidores "servidor", "ldap" y el propio servidor donde está conectado el SAI. Hay que tener en cuenta que para poder ejecutar remotamente los comandos de apagado con ssh sin tener que introducir la contraseña debemos haber establecido una relación de confianza entre nuestros servidores.
Bueno, con todo esto ya podemos iniciar los servicios:
/etc/init.d/nut-server restart
/etc/init.d/ups-monitor restart
Y verificar que funcionan con:
upsc salicru
Cambiar "salicru" por el nombre que le hayamos puesto al SAI en /etc/nut/ups.conf. La salida será algo como:
battery.charge: 100
battery.voltage: 54.60
battery.voltage.high: 52.00
battery.voltage.low: 41.60
battery.voltage.nominal: 48.0
device.type: ups
driver.name: blazer_usb
driver.parameter.bus: 005
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.productid: 0003
driver.parameter.vendorid: 06da
driver.version: 2.6.4
driver.version.internal: 0.08
input.current.nominal: 6.0
input.frequency: 50.0
input.frequency.nominal: 50
input.voltage: 226.6
input.voltage.fault: 226.6
input.voltage.nominal: 230
output.voltage: 226.6
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 19
ups.productid: 0003
ups.status: OL
ups.temperature: 52.5
ups.type: offline / line interactive
ups.vendorid: 06da
Otros comandos del paquete nut que no he usado nunca, pero ahí están:
  • upscmd: permite mandar comandos al SAI, si es programable.
  • upsrw: leer/cambiar variables de un SAI programable.
  • upsd, upslog, upsdrvctl, upsmon, upssched: son comandos internos usados por los demonios, un usuario normal no suele invocarlos
Por último, podemos acceder via web al estado del SAI, con una URL como: http://servidor-nut/cgi-bin/nut/upsstats.cgi?host=salicru@localhost, cambiando host=salicru@localhost por el nombre que le hayamos puesto al SAI en /etc/nut/ups.conf, el resultado será similar a:

Bueno, con esto tendremos bajo control nuestro SAI y protegidos nuestros servidores. Además llevaremos un registro de las caídas de tensión, para poder reclamar a Iberdrola, X-DDD.
Hasta la semana que viene, sean buenos con los lusers.

miércoles, 16 de diciembre de 2015

Monitorizando nuestro SAI con nut (Parte 3)

Bueno, salimos del fango de la política, lo dejamos para mas adelante y seguimos con nuestras cosas.

Venimos de aquí y de aquí, donde vimos como controlar nuestro SAI con nut y poder manejar los eventos para enviar notificaciones a través del correo electrónico y ejecutar acciones personalizadas.

En esta entrada vamos a ver como monitorizar el SAI desde un PC donde no está conectado directamente (por ejemplo, desde nuestro PC de trabajo o desde un servidor distinto al que tiene el SAI conectado) para ello usaremos el sistema maestro-esclavo que implementa nut.

1. Configuración del maestro.

El maestro es el PC al que tenemos conectado nuestro SAI con un cable USB/Serie y se encarga de monitorizarlo directamente. En las dos entradas previas vimos como configurarlo en gran medida, pero si queremos que tenga esclavos que se conecten a él hay que modificar algunas cosas. Daremos un rápido repaso:

En /etc/nut/hosts.conf:
........
MONITOR salicru@localhost "SAI Salicru IES Virgen de Guadalupe"
En /etc/nut/nut.conf hay que cambiar el mode (antes estaba en standalone):
.....
MODE=netserver
......
El fichero /etc/nut/ups.conf lo dejamos igual. En /etc/nut/upsd.conf ponemos localhost y la IP de la máquina donde esta conectado el SAI:
LISTEN 127.0.0.1
LISTEN 172.X.Y.Z #IP de la máquina donde esta corriendo el nut.
En /etc/nut/upsd.users debemos incluir un usuario para los clientes/esclavo:
[admin]
password = pwd_admin
allowfrom = localhost local_network
actions = SET
instcmds = ALL

[control]
password = pwd_control
allowfrom = localhost local_network
upsmon master

[clientes]
password = pwd_clientes
upsmon slave
El fichero /etc/nut/upsmon.conf (es el que configura el proceso upsmon que monitoriza el SAI):
MONITOR salicru@localhost 1 control pwd_control master
RUN_AS_USER nut
MINSUPPLIES 1
SHUTDOWNCMD "/root/scripts/apagar_servidores.sh"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower

NOTIFYCMD "/sbin/upssched"

NOTIFYMSG ONLINE "UPS: Normal state"
NOTIFYMSG ONBATT "UPS: On battery"
NOTIFYMSG LOWBATT "UPS: Battery low"
NOTIFYMSG FSD "UPS: Starting shutdown"
NOTIFYMSG COMMOK "UPS: Communication restored"
NOTIFYMSG COMMBAD "UPS: Communication lose"
NOTIFYMSG SHUTDOWN "UPS: Shutting down"
NOTIFYMSG REPLBATT "UPS: Replace battery"

NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC

RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 0

Los ficheros /etc/nut/upssched.conf, /etc/nut/upsset.conf y /etc/nut/upsstats.html quedan igual. Después de modificar todo esto reiniciamos los procesos:

# /etc/init.d/nut-server restart
# /etc/init.d/nut-client restart

2. Configuración del esclavo.

En el esclavo (que puede ser un PC normal desde el que queremos acceder al estado del SAI o bien otro servidor que quiere monitorizar el SAI pero no lo tiene conectado directamente) basta con instalar el paquete nut-client:
# apt-get install nut-client
Veamos ahora los ficheros que hay configurar para el esclavo. El primero es /etc/nut/nut.conf:
.....
MODE=netclient
......
Siguiente, /etc/nut/upsmon.conf:
MONITOR salicru@172.X.Y.Z 1 clientes pwd_clientes slave
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5

El fichero /etc/nut/upssched.conf no lo tocamos a no ser que queramos actuar ante los distintos eventos, en ese caso configurariamos upsmon.conf y upssched.conf como se hizo en la primera parte de esta serie de artículos. El resto de ficheros tampoco los tocamos.

Ahora reiniciamos el servicio:
# /etc/init.d/nut-client restart
Y preguntamos al SAI en el servidor remoto "Ola, ke ase?":
# upsc salicru@172.X.Y.Z
Si todo está bien nos contestará con:
battery.charge: 100
battery.voltage: 27.60
battery.voltage.high: 26.00
battery.voltage.low: 20.80
battery.voltage.nominal: 24.0
device.type: ups
driver.name: blazer_usb
driver.parameter.bus: 004
.....
.....

Si no funciona siempre podemos ejecutar a mano:
# upsmon -D 
que arranca el cliente nut en modo debug, lo cual nos muestra los posibles errores por pantalla.

3. Usando en Debian Wheezy knutclient.

Otra forma interesante de monitorizar el SAI que usa Paco, mi compañero del IES García Téllez, es con el cliente gráfico knutclient, que ejecuta un programa en el systray del escritorio de tu PC y con un clic de ratón te muestra el estado del SAI.

El paquete no existe para Debian, pero podemos bajar la versión knutclient-1.0.4-2.mga2.i586.rpm de Mageia en este enlace y luego convertirla en un paquete .deb con el comando alien de Debian, instalando después el paquete creado:.

# wget ftp://fr2.rpmfind.net/linux/mageia/distrib/2/i586/media/core/release/knutclient-1.0.4-2.mga2.i586.rpm
....
# alien knutclient-1.0.4-2.mga2.i586.rpm
....
# dpkg -i knutclient_1.0.4-3_i386.deb

Esta versión es totalmente compatible con nuestro Debian Wheezy, aunque quizá para versiones mas modernas de Debian habría que coger también una versión mas moderna del paquete. El contenido del paquete es:

/.
/usr
/usr/share
/usr/share/applications
/usr/share/applications/kde4
/usr/share/applications/kde4/knutclient.desktop
/usr/share/icons
/usr/share/icons/locolor
/usr/share/icons/locolor/16x16
/usr/share/icons/locolor/16x16/apps
/usr/share/icons/locolor/16x16/apps/knutclient.png
/usr/share/icons/locolor/32x32
/usr/share/icons/locolor/32x32/apps
/usr/share/icons/locolor/32x32/apps/knutclient.png
/usr/share/icons/hicolor
/usr/share/icons/hicolor/22x22
/usr/share/icons/hicolor/22x22/apps
/usr/share/icons/hicolor/22x22/apps/knutclient.png
/usr/share/icons/hicolor/16x16
/usr/share/icons/hicolor/16x16/apps
/usr/share/icons/hicolor/16x16/apps/knutclient.png
/usr/share/icons/hicolor/48x48
/usr/share/icons/hicolor/48x48/apps
/usr/share/icons/hicolor/48x48/apps/knutclient.png
/usr/share/icons/hicolor/32x32
/usr/share/icons/hicolor/32x32/apps
/usr/share/icons/hicolor/32x32/apps/knutclient.png
/usr/share/locale
/usr/share/locale/pt_BR
/usr/share/locale/pt_BR/LC_MESSAGES
/usr/share/locale/pt_BR/LC_MESSAGES/knutclient.mo
/usr/share/locale/ru
/usr/share/locale/ru/LC_MESSAGES
/usr/share/locale/ru/LC_MESSAGES/knutclient.mo
/usr/share/locale/uk
/usr/share/locale/uk/LC_MESSAGES
/usr/share/locale/uk/LC_MESSAGES/knutclient.mo
/usr/share/locale/de
/usr/share/locale/de/LC_MESSAGES
/usr/share/locale/de/LC_MESSAGES/knutclient.mo
/usr/share/locale/fr
/usr/share/locale/fr/LC_MESSAGES
/usr/share/locale/fr/LC_MESSAGES/knutclient.mo
/usr/share/locale/pl
/usr/share/locale/pl/LC_MESSAGES
/usr/share/locale/pl/LC_MESSAGES/knutclient.mo
/usr/share/locale/es
/usr/share/locale/es/LC_MESSAGES
/usr/share/locale/es/LC_MESSAGES/knutclient.mo
/usr/share/locale/cs
/usr/share/locale/cs/LC_MESSAGES
/usr/share/locale/cs/LC_MESSAGES/knutclient.mo
/usr/share/locale/it
/usr/share/locale/it/LC_MESSAGES
/usr/share/locale/it/LC_MESSAGES/knutclient.mo
/usr/share/doc
/usr/share/doc/HTML
/usr/share/doc/HTML/cs
/usr/share/doc/HTML/cs/knutclient
/usr/share/doc/HTML/cs/knutclient/mkicker-cs.png
/usr/share/doc/HTML/cs/knutclient/knutclient-cs.png
/usr/share/doc/HTML/cs/knutclient/variables-cs.png
/usr/share/doc/HTML/cs/knutclient/index.docbook.gz
/usr/share/doc/HTML/cs/knutclient/psetting-cs.png
/usr/share/doc/HTML/cs/knutclient/msetting-cs.png
/usr/share/doc/HTML/cs/knutclient/index.cache.bz2
/usr/share/doc/HTML/cs/knutclient/fsetting-cs.png
/usr/share/doc/HTML/cs/knutclient/new-cs.png
/usr/share/doc/HTML/cs/knutclient/ksetting-cs.png
/usr/share/doc/HTML/cs/knutclient/tkicker-cs.png
/usr/share/doc/HTML/cs/knutclient/usetting-cs.png
/usr/share/doc/HTML/cs/knutclient/asetting-cs.png
/usr/share/doc/HTML/en
/usr/share/doc/HTML/en/knutclient
/usr/share/doc/HTML/en/knutclient/asetting-en.png
/usr/share/doc/HTML/en/knutclient/knutclient-en.png
/usr/share/doc/HTML/en/knutclient/index.docbook.gz
/usr/share/doc/HTML/en/knutclient/variables-en.png
/usr/share/doc/HTML/en/knutclient/fsetting-en.png
/usr/share/doc/HTML/en/knutclient/index.cache.bz2
/usr/share/doc/HTML/en/knutclient/mkicker-en.png
/usr/share/doc/HTML/en/knutclient/ksetting-en.png
/usr/share/doc/HTML/en/knutclient/psetting-en.png
/usr/share/doc/HTML/en/knutclient/msetting-en.png
/usr/share/doc/HTML/en/knutclient/new-en.png
/usr/share/doc/HTML/en/knutclient/usetting-en.png
/usr/share/doc/HTML/en/knutclient/tkicker-en.png
/usr/share/doc/knutclient
/usr/share/doc/knutclient/README
/usr/share/doc/knutclient/ChangeLog.gz
/usr/share/doc/knutclient/AUTHORS
/usr/share/doc/knutclient/changelog.Debian.gz
/usr/share/doc/knutclient/copyright
/usr/share/apps
/usr/share/apps/knutclient
/usr/share/apps/knutclient/knutclientui.rc
/usr/share/apps/knutclient/knutclient.notifyrc
/usr/share/apps/knutclient/pics
/usr/share/apps/knutclient/pics/knc_conn.png
/usr/share/apps/knutclient/pics/knc_batt.png
/usr/share/apps/knutclient/pics/knc_ups.png
/usr/share/apps/knutclient/pics/knc_mpref.png
/usr/share/apps/knutclient/pics/knc_dock.png
/usr/share/apps/knutclient/pics/knc_panel.png
/usr/share/apps/knutclient/pics/knc_upses.png
/usr/share/apps/knutclient/pics/knc_mset.png
/usr/share/apps/knutclient/pics/knc_error.png
/usr/share/apps/knutclient/pics/knc_main.png
/usr/share/apps/knutclient/pics/knc_analog.png
/usr/bin
/usr/bin/knutclient
/usr/share/doc/HTML/cs/knutclient/common
/usr/share/doc/HTML/en/knutclient/common
Para que se arranque automaticamente al iniciar sesión habría que copiar /usr/share/applications/kde4/knutclient.desktop en /etc/xdg/autostart/knutclient.desktop. Durante las pruebas de configuración lo mejor es arrancarlo a mano desde terminal tecleando "knutclient". Al ejecutarla se minimiza al systray, en la parte derecha del panel:


Pulsando sobre ella con el botón derecho aparece el menú:


Elegimos "Opciones" para configurar:


Y damos de alta nuestro SAI (basta con dar dirección del SAI-ip o nombre de host-, nombre, usuario y contraseña, tal como hicimos en el apartado 2 en upsmon.conf):


Una vez configurado, pulsando sobre el icono en el systray con el botón izquierdo aparecerá el cuadro de mandos con los indicadores:
La configuración se hace mediante el entorno gráfico, pero se guarda en un fichero que quedaría mas o menos así:
# cat ~/.kde/share/config/knutclientrc 
APanelBackGroundColor=192,192,192
ActiveUps=Salicru
AnalogErrorColor=255,0,0
...............
...............
Width 1440=978

[UPS 0]
Delay=5000
Name=Salicru
Password=pwd_cliente
Port=3493
SavePassword=true
UpsAddress=172.X.Y.Z
UpsName=salicru
UserName=cliente
...............
...............
Var 9=7

Si no nos funciona la conexión desde knutclient, la forma mas sencilla de revisar todo es configurar el cliente como en el apartado 2, con nut-client y una vez funcione, meter la configuración que ya hemos probado en knutclient.

4. Bonus track: comandos útiles y curiosos.

Veamos varios comandos y trucos que pueden venir para manejar el nut y probarlo.

El primero es como generar eventos para verificar que funciona el log, el envío de correos e incluso el apagado. Si hacemos
# upssched
Error: UPSNAME and NOTIFYTYPE must be set.
This program should only be run from upsmon.
Nos da un error diciendo que no va, pero si lo hacemos así:
# export UPSNAME="salicru@localhost"
# export NOTIFYTYPE="ONBATT"
# upssched
Se genera el evento ONBATT que será procesado por el script upssched-cmd como si el SAI se hubiera puesto en modo batería realmente.

El segundo es como dar ordenes inmediatas al SAI:
# upscmd -l salicru
Instant commands supported on UPS [salicru]:

beeper.toggle - Toggle the UPS beeper
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 - Start a battery test
test.battery.start.deep - Start a deep battery test
test.battery.start.quick - Start a quick battery test
test.battery.stop - Stop the battery test
Por ejemplo, con:
# upscmd salicru@localhost beeper.toggle
Desactivamos el molesto beeper (pitido) si está sonando.

El tercero es como simular una orden de apagado inmediata (fsd=forced shutdown):
# upsmon -c fsd
Hay varios comandos más de todo tipo, estos son solo un repasito de lo que me ha resultado mas interesante.

5. Bonus track 2: apagado de los servidores desde nut.

Creo que la última cosa que queda pendiente es el apagado de los servidores desde nut cuando la batería está ya tiritando. Hay dos maneras:
  • La primera es al ejecutarse el comando definido en upsmon.conf mediante SHUTDOWNCMD. Se supone que dicho comando se ejecuta mas o menos cuando salta el evento LOWBATT, pero en mis pruebas no hay manera de hacer que salte automáticamente dicho evento (ni de definir un umbral de carga para que salte), quizá porque el driver del SAI no interpreta bien el dato de la carga de la batería.
  • La segunda es con el método de usar en upssched.conf un TIMER -de los minutos que estimemos oportunos- que llame al script de manejo de eventos con "ups-on-battery-shutdown". Esto hará que cuando el sistema lleve tirando de batería X minutos se llame a dicho script, que a su vez llama a otro script que denominé en anteriores entradas "apagar_servidores.sh", que se encarga de hacer shutdown en los servidores. El problema encontrado aquí es que upssched-cmd se ejecuta como usuario "nut" y por tanto, no puede hacer un shutdown así por las buenas donde nos plazca.
Como se ve, ninguno de los dos métodos funciona por lo que mis máquinas no se apagan de forma ordenada si se agota la batería, algo muy lamentable. ¿Como solucionarlo?. Cuando lo sepa lo cuento, ya que:


Continuamos pronto, ya con el R78 mas debilitado si hubiere suerte tras las próximas elecciones.



sábado, 12 de mayo de 2018

Monitorizando nuestro SAI con nut (Parte 4)

Hace ya tiempo que no dedico una entrada al SAI, pero como se me estropeó el que tenía y recibí uno de reemplazo, al conectarlo y monitorizarlo de nuevo he aprovechado para probar y cerrar temas pendientes. Las entradas precedentes eran:


En el apartado 5 de la última entrada dejaba abierto el problema del apagado del servidor cuando está funcionando con baterías, un tema peliagudo que no tenía muy probado por falta de tiempo y oportunidad. No es plan desconectar el SAI de la corriente y ver que pasa en horario de producción. Ahora si he probado con calma y estas son las conclusiones.

1. Ficheros de configuración básica.

Empecemos repasando como tenemos los ficheros básicos en /etc/nut:

/etc/nut/hosts.conf
MONITOR salicru@localhost "UPS Virgen de Guadalupe"
/etc/nut/nut.conf
MODE=standalone
/etc/nut/ups.conf
maxretry = 3
[salicru]
driver = blazer_usb
port = auto
subdriver = cypress
protocol = mustek
desc = "SAI Salicru"
vendorid = 0665
productid = 5161
bus = "004" # adaptalo a tu caso 
/etc/nut/upsd.conf
LISTEN 127.0.0.1 3493
#IP del servidor donde esta conectado el SAI con el cable USB.
LISTEN 172.20.123.2 3493
/etc/nut/upsd.users
[admin_sai]
password = 13578axd
upsmon master
/etc/nut/upsset.conf
deny from all
allow from 172.20.123.0  
/etc/nut/upsmon.conf
MONITOR salicru@localhost 1 admin_sai 13578axd master
RUN_AS_USER nut
MINSUPPLIES 1
SHUTDOWNCMD "/root/scripts/apagar_servidores.sh"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
NOTIFYCMD "/sbin/upssched"
NOTIFYMSG ONLINE "UPS: Normal state"
NOTIFYMSG ONBATT "UPS: On battery"
NOTIFYMSG LOWBATT "UPS: Battery low"
NOTIFYMSG FSD "UPS: Starting shutdown"
NOTIFYMSG COMMOK "UPS: Communication restored"
NOTIFYMSG COMMBAD "UPS: Communication lose"
NOTIFYMSG SHUTDOWN "UPS: Shutting down"
NOTIFYMSG REPLBATT "UPS: Replace battery"
NOTIFYMSG NOCOMM      "UPS %s is unavailable"
NOTIFYMSG NOPARENT    "upsmon parent process died - shutdown impossible"
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM     SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT   SYSLOG+WALL+EXEC
/etc/nut/upssched.conf:
CMDSCRIPT /usr/bin/upssched-cmd
PIPEFN /tmp/upssched.pipe
LOCKFN /tmp/upssched.lock
AT ONBATT * START-TIMER ups-on-battery 15
AT ONLINE * CANCEL-TIMER ups-on-battery
AT ONLINE * EXECUTE ups-back-on-line
AT REPLBATT * EXECUTE ups-change-battery  
AT LOWBATT * EXECUTE ups-low-battery  
AT FSD * EXECUTE ups-fsd
AT SHUTDOWN * EXECUTE ups-shutdown
AT COMMOK * EXECUTE ups-comunication-ok 
AT COMMBAD * EXECUTE ups-comunication-bad
Of course, en todo lo anterior pondremos el usuario que nos apetezca (en lugar de admin_sai), contraseña y direccionamiento IP correspondiente. Los que he puesto yo son de pega.

2. Proceso de apagado desde nut.

Con calma he leído todo lo que he encontrado sobre el proceso de eventos que genera NUT cuando el SAI está funcionando con batería y empieza a descargarse. Repasamos la secuencia de eventos:

  • El SAI está operando con corriente y con los 2 leds de la derecha del frontal encendidos. Se va la corriente eléctrica y se activa la batería del SAI. De los 6 leds que tiene se encienden en verde los 5 de la derecha, a modo de indicador de carga máxima y comienza a sonar un beep cada pocos segundos. Se irán apagando conforme se descargue la bateria y el beep sonará cada vez con mayor cadencia.
  • Si miramos el estado del SAI con "upsc salicru ups.status" vemos que está en "OB", On Battery. El demonio ups-monitor ha enviado el evento ONBATT para que lo procese el ups-scheduler.
  • Pasa el tiempo y la batería se va descargando. Con "upsc salicru battery.charge" podemos ver el % de carga.
  • Algunos SAI tienen un parámetro battery.charge.low que permite definir el umbral de carga mínima de la batería. Ese umbral se puede redefinir poniendo "override.battery.charge.low = 25" en /etc/nut/ups.conf, pero nuestro Salicru no lo tiene y el umbral está fijado en el 10%. Podemos poner dicho parámetro, reiniciar el demonio y ver con "upsc salicru" que battery.charge.low = 25, pero a la hora de la verdad dicho valor es ignorado y todo se comporta como ese 10% estuviese escrito en piedra.
  • En general: la forma de determinar si la batería está baja depende el SAI/driver concreto y se calcula en función de battery.charge/battery.charge.low y battery.runtime/battery.runtime.low.
  • Pasado el umbral de batería baja se genera un evento LOWBATT para que lo procese el ups-scheduler. Aquí empieza la fiesta.
  • Si nuestro nut tiene esclavos (como vimos en la entrada anterior del blog), se les notifica un evento FSD (forced shutdown). A su vez, cada esclavo:
    • Genera un evento SHUTDOWN.
    • Espera FINALDELAY segundos(tipicamente 5).
    • Ejecuta su propio SHUTDOWNCMD.
    • Desconecta del upsd maestro.
  • El nut maestro, si ha enviado el FSD a los esclavos espera HOSTSYNC segundos (típicamente 15) para darles tiempo a desconectar. Pasado esto se envía un FSD a si mísmo, lo cual:
    • Genera un evento SHUTDOWN.
    • Espera FINALDELAY segundos(tipicamente 5).
    • Crea el fichero POWERDOWNFLAG - usualmente /etc/killpower.
    • Ejecuta su propio SHUTDOWNCMD.
  • A diferencia del resto de código, el comando SHUTDOWNCMD se ejecuta con permisos de root. Esto es debido a que siempre hay en marcha dos instancias de upsmon, una con el usuario "nut" y otra con el usuario "root". Está última está casi siempre ociosa y solo existe para ejecutar lo que diga el parámetro SHUTDOWNCMD definido en upsmon.conf.
Esta es la teoría, haciendo una prueba en entorno real vamos a describir lo que pasa en la práctica:
  • Tengo conectado al SAI una fuente del servidor principal, un servidor auxiliar y un monitor. Desconecto el SAI de la corriente.
  • El parámetro ups.status se pone en OB. battery.charge baja rápidamente en menos de un minuto del 100% al 85-88%. Esto pinta mal.
  • Se estabiliza y empieza a bajar despacio, con los leds frontales apagándose conforme avanza la carga. Este es el ritmo:

    HORA CARGA STATUS EVENTO
    16:40 100% OL
    16:41 100% OB ONBATT
    16:42 88% OB
    17:09 69% OB
    17:24 65% OB
    17:42 29% OB
    17:45:11 15% OB
    17:45:25 12% OB
    17:45:51 10% OB LB FSD LOWBAT, FSD
    17:45:56 4% OB LB FSD EJECUCIÓN SHUTDOWNCMD
    17:46:11 0% OB LB FSD
    17:46:26 42% OL FSD VUELVE LA CORRIENTE
    ONLINE

    Para hacer el cuadrante anterior he capturado los datos con este script:
    #!/bin/bash
    
    while true
    do
       hora=$(date)
       carga=$(upsc salicru battery.charge 2> /dev/null)
       estado=$(upsc salicru ups.status  2> /dev/null)
       voltio=$(upsc salicru battery.voltage  2> /dev/null)
       echo "$hora -> ${carga}% $estado $voltio" >> /root/sai-status.txt
       echo "$hora -> ${carga}% $estado $voltio"
       sleep 15
    done
    
  • Conclusiones:
    • Hay una descarga rapidísima al comienzo, de un 12% en cuestión de segundos.
    • Luego va bajando con suavidad durante una hora. A los 30 minutos está al 70%. A los 60 llega al 15%.
    • Cuando llega al 15% empieza a bajar de nuevo en caída libre y en 2 minutos llega al 0%.
    • Al bajar del 10% se generan los eventos LOWBATT y FSD. Pocos segundos después se llama a SHUTDOWNCMD con credenciales de root.
    • Con la batería al 0% no se corta la corriente, pero no he querido tentar cuanto aguanta así hasta el apagado físico real.
    • Al conectar de nuevo el SAI a la corriente vuelve a cargar y el estado OB se transforma en OL, pero se queda activado el flag FSD ya que no ha llegado a suceder el apagado del servidor.

En resumen: el SAI aguanta 60 minutos o más con 2 servidores y un monitor, pero tiene una curva de descarga bastante acelerada al comienzo y al final. Desde que se genera el evento LOWBATT hasta que se llega al 0% de carga pasan segundos, lo que queda muy poco tiempo de maniobra si queremos apagar varias máquinas.

Una segunda cosa a que destacar que el SAI queda en estado "FSD OL" al volver la corriente en el último momento. Para quitar el flag FSD sin reiniciar el servidor hay que reiniciar el demonio nut-server, pero al hacer eso algunas veces (no siempre) se genera un evento FSD y se ejecuta un SHUTDOWCMD. Esto puede provocar que si no tenemos precauciones con lo que se hace en SHUTDOWNCMD se apague el servidor estando el SAI ya con corriente externa.

En general, siempre que llegamos al estado FSD (incluso manualmente haciendo "/sbin/upsmon -c fsd") tarde o temprano se ejecutará SHUTDOWNCMD, por lo que es algo que habrá que tener en cuenta.

En el siguiente apartado veremos como he abordado las cuestiones planteadas.

3. Configuración del apagado.

Ya que los pocos segundos que transcurren desde que se genera el LOWBATT+FSD hasta que la batería llega al 0% no me inspiran ninguna confianza lo que voy a hacer es que cuando se lleven 30 minutos de batería (momento en que está está sobre el 70%) se apague el servidor de forma segura.

Podría forzar más tiempo, pero si en media hora no ha vuelto la corriente parece que la cosa va para largo y... ¿para que esperar lo inevitable?

Modificamos /etc/nut/upssched.conf para incluir un nuevo timer de 1800 segundos:
CMDSCRIPT /usr/bin/upssched-cmd
PIPEFN /tmp/upssched.pipe
LOCKFN /tmp/upssched.lock
AT ONBATT * START-TIMER  ups-on-battery-shutdown 1800
AT ONLINE * CANCEL-TIMER  ups-on-battery-shutdown
AT ONBATT * START-TIMER ups-on-battery 15
AT ONLINE * CANCEL-TIMER ups-on-battery
AT ONLINE * EXECUTE ups-back-on-line
AT REPLBATT * EXECUTE ups-change-battery  
AT LOWBATT * EXECUTE ups-low-battery  
AT FSD * EXECUTE ups-fsd
AT SHUTDOWN * EXECUTE ups-shutdown
AT COMMOK * EXECUTE ups-comunication-ok 
AT COMMBAD * EXECUTE ups-comunication-bad
Los eventos son gestionados con /usr/bin/upssched-cmd:
#! /bin/bash
#
# This script should be called by upssched via the CMDSCRIPT directive.
# 
# Here is a quick example to show how to handle a bunch of possible
# timer names with the help of the case structure.
#
# This script may be replaced with another program without harm.
#
# The first argument passed to your CMDSCRIPT is the name of the timer
# from your AT lines.

function mailSend() {

   echo "$2" | mail -s "$1" -a "From: Avisos.ies "  tu.correo@gmail.com

}

MESSAGE_MAIL=""
EVENT_TYPE=$1
APAGADO=0
FECHA=$(date)

case "$EVENT_TYPE" in
    "ups-on-battery-shutdown")
      #Saltado evento AT ONBATT * START-TIMER  ups-on-battery-shutdown 1800: llevamos 30 minutos con bateria. Apagamos.
      MESSAGE_MAIL="UPS on battery: shutdown now"
      APAGADO=1
    ;;
    "ups-on-battery")
      MESSAGE_MAIL="UPS on battery: warning"
    ;;
    "ups-comunication-bad")
      MESSAGE_MAIL="Communications with UPS lost"
    ;;
    "ups-change-battery")
      MESSAGE_MAIL="UPS battery needs to be replaced"
    ;;
    "ups-back-on-line")
      MESSAGE_MAIL="UPS on line power"
    ;;
    "ups-low-battery")
      MESSAGE_MAIL="UPS battery is low"
    ;;
    "ups-comunication-ok")
      MESSAGE_MAIL="Communications with UPS established"
    ;;
    "ups-shutdown")  # Llega tras el FSD
      MESSAGE_MAIL="FSD: shutdown message"
    ;;
    *)
      MESSAGE_MAIL="Aviso tipo: $EVENT_TYPE"
    ;;
esac

mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Event $EVENT_TYPE de SAI Virgen de Guadalupe:"
echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log  # /var/log/sai.log permisos 664 y root:nut

if [ $APAGADO = "1" ]
then
    sleep 30
    /sbin/upsmon -c fsd #  Esto genera un evento ups-fsd y un evento ups-shutdown, que a su vez llama a SHUTDOWNCMD como root.
fi
La mayoría de los eventos mandan un correo y escriben en el log /var/log/sai.log. Tan sólo es difrente el salto del timer ups-on-battery-shutdown lanza una orden "/sbin/upsmon -c fsd", que genera a su vez un evento FSD y posteriormente dispara la ejecución de SHUTDOWNCMD, que apunta a /root/scripts/apagar_servidores.sh:
#!/bin/bash

function mailSend() {

   echo "$2" | mail -s "$1" -a "From: Avisos.ies "  tu.correo@gmail.com

}

FECHA=$(date)
estado=$(upsc salicru ups.status 2> /dev/null)
en_bateria=$(echo $estado | tr ' ' '\n' | grep "OB")

if [ -z $en_bateria ]  #Si en up.status no parece OB, no estamos en bateria. Es un SHUTDOWNCMD innecesario
then
   MESSAGE_MAIL="Evento SHUTDOWNCMD pero estado $estado. No apagamos el servidor"
   mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Evento SHUTDOWNCMD"
   echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log  # /var/log/sai.log permisos 664 y root:nut
else
   MESSAGE_MAIL="Apagado servidor por evento SHUTDOWNCMD"
   mailSend  "$FECHA => $MESSAGE_MAIL"  "[UPS] Evento SHUTDOWNCMD"
   echo "$FECHA => SAI: $MESSAGE_MAIL" >> /var/log/sai.log  # /var/log/sai.log permisos 664 y root:nut
   ssh root@servidor-auxiliar "/sbin/shutdown -h +0"
   sleep 10
   /sbin/shutdown -h +0
fi
exit 0
El script anterior recordemos que se ejecuta como root.

Primero comprueba que el SAI sigue en estado OB (en bateria). Si no es así, manda un mensaje diciendo que aunque se haya recibido un FSD-SHUTDOWN no se apagará nada. Esto previene que si tenemos el flag FSD activado estando OL (ON LINE, con corriente) se apague el servidor accidentalmente al reiniciar el demonio nut-server.

Si el SAI está en estado OB se mandan mensajes, se apaga un servidor auxiliar (con el que tenemos una relación de confianza para ejecutar comandos por ssh en él) y finalmente se apaga el servidor que ejecuta nut. Todo esto se hace a la media hora de estar funcionando con el SAI, por lo que da tiempo a cerrar todo tranquilamente ya que queda mas de la mitad de la batería.

4. Fuentes.

Acabo haciendo honores a las fuentes que he seguido para redactar esta entrada:

Y con esto creo que quedo cerrado del todo el tema de nut mientras que no suceda nada excepcional.

Nos leemos pronto.

jueves, 11 de junio de 2026

Monitorización de SAI Phasak SIRIUS 1560VA con nut

Bueno, nos han mandado SAI nuevos para reemplazar los que van fallando. En concreto ahora nos toca un Phasak SIRIUS 1560VA. Una vez instalado físicamente nos toca configurar el nut para monitorizarlo de forma correcta. Enchufo el cable USB al PC donde tengo la monitorización (el servidor del centro) y a ver que sale:
# lsusb
Bus 002 Device 026: ID 1a86:7523 QinHeng Electronics CH340 serial converter
Es raro, se identifica como un puerto Serie-USB. Este tipo de dispositivos se manejan con el dispositivo /dev/ttyUSBx. El problema es que cada vez que lo enchufas, desenchufas o pasa algo con la conexión el número final cambia, por lo que no podemos saber si será ttyUSB0, ttyUSB1, ttyUSB2.... Vamos a arreglar eso haciendo que siempre tenga un nombre fijo:
# nano /etc/udev/rules.d/99-ups.rules
Con contenido:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="ttyUPS_phasak"
Ahora siempre se llamará /dev/ttyUPS_phasak. Vamos a aplicar los cambios:
# udevadm control --reload-rules
# udevadm trigger
Siguiente paso: dar permisos al usuario nut para acceder a /dev/ttyUPS_phasak.
# usermod -aG dialout nut
Con esto ya podemos añadir el dispositivo a la configuración de nut en /etc/nut/ups.conf (Internet me ha recomendado usar el driver blazer_ser):
...
[phasak]
driver = blazer_ser
port = /dev/ttyUPS_phasak
desc = "UPS Phasak"
....
Vamos a reiniciar todo para que se apliquen los cambios:
# upsdrvctl stop
# upsdrvctl start
# systemctl restart nut-server
Y vamos a ver si se establece la conexión:
# upsc phasak
Init SSL without certificate database
battery.charge: 100
battery.voltage: 27.10
battery.voltage.high: 26.00
battery.voltage.low: 20.80
battery.voltage.nominal: 24.0
device.type: ups
driver.name: blazer_ser
driver.parameter.pollinterval: 2
driver.parameter.port: /dev/ttyUSB0
driver.parameter.synchronous: auto
driver.version: 2.8.0
driver.version.internal: 1.58
input.current.nominal: 6.0
input.frequency: 50.0
input.frequency.nominal: 50
input.voltage: 235.0
input.voltage.fault: 0.0
input.voltage.nominal: 230
output.voltage: 235.0
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 9
ups.status: OL
ups.temperature: 25.0
ups.type: offline / line interactive
Yeah, funciona! Ahora solo falta añadir al fichero /etc/nut/upsmon.conf el identificador del SAI para poder monitorizarlo:
MONITOR phasak@localhost 1 admin pontupassword primary
El resto de la configuración del NUT, su cliente y sus alertas está requeteexplicada en otras entradas pasadas del blog, puedes empezar por esta entrada.

Nos vemos!

martes, 10 de noviembre de 2015

Monitorizando nuestro SAI con nut (Reloaded-Parte 2)

En la entrada correspondiente a la Parte 1 contaba como monitorizar el SAI desde uno de nuestros servidores. Como estamos de renovación nos han llegado SAIs nuevos Salicru SPS 1500 One, así que voy a actualizar el documento anterior e incluir alguna cosa que quería corregir hace tiempo.

No me queda claro que sea o no un SAI online u offline (ver entrada anterior del blog para saber la diferencia) . Ya he tenido malas experiencias con SAIs offline y servidores HP Proliant (que es el nuevo servidor que nos han mandado), que se apagaban (bueno, se ponían en standby mode, que es casi apagado) antes de que al SAI le diese tiempo a activar la batería. Al primer corte de luz saldremos de dudas y podremos respirar tranquilos o bien darnos cabezazos contra la pared.

1) Configuración para el SAI Salicru SPS One 1500.

Lo primero es ver como se identifica. El lsusb me dice:
~# lsusb
Bus 004 Device 074: ID 0665:5161 Cypress Semiconductor USB to Serial
Buscando el identificador 0665:5161 por Internet el driver adecuado es blazer_usb, así que el fichero ups.conf sería:
~# cat /etc/nut/ups.conf
[salicru]
#Conexión USB falla al poco tiempo y da errores en syslog.
driver = blazer_usb
desc = "SAI Salicru"
port = auto
vendorid = 0665
productid = 5161
bus = "004"
El valor bus="004" tendrá que adaptarse al que tenga cada cual en su caso. Del resto de ficheros de configuración descritos en la anterior entrada del blog no he tocado nada. Bueno, pues solo queda reiniciar los servicios nut-server y ups-monitor:
# /etc/init.d/ups-monitor restart
# /etc/init.d/nut-server restart
Y decirle al SAI, "ola, ke ase?":
~# upsc salicru
battery.charge: 100
battery.voltage: 27.60
battery.voltage.high: 26.00
battery.voltage.low: 20.80
battery.voltage.nominal: 24.0
device.type: ups
driver.name: blazer_usb
driver.parameter.bus: 004
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.productid: 5161
driver.parameter.vendorid: 0665
driver.version: 2.6.4
driver.version.internal: 0.08
input.current.nominal: 6.0
input.frequency: 50.0
input.frequency.nominal: 50
input.voltage: 233.6
input.voltage.fault: 233.6
input.voltage.nominal: 230
output.voltage: 233.6
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 22
ups.productid: 5161
ups.status: OL
ups.type: offline / line interactive
ups.vendorid: 0665
Parece ser que todo está en orden: me da bien los parámetros y aguanta todo lo que tengo enchufado (4 servidores, 1 monitor, el switch troncal, el switch de cisco y el respaldo 4G de Telefónica). Me preocupa la línea:
ups.type: offline / line interactive. 
Como el servidor nuevo HP sea quisquilloso con los SAI offline eso nos va a dar problemas y el SAI va a ser un bonito adorno, pero seamos positivos como teletubbies y no pensemos en ello de momento.

Nota 23/11/2015: bueno, me congratula anunciar que tras una prueba involuntaria por un corte de corriente puedo afirmar que el servidor Proliant nuevo no se apaga ni se pone en standby al tener que alimentarse solo del SAI. Parece ser que el "line interactive" es suficiente para nuestro servidor.

2) Configuración del envío de correos.

En el post anterior el envío de correos de aviso lo hacia con el programa mailsend, que es una forma rápida y efectiva de enviar correos a través de un servidor SMTP externo. Para ello usaba una función bash con 2 parámetros, el título y el texto del mensaje:
~# cat /root/scripts/mail.sh
function mailSend() {
    mailsend -smtp smtp.gmail.com \
        -port 587 \
        -starttls -auth \
        -user micuenta@gmail.com \
        -pass mipassword \
        -f micuenta@gmail.com \
        -t micuenta@gmail.com \
        -sub "$1" -M "$2"
}
Esta función la incluía mediante "source mail.sh" dentro del script bash desde donde vamos a enviar los correos, en nuestro caso en el script /root/scripts/avisoups.sh descrito en la anterior entrada del blog.

El problema de usar mailsend es que es un comando que no espera: si en el momento de ejecutarlo no puede contactar con el servidor smpt.gmail.com la ejecución es abortada y el envío del mensaje no se realiza. Esto, dentro del contexto que nos ocupa, con el SAI generando eventos seguramente por un corte de corriente hace que tengamos muchas papeletas para que algún switch o router de la red no tenga corriente y no se pueda alcanzar smpt.gmail.com, por lo que la función mailSend no haría un carajo.

Por dicho motivo había que resolverlo de otra manera. Durante un tiempo implementé un sistema de colas de envío construido alrededor de mailsend y gestionado de forma artesanal. Tenía una pinta tan cutre que he decidido borrarlo de la faz de Matrix y no publicarlo aquí ni en ningún otro sitio.

Vaya tontería reinventar la rueda si podemos usar postfix para enviar correos a través de gmail. Siguiendo las instrucciones de dicho enlace ya tenemos un sistema que manda correos usando postfix, basado en hacer un relay de los mensajes a la cuenta SMTP de gmail, que envía el correo. Como postfix si que tiene un sistema de encolado serio y profesional, si intentamos enviar un correo ante un corte de corriente y si no hay respuesta de smtp.gmail.com el mensaje queda encolado para intentarlo mas tarde.

Los ficheros main.cf, sasl_passwd, mailname y sender_canonical quedan finalmente:
~# cat /etc/postfix/main.cf 
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = gmail.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = mail.example.com, miserver.vguadalupe, localhost.vguadalupe, localhost
relayhost =  [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/postfix/cacert.pem
smtp_use_tls = yes
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
sender_canonical_maps = hash:/etc/postfix/sender_canonical

~# cat /etc/postfix/sasl_passwd
[smtp.gmail.com]:587    micuenta@gmail.com:mipassword
El comando postmap a continuación crea /etc/postfix/sasl_passwd.db a partir de /etc/postfix/sasl_passwd, de manera que no se guarda la contraseña en texto plano sino en cifrado.
~# postmap hash:/etc/postfix/sasl_passwd

~# cat /etc/mailname 
gmail.com

~# cat /etc/postfix/sender_canonical
root micuenta@gmail.com
~# postmap /etc/postfix/sender_canonical
Para que los mensajes lleguen apareciendo como remitente micuenta@gmail.com en lugar de el aséptico "root" hay que retocar un poco los parámetros del comando "mail", que es el que usaremos para enviar los mensajes en lugar de "mailsend" ya que "mail" los envía a través del gestor de correos de salida por defecto, en nuestro caso postfix:
~# cat /root/scripts/mail.sh
function mailSend() {
echo "$2" | mail -s "$1" -a "From: avisos.ies "  cuenta.destino@gmail.com
}
3) Uso de knutclient para controlar el SAI desde nuestro PC de trabajo

Esta es una sugerencia de mi compañero Paco, del IES Garcia Téllez. Tengo pendiente probarla y describir aquí que tal va en una futura entrada. Se basa en que el nut es un sistema cliente-servidor, así que nada impide instalar un cliente nut gráfico en mi PC que contactará con el servidor remoto y me mostrará en la barra de tareas el estado del SAI. Una vía interesante para explorar.

Bueno, pues hasta pronto si la invasión de Microsoft y Adobe que esperamos en los centros educativos de Extremadura nos deja vivos. Siempre nos quedará Masada.


Addenda 29-marzo-2016: Bueno, pues después de unos meses monitorizando el SAI hemos tenido un problema bastante puñetero. Tarde o temprano el SAI dejaba de comunicarse con el PC y llenaba el syslog con mensajes:
Nov 12 14:27:21 servidor kernel: [  798.728084] usb 1-2: USB disconnect, device number 72
Nov 12 14:27:23 servidor kernel: [  800.628034] usb 1-2: new low-speed USB device number 73 using uhci_hcd
Nov 12 14:27:23 servidor kernel: [  800.806068] usb 1-2: New USB device found, idVendor=0665, idProduct=5161
Nov 12 14:27:23 servidor kernel: [  800.807639] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Nov 12 14:27:23 servidor kernel: [  800.809114] usb 1-2: Product: USB to Serial
Nov 12 14:27:23 servidor kernel: [  800.810592] usb 1-2: Manufacturer: INNO TECH
Nov 12 14:27:23 servidor kernel: [  800.842240] hid-generic 0003:0665:5161.0048: hiddev0,hidraw0: USB HID v1.00 Device [INNO TECH
USB to Serial] on usb-0000:00:1d.0-2/input0
Nov 12 14:27:33 servidor kernel: [  810.136084] usb 1-2: USB disconnect, device number 73
Nov 12 14:27:34 servidor kernel: [  811.680031] usb 1-2: new low-speed USB device number 74 using uhci_hcd
Y así horas y horas. A veces se solucionaba reiniciando el servidor (que gracia), o desconectando el SAI, o reiniciando el servicio nut. La mayoría de las veces no había otra opción que desconectarlo del USB antes de que el syslog explotase.

Los de soporte técnico de HP han puesto cierto interés en arreglarlo, pero sin grandes resultados. Propusieron usar el parámetro POLLFREQ con valor 2 en upsmon.conf, pero no sirvió de nada. También intentaron convencerme de que abandonase nut y usase ViewPower/WinPower, un monstruo propietario hecho en Java (agárrate, Manuel) para monitorizar el SAI. Ni de coña.

Al final nuestro compañero Carlos Martín me configuró esto:
# cat /etc/nut/ups.conf:
......
......
# Set maxretry to 3 by default, this should mitigate race with slow devices:
maxretry = 3

[salicru]
driver = blazer_usb
port = auto
Y con ese mágico maxretry llevo varios meses en mis dos SAIs sin más problema de comunicación. Carlos: eres un crack.




domingo, 14 de abril de 2019

Monitorizando los puestos del aula con monit (I)


Mi compañero Esteban ha publicado en su blog varios artículos muy interesantes sobre monit. Resumidamente: monit es un servicio que se encarga de monitorizar el sistema y asegurarse de que otros servicios funcionan y/o informarnos ante determinados eventos.

Aparte de usarlo en los servidores del centro también viene bien tenerlo en funcionamiento en los ordenadores de los profesores dentro del aula, ya que se ocupan de varias tareas críticas dentro del contexto de sus funciones y es recomendable tener asegurada y controlada su disponibilidad.

1. Configuración de alertas mediante correo.

Para que monit nos notifique cosas la opción más sencilla es que nos envíe correos electrónicos a través de una cuenta de Gmail. En mi caso ya tengo en el centro un servidor de correo postfix que redirige sus correos a través de la cuenta de Gmail, tal como conté en al apartado 2 de la entrada sobre la Gestión de Avisos del SAI usando nut, por lo que lo mas correcto es que los distintos servicios monit que hay por los pc del centro envíen sus alertas al servidor postfix y este a su vez lo reenvíe a través Gmail.

Para que el servidor postfix admita correos de cualquier PC de nuestra red hay que editar su fichero /etc/postfix/main.cf y añadir:
..
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.19.196.0/24
..
smtpd_client_restrictions = permit_mynetworks, reject
Siendo 172.19.196.0 mi red local y no olvidando reiniciar el servicio postfix después.

A continuación, en cada /etc/monit/monitrc añadimos:
.....
set mailserver 172.19.196.X port 25

set alert mi.correo@gmail.com not on {instance}

set mail-format { from: mi.correos@gmail.com
subject: $HOST - $SERVICE $EVENT a $DATE
message: Monit $ACTION $SERVICE a $DATE en $HOST, Descripcion: $DESCRIPTION.
}
Siendo 172.19.196.X el servidor donde está ejecutándose el servicio postfix en mi red y mi.correo@gmail.com la cuenta de correo Gmail usada para notificar las alertas. El "not on {instance}" es un filtro para que no nos envien correos de alerta cada vez que el servicio monit se enciende o se apaga, ya que son bastante molestos.

2. Monitorizando servicios básicos.

En los puestos de los profesores tengo como mínimo 2 servicios críticos: dhcp (para dar IP a los portátiles, thinclients o worskstations de alumnos) y tftp (para la imagen de arranque de thinclients).
# cat /etc/monit/conf.d/monit.dhcp
check process dhcpd matching "dhcpd"
  start program "/etc/init.d/isc-dhcp-server start"
  stop  program "/etc/init.d/isc-dhcp-server stop"
Y:
# cat /etc/monit/conf.d/monit.tftp
check process tftp matching "/usr/sbin/in.tftpd"
  start program "/etc/init.d/tftpd-hpa restart"  # El restart funciona mejor, porque a veces si no se hace stop luego no arranca.
  stop  program "/etc/init.d/tftpd-hpa stop"
De igual manera podemos ir añadiendo ficheros para monitorizar cualquier servicio que juzguemos imprescindible.

3. Monitorizando los puntos wifi.

Otro recurso crítico en las aulas son los puntos wifi para permitir la conexión de portátiles y dispositivos móviles. Por regla general están en la IP 192.168.0.1 de la red interna del aula:
# cat /etc/monit/conf.d/monit.puntowifi
check host punto-wifi  with address 192.168.0.1
      if failed icmp type echo count 5 with timeout 30 seconds then alert
De esta manera si hay algún problema con el punto wifi (bloqueo o desconexión de cables) nos llegará una alerta por correo.

4. Monitorizando la conexión de las pizarras digitales.

Esta es más divertida: las pizarras digitales se conectan por USB y a veces por accidente o por diabluras de los alumnos se desconecta el cable que las une al PC.
# cat /etc/monit/conf.d/monit.pizarra
check program pizarra with path /usr/local/bin/check_pizarra
    if status != 0 then alert
Evidentemente, para este caso no hay orden específica de monit, lo que tenemos es un script que busca la pizarra entre los dispositivos USB y devuelve 1 si no la encuentra.
# cat /usr/local/bin/check_pizarra
#!/bin/bash
# Devuelve 1 para avisar de desconexión, 0 si esá conectada o bien ya se avisó.

pizarra=$(lsusb -d 0b8c: ; lsusb -d 13ff:) # 0b8c:0069  0b8c:0001  13ff:0008 - Pizarras SmartBoard 480/640 y Galneo
if test -z "$pizarra"
then
     if ! test -f /var/cache/no-pizarra
     then
         retorno=1
         touch /var/cache/no-pizarra
     else
         retorno=0 # Ya se avisó, no necesario volver a hacerlo
     fi
else
      retorno=0
      rm -f /var/cache/no-pizarra  # Reconectada, se borra el testigo de aviso.
fi
exit $retorno
De esta manera se avisa de forma inmediata de cualquier desconexión, quedando registrado en el correo el momento en que sucedió por si necesitamos hacer indagaciones posteriores.

5. Monitorizando teclados y ratones.

Al igual que las pizarras digitales, los teclados y ratones en los puestos del profesor son causa de algún que otro problema. Ya traté este tema en otro artículo, pero ahora lo enfocaré para que la detección se haga desde monit:
# cat /etc/monit/conf.d/monit.kbmouse
check program teclado_raton with path /usr/local/bin/check_kb_mouse
    if status != 0 then alert
Siendo el script:
# cat /usr/local/bin/check_kb_mouse
#!/bin/bash

FICHERO=/var/cache/kbvigila

#En teclados Sweex USB, aparece mouse en devices, aun cuando no haya ratón 
#conectado. Con el filtro grep -v kbd eliminamos esas lineas, para que solo
#coja las corresponden a un ratón real.
raton=$(cat /proc/bus/input/devices  | grep -i mouse | grep -v kbd | grep Handlers| wc -l)

#En teclados RML, la cadena es "keykoard" en lugar de "keyboard"
teclado=$(cat /proc/bus/input/devices  | grep -i key[bk]oard | wc -l)

pizarra=$(lsusb -d 13ff:0008) # Pizarra Galneo
if test -n "$pizarra"
then
   #Las pizarras Galneo se identifican como ratón, asi que hay que decrementar el contador
   ((raton--))
fi

test $raton -eq 0  && hayraton="1" ||  hayraton="2"
test $teclado -eq 0 &&  hayteclado="1" || hayteclado="2"

#En hayXXX: Valor "1": no detectado. 
#           Valor "2": detectado. 

#Recupera el estado anterior de teclado y ratón.
if [ -f $FICHERO ]
then
   km_anterior=$(cat $FICHERO)
else
   km_anterior=""
fi
#Estado actual
km_actual="${hayteclado}${hayraton}"

#Si el estado teclado/raton ha cambiado respecto al estado anterior, devuelve 1
#para que haya una alerta
if  [ "$km_anterior" != "$km_actual" ]
then
   retorno=1
   #Guarda el estado actual para la siguiente comprobación.
   echo "${hayteclado}${hayraton}" > $FICHERO   
else
   retorno=0
fi
exit $retorno
Simplemente se comprueba el estado de conexión de teclado/ratón y se compara con el resultado de la comprobación anterior. Si ha variado algo se lanza un aviso.

6. Tarea puppet.

Todo esto lo distribuyo mediante una tarea puppet que aplicaría a las distintos pc de profesor que quiero monitorizar, siendo el init.pp de la tarea:
class  xubuntu18_monit {

        package { "monit": ensure =>installed }

        service { 'monit':
                ensure  => 'running',
                enable  => true,
                require => Package['monit'],
        }

        file { "monitrc":
                path => "/etc/monit/monitrc",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc",
                ensure => file,
                notify  => Service['monit'],  # Reinicia el servicio si el fichero cambia
                require => Package['monit'],
        }

        case $ies_isltsp {
                "si","yes","true" : {  #En los pc con thinclients hay serficio tftp
                        file { "monitrc-tftp":
                                path => "/etc/monit/conf.d/monitrc.tftp",
                                owner => root, group => root, mode => 600,
                                source => "puppet:///modules/xubuntu18_monit/monitrc.tftp",
                                ensure => file, notify  => Service['monit'], require => Package['monit'],
                        }
                }
                default: { 
                }
        }


        file { "monitrc-wifiap":
                path => "/etc/monit/conf.d/monitrc.wifiap",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc.wifiap",
                ensure => file, notify  => Service['monit'], require => Package['monit'],
        }

        file { "monitrc-pizarra":
                path => "/etc/monit/conf.d/monitrc.pizarra",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc.pizarra",
                ensure => file, notify  => Service['monit'], require => Package['monit'],
        }

        file { "pizarra":
                path => "/usr/local/bin/check_pizarra",
                owner => root, group => root, mode => 755,
                source => "puppet:///modules/xubuntu18_monit/check_pizarra",
        }

        file { "kb_mouse":
                path => "/usr/local/bin/check_kb_mouse",
                owner => root, group => root, mode => 755,
                source => "puppet:///modules/xubuntu18_monit/check_kb_mouse",
        }

}
7. Continuará...

Una vez montado el sistema lo seguiré ampliando con más scripts de monitorización de temperaturas de CPU, placa y GPU, espacio en disco, uso de CPU, estado de las fuentes de alimentación, etc. Lo iremos viendo en artículos sucesivos.


Llevamos unas semanas frenéticas para los espaciotrastornados. Podría hablar de:
  • Increíbles fotos de agujeros negros.


  • El éxito completo de la Falcon Heavy de Space con los tres cohetes reutilizados aterrizando suavemente en sus plataformas.


    ¡Eres grande, Elon Musk!

  • Próxima C: otro candidato a planeta rocoso a 4 años luz de nosotros.

Pero no, la imagen es un eclipse de sol desde la superficie Marte, al pasar las lunas Fobos/Deimos delante del astro rey. ¿Quién tomó esta maravillosa imagen? Mi admirada Opportunity:


Impresionante.