NUT is an uninterruptible power supply (UPS) monitoring system that allows the sharing of one (or more) UPS systems between several computers. It has a 'server' component, which monitors the UPS status and notifies a 'client' component when the UPS has a low battery. There can be multiple computers running the client component and each can be configured to shut down cleanly in a power failure (before the UPS batteries run out of charge).
Monitor a direct-local connected UPS
After installing the NUT Package there are six example configuration files in /etc/nut/
.
Connect to your IPFire system using ssh as root.
Device Driver
Identify your UPS in the NUT Hardware Compatibility List.
Then configure the ups.conf
file. For a UPS connected directly with USB it should look like this:
filename = ups.conf
[apc-1500]
driver = usbhid-ups
port = auto
desc = "The white UPS in the rack"
In this example, the [apc-1500]
is the name of the UPS which will be referred to later. So it is best to keep your alias simple.
The desc
is a short description that you can skip.
Optional Settings
Configure these if your UPS sets the Low Battery flag too early or calculates run time in an odd way.
ignorelb
When you specify this, the driver ignores a low battery condition flag that is reported by the UPS (some devices will switch off almost immediately after setting this flag, or will report this as soon as the mains fails). Instead, it will use either of the following conditions to determine when the battery is low:
battery.charge < battery.charge.low
battery.runtime < battery.runtime.low
The idea is to set the battery.charge.low and/or battery.runtime.low levels in ups.conf to a value that gives enough time to cleanly shutdown your system:
override.battery.charge.low = 30
override.battery.runtime.low = 180
In order for this to work, your UPS should be able to (reliably) report charge and/or runtime remaining on the battery. Use with caution!
default.<variable>
Optional. Set a default value for
default.input.voltage.nominal = 230
The above will report the nominal input voltage to be 230 unless the UPS tells us differently.
override.<variable>
Optional. Set a value for
override.battery.voltage.nominal = 12
Use with caution! This will only change the appearance of the variable to the outside world, internally in the UPS the original value is used.
All other fields are passed through to the hardware-specific part of the driver. See those manuals (FIXME add a link to NUT documentation here) for the list of what is allowed.
Now we should be able to start only the device module of NUT and talk to the UPS
upsdrvctl start
And it should respond with the following output:
Network UPS Tools - UPS driver controller 2.6.3
Network UPS Tools - Generic HID driver 0.34 (2.6.3)
USB communication driver 0.31
Using subdriver: APC HID 0.95
This tells us that NUT was able to launch the USB driver and found a UPS with this driver.
Next, configure the daemon which collects data from the UPS and provides it to a local monitor daemon and/or to daemon from the network.
Daemon Config
The daemon is configured in upsd.conf
filename = upsd.conf
LISTEN 127.0.0.1 3493
LISTEN 192.168.10.1
In this example 192.168.10.1
is the IP-Address of the green interface. You can skip the port number 3493
as it is the default port.
To configure NUT in a standalone configuration only these lines are required as IPFire only uses IPv4.
A user account must be configured to connect to the daemon. Therefore we use the upsd.users
file.
filename = upsd.users
[admin]
password = xxxx
actions = SET FSD
instcmds = ALL
upsmon master
[user]
password = yyyy
upsmon slave
[admin]
is the username, for rest please check out the NUT manpage (FIXME add a link to man page here).
Now start the NUT daemon:
upsd
{bash}
and read the status of our UPS with this command:
upsc apc-1500@localhost
{bash}
we will get something like this (localhost
can be skipped):
battery.charge: 100
battery.charge.low: 10
battery.charge.warning: 50
battery.date: 2001/09/25
battery.mfr.date: 2011/07/14
battery.runtime: 1860
battery.runtime.low: 900
battery.type: PbAc
battery.voltage: 26.9
battery.voltage.nominal: 24.0
device.mfr: American Power Conversion
device.model: Back-UPS RS 1500
device.serial: xxxxxxxxxxxxxxx
device.type: ups
driver.name: usbhid-ups
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.version: 2.6.3
driver.version.data: APC HID 0.95
driver.version.internal: 0.35
input.sensitivity: medium
input.transfer.high: 264
input.transfer.low: 194
input.transfer.reason: input voltage out of range
input.voltage: 234.0
input.voltage.nominal: 230
ups.beeper.status: enabled
ups.delay.shutdown: 20
ups.firmware: 8.g9a.I
ups.firmware.aux: g9a
ups.load: 12
ups.mfr: American Power Conversion
ups.mfr.date: 2011/07/14
ups.model: Back-UPS RS 1500
ups.productid: 0002
ups.realpower.nominal: 865
ups.serial: xxxxxxxxxxxx
ups.status: OL
ups.test.result: No test initiated
ups.timer.reboot: 0
ups.timer.shutdown: -1
ups.vendorid: 051d
if you want only the value of one single line (for scripting, see later) just add the name of the value to the command, like this:
upsc apc-1500@localhost battery.charge
{bash} will return 100
Next, configure the NUT monitor daemon who will be monitoring the UPS and trigger the system shutdown if desired.
Monitor daemon config
The daemon monitor will be configured with upsmon.conf
:
RUN_AS_USER root
MONITOR apc-1500@localhost 1 admin xxxx master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 2
POLLFREQALERT 1
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
NOTIFYMSG ONLINE "UPS %s on line power"
NOTIFYMSG ONBATT "UPS %s on battery"
NOTIFYMSG LOWBATT "UPS %s battery is low"
NOTIFYMSG FSD "UPS %s: forced shutdown in progress"
NOTIFYMSG COMMOK "Communications with UPS %s established"
NOTIFYMSG COMMBAD "Communications with UPS %s lost"
NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding"
NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced"
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
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL
NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL
RBWARNTIME 43200
NOCOMMWARNTIME 600
FINALDELAY 5
I will here only explain some important options to get the whole picture please take a look at the example config file.
RUN_AS_USER root
for more security you may want to create a new user under which NUT will run, but this user must have access to the USB or SERIAL device, read-only access to the config file, and so on.
Or we run NUT as root, since NUT can shutdown the System anyway.
If you skip this NUT will run as user NOBODY which as no access to read the config file (config file access chown
comes later down).
MONITOR apc-1500@localhost 1 admin xxxx master
very important here you set up which UPS NUT should monitoring, also use the right username and password form the upsd.users
file.
SHUTDOWNCMD "/sbin/shutdown -h +0"
this command will be triggered if UPS sends the BL (Battery Low) flag.
NOTIFYCMD /usr/sbin/upssched
only needet if you will follow this how-to to the end and want to use additional notifiying.
POLLFREQ 2
how often it will call the daemon to update the monitor status, for a local unit 1-2 second is fine, for network 5-10 should be ok (depends on how much net traffic you want to have).
POLLFREQALERT 1
same as above but will only be used if the monitor knows that the UPS is on battery, so it may be lower than our default poll frequency so we keep in touch with the UPS (important for network monitoring, you won't miss the FSD flag from master).
HOSTSYNC 15
delay which the master will wait till all the slave hosts have pulled an update (if the master system shuts down).
DEADTIME 15
time the monitor keep an UPS state to be vaild and before it set it to stale if the monitor loss connection with that UPS. (If the UPS was on battery and the deadtime runs out [no update] the monitor will trigger immediately the FSD flag (Force ShutDown) and start the shutdown sequence)
POWERDOWNFLAG /etc/killpower
todo if missing will display a note form init script on system shutdown
NOTIFYMSG ONLINE "UPS %s on line power"
NOTIFYMSG ONBATT "UPS %s on battery"
NOTIFYMSG LOWBATT "UPS %s battery is low"
NOTIFYMSG FSD "UPS %s: forced shutdown in progress"
NOTIFYMSG COMMOK "Communications with UPS %s established"
NOTIFYMSG COMMBAD "Communications with UPS %s lost"
NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding"
NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced"
NOTIFYMSG NOCOMM "UPS %s is unavailable"
NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible"
format of the massages that the monitor can send to wall, syslog or script:
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL
NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL
here you select what kind of actions the monitor will take if he notice an event, if you following this how-to you can keep this settings. For basic UPS monitoring just remove the +EXEC
NOCOMMWARNTIME 600
will repeat the trigger NOCOMM
every 600 seconds
The system will now shutdown when the UPS runtime or battery charge false below the low value!
which is by APC as default very far down the road, so we will set this parameter to a higher value to keep some reserves in the UPS
upsrw apc-1500@localhost
{bash}
will list all available variables you can set in your UPS
[battery.charge.low]
Remaining battery level when UPS switches to LB (percent)
Type: STRING
Value: 10
[battery.runtime.low]
Remaining battery runtime when UPS switches to LB (seconds)
Type: STRING
Value: 900
[input.sensitivity]
Input power sensitivity
Type: STRING
Value: medium
[input.transfer.high]
High voltage transfer point (V)
Type: STRING
Value: 264
[input.transfer.low]
Low voltage transfer point (V)
Type: STRING
Value: 194
[ups.delay.shutdown]
Interval to wait after shutdown with delay command (seconds)
Type: STRING
Value: 20
so we will set the parameter for minimum runtime to 15 min and the minimum charge to 40%
upsrw -s battery.runtime.low=900 apc-1500@localhost
upsrw -s battery.charge.low=40 apc-1500@localhost
after each command, it will ask for the username and password from our daemon user config upsd.users
If your UPS does not support this you may check out the value override guide in the device driver section
Schedule Config (Optional)
the NUT schedule module is basically a timer/trigger customized for the notify events of NUT
I stored the upssched-cmd file also in the /etc/nut/
folder so it will be included in the IP-Fire backup
CMDSCRIPT /etc/nut/upssched-cmd
PIPEFN /etc/nut/upssched.pipe
LOCKFN /etc/nut/upssched.lock
# ============================================================================
AT ONBATT * START-TIMER onbatt 300
AT ONLINE * CANCEL-TIMER onbatt online
AT LOWBATT * EXECUTE onbatt
AT COMMBAD * START-TIMER commbad 30
AT COMMOK * CANCEL-TIMER commbad commok
AT NOCOMM * EXECUTE commbad
AT SHUTDOWN * EXECUTE powerdown
in this file you just set up witch timer will be started at which event.
So AT ONBATT * START-TIMER onbatt 300
will start the timeronbatt with 5 min if any (*
) of the UPS will paste the ONBATT
event to upssched (which we configured in the upsmon.conf
notifycmd=...
and the flags with the +EXEC
) if the timer reach zero it will execute onbatt
in the upssched-cmd
bash script
AT ONLINE * CANCEL-TIMER onbatt online
this will cancel the timeronbatt the event ONLINE
get paste, if the timer has already be running out (or timer has not run) the command online
in the bash script will be executed
well and AT SHUTDOWN * EXECUTE powerdown
will directly EXECUTE
the script powerdown
Schedule CMD file
For this script you will need the sendmail addon (sendemail) and maybe some bash scripting knowledge :)
This script will just send an Email with the UPS Status depending on the event
#!/bin/sh
DATUM=`/bin/date
case $1 in
onbatt)
STAT=`upsc apc-1500@localhost ups.status`
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -50`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
-u "Server UPS Event" \
-s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
-o tls=yes -m "$DATUM\nThe Server runs for more than 5 min on UPS Battery now!\n\nUPS Status: $STAT\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
online)
STAT=`upsc apc-1500@localhost ups.status`
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -50`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
-u "Server UPS Event" \
-s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
-o tls=yes -m "$DATUM\nThe Server UPS is back on Line Power now.\n\nUPS Status: $STAT\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
commbad)
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
-u "Server UPS Event" \
-s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
-o tls=yes -m "$DATUM\nThe Server lost Communication with the UPS!" &;;
commok)
STAT=`upsc apc-1500@localhost ups.status`
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -50`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
-u "Server UPS Event" \
-s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
-o tls=yes -m "$DATUM\nThe Server has re-establish Communication with the UPS.\n\nUPS Status: $STAT\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
powerdown)
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -100`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
-u "Server UPS Event" \
-s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
-o tls=yes -m "$DATUM\nThe Server Shutdown due to UPS Event!!!\n\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
*)
echo "wrong parameter";;
esac
exit 0
the '&' at the and of the sendmail command is mandatory upssched will only wait a few ms for the end of the script but sendmail may take up to 3-5 seconds to send the mail, so upssched will try to hit the trigger again and will also only wait a few ms till it get a return code so in the end it will send 3-5 emails instant of only one. With the &
the sendmail command will be send to background and the script returns immediately the error 0 and all are happy :)
Config NUT Mode
Finally we will set the startup mode for NUT tostandalone in the nut.conf
file:
MODE=standalone
User rights (chmod)
for all files in /etc/nut/
user-rights must be set to
chown root:root /etc/nut/*
chmod 0:640 /etc/nut/*
except the upssched-cmd
needs
chmod 0:740 /etc/nut/upssched-cmd
{bash}
Now NUT with all sub modules can be started with /etc/init.d/nut start
The init scripts are already shipped with the packed so no further action has to be taken to autostart NUT on system boot.
To see NUT as running in the service tap of the WGI we do a restart of the system or use
/etc/init.d/nut force-reload
{bash}
to only restart NUT
Plug-in for SysInfo script
Here is a quickplug-in for the sysinfo script (sysinfo)
for the head-part:
ups=`cat /var/log/messages | grep ups
for the body-part:
filename = sysinfo.sh
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
echo " What says NUT ?:"
echo ""
echo "$datum - from IP:$ip_addr"
echo "--------------------------------------------------------------------------------------------------------------------------------------------------"
# UPS entrie in logs
if [](-n $ups) ; then
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
MFR=`upsc apc-1500@localhost ups.mfr`
MODEL=`upsc apc-1500@localhost ups.model`
SERIAL=`upsc apc-1500@localhost ups.serial`
LOAD=`upsc apc-1500@localhost ups.load`
STAT=`upsc apc-1500@localhost ups.status`
echo "UPS MFR: $MFR"
echo "UPS Model: $MODEL"
echo "UPS Serial: $SERIAL"
echo ""
echo "UPS Load: $LOAD%"
echo "UPS Status: $STAT"
echo "UPS Battery Charge: $BATT%"
echo "UPS Runtime: $RUNTIME seconds"
echo ""
echo "--------------------------------------------------------------------------------------------------------------------------------------------------"
echo "NUT has this Log entry's"
echo ""
cat /var/log/messages | grep ups | tail -50
echo "-----------------------------------------------------------------------------------------------------------------------------------------------"
elif [](-z $ups) ; then
echo ""
echo "NUT is not enable and/or has no Log entry"
echo ""
fi
echo ""
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
echo ""
Monitor a network UPS
There Driver and Daemon Part is not needed to monitor a network UPS,
you only need to change the Monitor entry in the upsmon.conf
to
MONITOR apc-1500@192.168.1.1 1 username password slave
instead of localhost enter the IP of the device where the UPS is connected and NUT is running, and use the right username and password form the upsd.users file on that device.
Also, you have to change the mode in the nut.conf
to
MODE=netclient
this way NUT will only start the monitor and if you configured the Schedule module
What happens on Power Events
http://www.networkupstools.org/docs/user-manual.chunked/ar01s06.html#Shutdown_design
Here are the steps that occur when a critical power event happens:
-
The UPS goes on battery
-
The UPS reaches low battery (a "critical" UPS), that is to say upsc displays:
ups.status: OB LB
The exact behavior depends on the specific device and is related to:
battery.charge and battery.charge.low
battery.runtime and battery.runtime.low
-
The upsmon master notices and sets "FSD" - the "forced shutdown" flag to tell all slave systems that it will soon power down the load.
(If you have no slaves, skip to step 6) -
upsmon slave systems see "FSD" and:
generate a NOTIFY_SHUTDOWN event
wait FINALDELAY seconds - typically 5
call their SHUTDOWNCMD
disconnect from upsd
-
The upsmon master system waits up to HOSTSYNC seconds (typically 15) for the slaves to disconnect from upsd. If any are connected after this time, upsmon stops waiting and proceeds with the shutdown process.
-
The upsmon master:
generates a NOTIFY_SHUTDOWN event
waits FINALDELAY seconds - typically 5
creates the POWERDOWNFLAG file - usually /etc/killpower
calls the SHUTDOWNCMD
-
On most systems, init takes over, kills your processes, syncs and unmounts some filesystems, and remounts some read-only.
-
init then runs your shutdown script. This checks for the POWERDOWNFLAG, finds it, and tells the UPS driver(s) to power off the load.
-
The system loses power.
-
Time passes. The power returns and the UPS switches back on.
-
All systems reboot and go back to work.