Tuesday, May 29, 2018

UPS monitoring

Here is an example of setting up a Raspberry Pi 3 to monitor a few UPSs.
Note you can also install on Windows, iOS and other Linux versions but for a UPS not near a PC, a Raspberry Pi 3 works a treat.

Install the apcupsd and chkconfig packages from the software manager or via yum
yum install apcupsd chkconfig -y
or
apt-get install apcupsd chkconfig -y
Note apcuspd works with many non APC brand UPSs like Cyber Power. 
Note too in some cases you might need to activate the epel repo for the above to find the apcupsd package with:
yum install epel-release
yum update -y

This is what apcupsd has to say about multiple UPSs on a box though it uses the old style init.d structure the the current binaries for CentOS 7 for example do not.

For the first one you can use the standard files. For more than one things get a bit trickier as you need to pass parameters the built in functions do not support. Below has the added steps for adding a second, third .... UPS. Replace the 2 in apcupsd2 in each step with the number of the UPS. For first UPS just leave off the 2.
Note NISPORT 3551 is for UPS 1, 3552 for UPS 2 and so on
Note DEVICE  hiddev0 is for UPS 1, hiddev1 for UPS 2 and so on

To see which UPS is on which port use these commands
First see what ports are in use with
ls /dev/usb/hiddev*

Then for each listed run this swapping in the matching device name for hiddev0
udevadm info --attribute-walk --name=/dev/usb/hiddev0 | egrep 'manufacturer|product|serial'

mv /etc/apcupsd2/apcupsd.conf /etc/apcupsd2/apcupsd.conf.bak
vi /etc/apcupsd2/apcupsd.conf
Add lines like these
## apcupsd.conf v1.1 ##
#
#  for apcupsd2 release 3.14.12 (29 March 2014) - debian
#
# "apcupsd2" POSIX config file
UPSNAME ShopRack
UPSCABLE usb
UPSTYPE usb
DEVICE /dev/usb/hiddev1
LOCKFILE /var/lock
SCRIPTDIR /etc/apcupsd2
PWRFAILDIR /etc/apcupsd2
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 5
MINUTES 3
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 0.0.0.0
NISPORT 3552
EVENTSFILE /var/log/apcupsd2.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 0
STATFILE /var/log/apcupsd2.status
LOGSTATS off
DATATIME 0

vi /etc/init.d/apcupsd2
Replace the script lines with this. You should similarly alter /etc/init.d/apcupsd to match removing the 2 from the highlighted areas.

#!/bin/sh

### BEGIN INIT INFO

# Provides:             apcupsd2
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Should-Start:         $local_fs
# Should-Stop:          $local_fs
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Starts apcupsd2 daemon
# Description:          apcupsd2 provides UPS power management for APC products.
### END INIT INFO

NAME=`basename $0`

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/sbin/apcupsd
CONFDIR=/etc/${NAME}
PID=/var/run/${NAME}.pid
DAEMON_OPTS="-d 9 -f ${CONFDIR}/apcupsd.conf"
CONFIG=/etc/default/apcupsd
DESC="UPS power management:${NAME}"
APCACCESS=/sbin/apcaccess

test -x $DAEMON || exit 0

test -e $CONFIG || exit 0

set -e


. $CONFIG


if [ "x$ISCONFIGURED" != "xyes" ] ;

then
        echo "Please check your configuration ISCONFIGURED in /etc/default/apcupsd"
        exit 0
fi


case "$1" in

        start)
                echo "Starting $DESC: "
                rm -f ${CONFDIR}/powerfail
                /lib/apcupsd/prestart
                PS=`ps -ef | grep ${CONFDIR}/apcupsd.conf | wc -l`
                if [ "$PS" = "1" ]
                then
                        echo "start-stop-daemon --start --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS"
                        start-stop-daemon --start --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS
                        sleep 1
                        $APCACCESS status -f ${CONFDIR}/apcupsd.conf
                else
                        echo ""
                        echo "A copy of the daemon is still running.  If you just stopped it,"
                        echo "please wait about 5 seconds for it to shut down."
                        echo $PS
                        exit 0
                fi
                ;;

        status)

                $APCACCESS status -f ${CONFDIR}/apcupsd.conf
                ;;


        stop)

                echo -n "Stopping $DESC: "
                start-stop-daemon --stop --oknodo --pidfile $PID || echo "Not Running."
                #rm -f $PID
                echo "$NAME."
                ;;

        restart|force-reload)

                $0 stop
                sleep 10
                $0 start
                ;;

        *)

                N=/etc/init.d/$NAME
                echo "Usage: $N {start|stop|restart|force-reload}" >&2
                exit 1
                ;;
esac

exit 0

On CentOS 7
vi /usr/lib/systemd/system/apcupsd2.service
and add the 2 in the paths

[Unit]
Description=APC UPS Power Control Daemon for Linux
After=syslog.target
After=network-online.target

[Service]
ExecStartPre=-/bin/rm -f /etc/apcupsd2/powerfail
ExecStart=/sbin/apcupsd -b -f /etc/apcupsd2/apcupsd.conf

[Install]
WantedBy=multi-user.target


Mark ready by editing master conf file (Note it looks like this might not be in the latest version.)
vi /etc/default/apcupsd
Change the line
ISCONFIGURED=no
to
ISCONFIGURED=yes

Set to auto start by running
chkconfig apcupsd2 on

On CentOS 7 instead do (replace 2 as needed)
/bin/systemctl enable apcupsd2.service
firewall-cmd --permanent --add-port=3552/tcp
firewall-cmd --reload
semanage port -a -t apcupsd_port_t  -p tcp 3552
semanage port -a -t apcupsd_port_t  -p udp 3552

If iptables is enabled you might need to run this command for each port too.
iptables -I INPUT -p tcp --dport 3551 -j ACCEPT

Lastly start it.
/etc/init.d/apcupsd2 start

On CentOS 7 instead do
/bin/systemctl start apcupsd2.service

Test with
apcaccess status -f /etc/apcupsd2/apcupsd.conf
and
apcaccess -h 192.168.2.100:3552
Where 192.168.2.100 is the IP address of the system you are on

With both you should see something like this
APC      : 001,032,0743
DATE     : 2018-06-28 14:55:07 -0500
HOSTNAME : T3500
VERSION  : 3.14.14 (31 May 2016) redhat
UPSNAME  : ShopRack
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2018-06-28 14:52:33 -0500
MODEL    : CP 1000D
STATUS   : ONLINE
LINEV    : 123.0 Volts
LOADPCT  : 9.0 Percent
BCHARGE  : 100.0 Percent
TIMELEFT : 54.3 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
OUTPUTV  : 123.0 Volts
DWAKE    : 0 Seconds
LOTRANS  : 90.0 Volts
HITRANS  : 140.0 Volts
ALARMDEL : 30 Seconds
NUMXFERS : 0
TONBATT  : 0 Seconds
CUMONBATT: 0 Seconds
XOFFBATT : N/A
SELFTEST : OK
STATFLAG : 0x05000008
SERIALNO : BFE5107.B23
NOMINV   : 120 Volts
NOMPOWER : 580 Watts
END APC  : 2018-06-28 14:55:09 -0500


Other CentOS 7 quick checks / trouble shooters

Output of:
firewall-cmd --list-ports
Should contain the ports use above
3389/tcp 8443/tcp 137/tcp 138/tcp 139/tcp 445/tcp 901/tcp 3306/tcp 3552/tcp 3551/tcp

Output of:
semanage port -l | grep apcups
Should contain the ports use above
apcupsd_port_t                 tcp      3552, 3551
apcupsd_port_t                 udp      3552, 3551
Note udp should not be needed but since the apcupsd install enabled it for the first one I enabled it for the second as well to be consistent.

Lastly you might see error in /var.logs/messages like
SELinux is preventing apcupsd from read access on the file /var/log/apcupsd2.events

To fix run the commands
ausearch -c 'apcupsd' --raw | audit2allow -M my-apcupsd

semodule -i my-apcupsd.pp

For more on sorting SELinux issues look at this.

If things did not work take a look at the wiki page for help debugging and / or triggering local actions on events. Note the script they show has the line
. /lib/lsb/init-functions
Odds are nothing below that line in the script gets executed due it being overridden by 
/lib/lsb/init-functions.d/40-systemd which /lib/lsb/init-functions probably pulls in as an include. Hence the custom script above.

Now you should be able to aim your monitor at the host and port to pull in the UPS stats. For instance with Homeseer's Apcupsd plugin.

Which let's you monitor and trigger events on most of these data bits.

For more apcupsd options see Raspbery Pi's and APC UPS'es