Guide: Network UPS Monitoring on CentOS 7

Having an UPS is a great way to save your precious equipment from power spikes and interrupted supply which could lead to hardware failure or data corruption, but what else can you do with your UPS?

Most UPSes have a USB or Serial connection that can be used to monitor UPS and possibly safely shutdown your computer gracefully when power is lost. Network UPS Tools – or NUT for short – is a server-client piece of software that can be used to send this information across a network. This enabled you to allow other computers that also depend on the UPS to shutdown as well.

In this tutorial I’ll be setting up 2 servers I use at home that run from the UPS. I have the following

  • Mecer ME-3000-WPTU UPS
  • HP Proliant N40L (UPS USB connected to this machine)
  • AMD Rack server
  • Internet equipment (Fibre CPE, Wireless APs, etc)
  • NVR and Security Cameras

Desired result:

  • Turn off the HP and Rack Server 1 minute after a power failure
  • Turn off the beeper 5 seconds after going on battery
  • Leave the UPS running until battery out – this is to keep the internet and NVR running for as long as possible
  • In South-Africa we regularly have load shedding which typically lasts 2 hours and 30 minutes. My UPS runs about 4 hours, which leaves enough time for power to be restored before the UPS will drop power to the remaining online devices

Master Node (HP Server)

In my case I’ll be using the HP Server as my master node, since the UPS is connected directly to this machine. This node will run the driver (upsdrvctl), network service (upsd), as well as a ups monitor (upsmon) to shutdown this server.

Install packages

Firstly you need the epel-release repositories that contains the nut packages

sudo yum install epel-release

Install the nut package

sudo yum install nut

Configure Driver

Connect your UPS and detect it using this command

$ nut-scanner

You will get output looking something like this

Scanning USB bus.
No start IP, skipping SNMP
Scanning XML/HTTP bus.
No start IP, skipping NUT bus (old connect method)
Scanning NUT bus (avahi method).
Scanning IPMI bus.
Failed to create client: Daemon not running

[nutdev1]
driver = "blazer_usb"
port = "auto"
vendorid = "0665"
productid = "5161"
product = "USB to Serial"
vendor = "INNO TECH"
bus = "004"

I had to slightly adapt the output before it worked properly… Lets’ add the configuration required for the driver to talk to the UPS in /etc/ups/ups.conf

[mecer]
driver = "blazer_usb"
port = "auto"
vendorid = "0665"
productid = "5161"

Configure the nut instance mode in /etc/ups/nut.conf

MODE=netserver

Configure access and permissions

Now configure upsd to listen on the server’s IP as well as setup ACLs with access rights to the upsd daemon in /etc/ups/upsd.conf

LISTEN 127.0.0.1 3493
# Listen on the interface of this server
LISTEN 192.168.0.1 3493
ACL all 0.0.0.0/0
ACL localhost 127.0.0.1/32
ACL network 192.168.0.0/24
ACCEPT localhost
ACCEPT network
REJECT all

Let’s configure users that may connect to the daemon in /etc/ups/upsd.users. Each block section is the username used to connect to the daemon. “server1” will be used by the master node, and allows all actions and commands. “server2” will be used by the second node as a slave, and does not require any additional permission.

[server1]
password = secretpass1
allowfrom = localhost
actions = set
instcmds = all
upsmon master

[server2]
password = secretpass2
allowfrom = network
upsmon slave

Configure monitoring service

Next we configure UPSMon which is responsible for monitoring the information provided by upsd. Configure the following in /etc/ups/upsmon.conf. Import here is the NOTIFYFLAG entries. These tell upsmon to call NOTIFYCMD for ONLINE, ONBATT and LOWBATT events. Also we configure how to connect to the ups monitor with the MONITOR entry

MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/ups/killpower
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
MONITOR mecer@localhost 1 server1 secretpass1 master

Configure schedules

Now we configure upssched which is used to control timers on events by editing /etc/ups/upssched.conf

  • AT an ONBATT event from any ups, start a timer that will call CMDSCRIPT with “beeperoff” after 5 seconds.
  • AT an ONBATT event from any ups, start a timer that will call CMDSCRIPT with “earlyshutdown” after 120 seconds
  • AT an ONLINE event from any ups, cancel timer “earlyshutdown” if it hasn’t fired yet.
  • AT a LOWBAT event execute the CMDSCRIPT with “shutdowncritical“.
CMDSCRIPT /usr/bin/upssched-cmd
PIPEFN /var/run/nut/upssched.pipe
LOCKFN /var/run/nut/upssched.lock

# Once any UPS goes on battery, delay turning off the beeper by 5 seconds
AT ONBATT * START-TIMER beeperoff 5
# Once any UPS goes on battery, delay executing "earlyshutdown" with 120 seconds
AT ONBATT * START-TIMER earlyshutdown 120
# If any UPS comes back cancel the "earlyshutdown" if not yet fired
AT ONLINE * CANCEL-TIMER earlyshutdown
# If battery is critical shutdown immediately
AT LOWBATT * EXECUTE shutdowncritical

Edit the script called by upssched in /usr/bin/upssched-cmd

#! /bin/sh
case $1 in
beeperoff)
logger -t upsshed-cmd "Turning off Beeper"
STATUS=`upsc ${UPS_LINK} ups.beeper.status`
if [[ "${STATUS}" == "enabled" ]] ; then
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.toggle
fi
;;
earlyshutdown)
logger -t upssched-cmd "UPS on battery too long, forced shutdown"
/usr/sbin/upsmon -c fsd
;;
shutdowncritical)
logger -t upssched-cmd "UPS on battery critical, forced shutdown"
/usr/sbin/upsmon -c fsd
;;
*)
logger -t upssched-cmd "Unrecognized command: $1"
;;
esac

Enable and start the services

sudo systemctl enable nut-monitor.service
sudo systemctl enable nut-server.service
sudo systemctl start nut-monitor.service
sudo systemctl start nut-server.service

At this stage the Master Node (my HP server) will shutdown correctly after 2 mins on UPS battery.

Slave Node

Next we will configure the slave node to connect to the master node and monitor that UPS.

Install packages

Install epel-release repositories

sudo yum install epel-release

Install the nut client

sudo yum install nut-client

Configure monitoring service

Configure upsmon in /etc/ups/upsmon.conf here we are configuring similar as the master node, except for the MONITOR section. Here we connect to the master node using it’s IP (instead of localhost), we use the credentials for user “server2” and we connect as a slave node.

MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/ups/killpower
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
MONITOR mecer@192.168.0.1 1 server2 secretpass2 slave

Configure schedules

Configure schedules in /etc/ups/upssched.conf. Copy the same config from the master node, but delete the “beeperoff” item

Creating missing directory for upssched.

sudo mkdir -p /var/run/nut/upssched
sudo chown nut:nut -R /var/run/nut/upssched

Edit the script called by upssched in /usr/bin/upssched-cmd. Copy the contents from the master node, you can remove the “beeperoff” section if you which – it is only used by the master node.

Enable and start the services

sudo systemctl enable nut-monitor.service
sudo systemctl enable nut-server.service
sudo systemctl start nut-monitor.service
sudo systemctl start nut-server.service

You should be all set now. I’ve you feel brave you can now pull the plug and watch the action.

References

2 thoughts on “Guide: Network UPS Monitoring on CentOS 7

  • 2019-11-08 at 3:13 pm
    Permalink

    Hey TrojanC,

    This guide is incredible thank you so much (from Cape Town)! God damn, I’ve been struggling since the beginning of the year with my Mecer ME-2000 UPS and my HP ML350G6 (running CentOS 7.7) to play nice with NUT. And your guide is a lifesaver. After implementing your steps, I sadly fell into a wormhole of errors. The last problem that I can’t surmount is a SELinux policy issue.

    From what I’ve read, SELinux won’t let NUT read off the USB. The is a NUT module enabled on SELinux, but I still get an error on the nut-server.service “fopen /var/run/nut/upsd.pid: No such file or directory”. Have you come across this issue? Any ideas on a solve?

    Also, happy to write up some trouble-shooting around “No device supported” and “Failed to open ‘/etc/tmpfiles.d/nut-run.conf'” errors for a main article edit?

    Reply
    • 2019-11-08 at 4:11 pm
      Permalink

      Hi Kyle, I’m almost sure I had that same issue “fopen /var/run/nut/upsd.pid: No such file or directory”. I can’t remember exactly what I did… But I think it the directory did not exist (try sudo mkdir -p /var/run/nut) and make sure its directory permissions are proper with se context set as well.
      This is what a “ls -alZ /var/run” looks like for me

      drwxr-x---. nut nut system_u:object_r:nut_var_run_t:s0 nut

      I could probably write a whole guide on how to troubleshoot SELinux errors too… There are some tools that can help figure out selinux. Search for audit2why and audit2allow… But I can’t remember requiring any SELinux magic… My server are all running selinux enabled too…

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *