SYNOPSIS

powstatd [ -t| -k ]

DESCRIPTION

powstatd is a configurable UPS monitoring daemon designed to work with SysVinit (e.g., most Linux distributions).

powstatd monitors a serial connection from a "dumb" or "relay" UPS for power failures and shuts the machine down gracefully if the power remains off for more than a prespecified interval. powstatd can also be configured to allow a master machine to control several slave machines connected to the same UPS via a network connection. This allows you to run several machines off the same UPS, with only one of the machines actually reading the UPS status over the serial line. When compiled with appropriate options enabled, powstatd also provides security by means of fast encryption of master/slave communication to prevent malicious shutdown of slave systems.

powstatd has two options:

-t

Test mode. Used to explore what a given UPS signals under various failure modes as an aid to constructing an appropriate configuration file. When operating in test mode, powstatd doesn't actually signal init, so while changes in UPS status are detected, they are not acted upon. See configuration information for more details.

-k

Kill mode. Directs powstatd to attempt to shut down the UPS. Most UPS systems will ignore the shutdown signal unless the power is actually off. By shutting down the UPS, powstatd ensures that once the main power returns the UPS will automatically turn on and cause the machine to reboot.

CAVEATS

powstatd uses the connectionless UDP protocol to communicate UPS status from master to slave. To keep just anyone from generating a UDP packet that will shut your slave machine down when encrypted master/slave communication is not in use, the slave checks the IP address of origin in the UDP packet it receives. If your master has more than one network card, a master with multiple addresses may provide an unexpected IP address, which results in the slave ignoring (legitimate) status reports.

So when you have a machine with multiple network cards, you must either ensure that the master has a unique IP address (try connecting the single-NIC slave to the UPS and demoting the dual-NIC master to slave instead), or use encrypted master/slave communication, which does not need to check IP source addresses thanks to the cryptographic measures used.

When using encrypted master/slave communication, powstatd also uses a timestamp to foil replay attacks. Outdated status messages (as defined by a compile-time constant) are simply rejected; thus master and slave clocks should be reasonably synchronized (using, for example, the NTP protocol) or valid status messages may be rejected.

CONFIGURATION

powstatd is configured via a configuration file, /etc/powstatd.conf by default, that specifies the serial line behavior of the UPS under its various failure modes (note that, if compiled with appropriate security option enabled, powstatd will require that file permissions on the configuration file deny rwx access to "group" or "other").

To configure your UPS, follow these steps:

0. Edit the Makefile to suit your installation. In particular, the secure master/slave communication protocol is selected/deselected by making the appropriate change to the definition of CFLGS in the Makefile. Note that users outside the United States wishing to use the secure communication protocol will first need to download the public-domain ANSI C implementation of TEA, the Tiny Encryption Algorithm, from ftp://vader.eeng.brad.ac.uk/pub/crypto/xtea.c

1. Compile powstatd:

% make

or, if you are compiling on a DEC Alpha platform:

% make alpha

2. Make sure your new UPS is completely charged and is connected to your machine via the serial monitoring line provided by the UPS manufacturer to your machine (if you did not get such a monitoring line with your UPS, see the the UPS-HOWTO for information on how to make one).

3. In order to configure powstatd, make sure your machine is not powered from the UPS but is instead plugged directly into the wall outlet (your UPS should still, however, be connected to the machine via the serial monitoring line). Instead, plug a desk light or radio into the UPS.

4. Determine what serial line is connected to your UPS and create an initial copy of /etc/powstatd.conf (you can look at the sample powstatd.conf.* files included in the distribution) containing a single line specifying the serial line, e.g.:

watch ttyS0

5. As root, run powstatd in test mode (you'll have to be root to have rw access to /dev/ttyS0 or whatever device corresponds to your UPS monitoring line).

% ./powstatd -t

Hit ^C to stop after you see something like:

CTS DSR DCD RNG RxD TxD DTR RTS STATUS
1 0 1 1 0 0 0 1 OK
1 0 1 1 0 0 0 1 OK
1 0 1 1 0 0 0 1 OK
1 0 1 1 0 0 0 1 OK

The output describes the state of the serial connection between the UPS and the computer. Since the signaling needs of a UPS/computer connection are really quite low (just a few bits), we aren't really using the serial connection as it was designed to be used for higher-throughput applications. Instead, we'll use the individual control and transmission lines in the nine wire standard connector a bit differently.

Of the nine wires, six are of particular interest: four "input" control lines (CTS, DSR, DCD, RNG) and two "output" control lines (DTR, RTS). The remaining three lines consist of an electrical ground and the two transmission lines (TxD and RxD, one running in each direction); the latter are typically used for asynchronous serial information rather than for control. Most "dumb" UPS systems ignore the transmission lines and operate only by toggling combinations of the four "input" wires to indicate the status of the UPS and the two "output" wires to send commands back to the UPS from the computer (for now, we'll assume that the current UPS is one of these).

Since the UPS is fully charged and the power is on, we want to play with the configuration in /etc/powstatd.conf until STATUS reads OK, and not LOW or FAIL. Provided we are actually watching the correct serial line, getting STATUS to read OK entails setting initial values for the output lines DTR and RTS (of course, it makes no sense to try to set initial values on the input lines). Try adding permutations of init values like:

init dtr 1
init rts 1

until you get the OK status reading.

6. Repeat step 4, but this time pull the plug on the UPS and then reinsert it after a few seconds. Observe changes in the values for the input lines; it should be easy to determine what line corresponds to power failure. For example:

CTS DSR DCD RNG DTR RTS STATUS
1 0 1 1 0 1 OK
1 0 1 1 0 1 OK
1 0 1 1 0 1 OK
1 0 1 1 0 1 OK
0 0 1 1 0 1 FAIL <- plug pulled
0 0 1 1 0 1 FAIL
0 0 1 1 0 1 FAIL
0 0 1 1 0 1 FAIL
1 0 1 1 0 1 OK <- plug reinserted
1 0 1 1 0 1 OK
1 0 1 1 0 1 OK

would indicate that CTS going to 0 corresponds to a power failure. If you leave the UPS unplugged long enough to discharge (this may take quite a while even with a good size light bulb!), the UPS should signal a battery failure in a similar fashion, e.g.,

CTS DSR DCD RNG DTR RTS STATUS
0 0 0 1 0 1
LOW 0 0 0 1 0 1
LOW 0 0 0 1 0 1
LOW 0 0 0 1 0 1
LOW

7. At this point, you should know the power failure and low battery signals. Now we must determine the appropriate UPS shutdown signal. Fortunately, for most UPS systems, there are only 4 possible simple signals. With the UPS on battery power (e.g., unplugged), try adding each of the following lines into /etc/powstatd.conf in turn:

kill dtr 0
kill dtr 1
kill rts 0
kill rts 1

for each trial, try issuing the command:

% ./powstatd -k

one of the line specifications should cause the desk lamp or radio to turn off; that's the one you want. Important: be aware that many UPS have a "dead time" after the signal is sent before the UPS turns itself off; this "dead time" can be as long as 30-45 seconds! So don't be too impatient here or you won't know which signal is responsible for actually turning the UPS off.

8. At this point configuration should be complete. For example, for the Cyberpower Power99 325/385/450/500VA models, a reasonable /etc/powstatd.conf configuration file reads:

watch ttyS0
fail cts 0
low dcd 0
init rts 1
init dtr 0
kill dtr 1

9. If you have other machines running off the same UPS, include one or more slave entries specifying their names in the master's configuration file:

slave slave1.domain.edu
slave slave2.domain.edu

The slave machines' configuration files /etc/powstatd.conf should contain a single line specifying the name of the master machine that is actually monitoring the UPS that also powers the slave:

watch master.domain.edu

If you intend to run more than 2 slaves off a very large UPS, you will need to adjust the MAXSLAVES parameter in the source code accordingly and then recompile.

If powstatd is compiled with the appropriate security option enabled, encryption is used to protect slaves from malicious shutdown messages. An identical password directive should therefore appear in both master and slave configuration files:

password MyPasswordHere

In addition to encrypting status information, powstatd will encrypt generate and check timestamps in order to foil replay attacks.

10. Make sure your inittab file contains appropriate lines to invoke powstatd.fail, powstatd.low, and powstatd.ok:

# UPS signals a power outage.
pf:12345:powerfail:/sbin/powstatd.fail

# UPS signals power restored before the shutdown kicks in.
pr:12345:powerokwait:/sbin/powstatd.ok

# UPS signals low battery power: emergency shutdown.
pn:12345:powerfailnow:/sbin/powstatd.low

11. Edit scripts powstatd.ok, powstatd.fail, and powstatd.low to adjust time parameters, if desired.

12. "make install", then reboot the machine. If you don't want to reboot, issue instead:

% /etc/rc.d/init.d/powstatd start
% /sbin/init q

How It Works:

powstatd is initiated as a daemon in runlevels 3 and 5.

A UPS can only be in one of three states; OK, FAIL, or LOW. Usually, when the main power is on, the UPS is operating in the OK state; when power fails, the UPS changes to FAIL mode, from which it can either recover and return to OK (if the power is restored) or can move to LOW (if the battery starts running out of juice before the power returns).

powstatd monitors the UPS condition. When the state changes, powstatd writes the new state of the UPS in /etc/powerstatus and then signals init (the mother of all processes) of the change in the UPS condition. The init process receives this notice (a SIGPWR interrupt) and checks /etc/powerstatus to see if it contains "OK", "FAIL" or "LOW".

The contents of /etc/powerstatus tells init (which is configured by the /etc/inittab file) to run one of three scripts: powstatd.fail, powstatd.ok, or powstatd.low The init process then removes /etc/powerstatus so as not to be confused on subsequent interrupts.

powstatd.fail

initiates a timed shutdown -h (halt) in background, on the assumption that if power is restored the shutdown can be cancelled.

powstatd.ok

cancels the running shutdown and notifies all users that power is restored and no shutdown is imminent.

powstatd.low

cancels the running shutdown and initiates an immediate shutdown -h in foreground; this means once the UPS tells you the battery is low, you will indeed shutdown (there is no recovery).

Note that as you halt the machine, the shutdown sequence invokes powstatd one last time, but this time with the kill flag (-k), forcing the UPS to turn off, but only if the UPS is indeed in either the FAIL or LOW state (in any case, most supplies will ignore the kill signal if power is still available). In this fashion, once the power eventually returns (even after a day or two), the system should automatically restart without intervention.

Troubleshooting:

1. If your machine doesn't seem to notice power status changes even when the UPS daemon is signalling them, try adjusting the location of the powerstatus file by changing the value of STATUS in the Makefile and recompiling. Some versions of the init process look in /var/log/powerstatus rather than the default /etc/powerstatus.

2. If your machine keeps shutting down even when the power is on, you're probably watching the wrong serial line. To recover, try rebooting in single user mode (issue "linux 1" at the LILO prompt) and disable powstatd by renaming /etc/powstatd.conf to something else. Reboot and you should be able to fix the configuration.

3. Some older UPS systems as well as some homebuilt cable connections (see the UPS HowTo) may require that UPS shutdown signals be sent on the transmission line rather than on one of the signaling lines. Usually, this implies that a serial break signal (e.g., a long series of zeros) is required for the UPS to shut down. For these situations, you can use the special configuration file command

kill break

to obtain the appropriate behavior.

4. If your slave machines keep rejecting seemingly valid status messages from the master when using encrypted master/slave communication, first make sure they are running the same version of the software. Otherwise, try changing the definition of "outdated" at compile time (MAXCLOCKDRIFT) and recompiling. If you are not using NTP or some other mechanism to ensure that master and slave clocks are reasonably synchronized, you may well be better off running powstatd compiled without -DSECURE.

5. Some older versions of init are not capable of invoking one of several different scripts (e.g., powstatd.ok, powstatd.fail, powstatd.low) on receipt of SIGPWR under different circumstances. Instead, they always invoke the same script, which must then handle the control logic (i.e., deciding whether to shutdown gracefully, abort a shutdown, or shutdown immediately) internally (SPARC/Solaris and SGI/Irix apparently fall in this catagory). If you have such a version of init, look at the sample script powstatd.dumb included in the distribution for an example of how to go about handling this case.

ACKNOWLEDGEMENTS

I learned a lot from reading the publically-available source code for other UPS monitoring packages, like genpower, powerd and upsd. I wrote powstatd primarily because the exact combination of features or configuration options I required were not available with these other packages.

Peter Galbraith ([email protected]), the powstatd Debian package maintainer, provided numerous suggestions and bug fixes, as did Philippe Troin ([email protected]), who was the first to suggest using, e.g., MD5-based digital signatures to avoid malicious shutdowns. Nick Holgate ([email protected]) suggested an extension to powstatd signaling capabilities in order to support UPS systems that require a break signal for shutdown. Nicolas Simonds ([email protected]) provided information about changes to the code for both SPARC/Solaris and SGI/Irix.

TEA, or the Tiny Encription Algorithm, is due to David Wheeler and Roger Needham of the Cambridge Computer Laboratory. Their implementation, used here, is in the public domain.

Alberto Maria Segre
[email protected]
S378 Pappajohn Building
The University of Iowa
Iowa City, IA  52242-1000.