Imported Upstream version 2.4.3

This commit is contained in:
arnaud.quette@free.fr 2010-03-26 00:20:59 +01:00
commit 26fb71b504
446 changed files with 148951 additions and 0 deletions

822
docs/FAQ Normal file
View file

@ -0,0 +1,822 @@
Desc: Frequently Asked Questions
File: FAQ
Date: 20 January 2006
Auth: Russell Kroll <rkroll@exploits.org>
Arnaud Quette <aquette.dev@gmail.com>
-----------------------------------------------------------------------------
Q: I just upgraded, and ...
A: You have read UPGRADING in the base directory of the distribution,
right? If not, go read it now, then come back to this file if your
question wasn't answered in there.
-----------------------------------------------------------------------------
Q: upsstats says "Error: can't open template file (upsstats.html)".
How do I fix this?
A: Go into your configuration path (/usr/local/ups/etc by default) and
copy the sample template files over to their real names. The sample
template files are installed with 'make install-cgi-conf' and can
also be found inside the source distribution in the conf directory.
-----------------------------------------------------------------------------
Q: upsmon fails the login and says "username required" now.
A: Go read the UPGRADING file again.
-----------------------------------------------------------------------------
Q: My 1.4 CGI programs won't talk to my 2.0 upsd. What should I do?
A: Upgrade the CGI programs to 2.0. While 1.4 was intended as a
compatibility tree that used the new protocol by default, the CGI
programs were not upgraded at the same time. The 1.4 versions
still use the old REQ protocol, and your 2.0 upsd expects GET.
-----------------------------------------------------------------------------
Q: I just upgraded from 1.2 and upsmon now fails to start, saying
"Fatal error: insufficient power configured!". Why?
A: You didn't read the top of the error, where upsmon says that it
ignored the invalid MONITOR line because UPS directives now require
a UPS name. It also means you didn't see the same warning in
UPGRADING.
At least you saw this in the FAQ before asking the list.
-----------------------------------------------------------------------------
Q: My UPS driver now says it's "broken", and won't start. What now?
Q: My favorite UPS driver disappeared after an upgrade. What now?
A: Drivers are occasionally removed from the tree if they are no longer
receiving maintenance, or sometimes renamed to better reflect their
hardware support scope or replaced by a more generic driver.
There have been several architectural changes to the driver code
in recent times, and drivers which were not converted by someone
are eventually dropped.
This is called progress. We do this in order to avoid a situation
where someone believes that a driver is being maintained when it is
actually rotting slowly in the tree. It also keeps the tree free of
old compatibility hacks for code that nobody actually uses anyway.
To get a driver back into current releases, you need to convert it
yourself or get someone to do it for you. This is not difficult.
The hardest part of any driver is decoding the protocol, and that's
already been done in the old version.
-----------------------------------------------------------------------------
Q: I just upgraded and now I can't talk to older versions.
A: Version 2.0 can't communicate with anything before 1.4 due to the
protocol changes. Version 1.4 can communicate with both 2.0 and
most older versions since it was a transitional release and has
compatibility code for both protocols.
-----------------------------------------------------------------------------
Q: My UPS driver program won't work. I'm starting it as root, and root
owns the device, so what's the problem?
A: The drivers drop root privileges long before the serial port is
opened. You'll need to change the permissions on that port so that
their new user id can access it. Normally this is "nobody", but it
may be changed at compile-time by using configure --with-user.
Read the error message. If you have a permissions mismatch, then
you'll see something like this:
Network UPS Tools - APC Smart protocol driver 0.60 (1.1.7)
This program is currently running as youruid (UID 1234)
/dev/ttyS2 is owned by user root (UID 0), mode 0600
Change the port name, or fix the permissions or ownership
of /dev/ttyS2 and try again.
Unable to open /dev/ttyS2: Permission denied
Now is a good time to point out that using "nobody" is a bad idea,
since it's a hack for NFS access. You should create a new role
account (perhaps called "ups" or "nut"), and use that instead.
Also, scroll down to the "security domains" question to see an
even better way of restricting privileged operations. Neither the
drivers nor upsd ever need root powers, and that answer tells you
how to make it work.
A: You can also specify a user with "user=" in the global part of
ups.conf. Just define it before any of your [sections]:
user = nut
[myups]
driver = mge-shut
port = /dev/ttyS0
-----------------------------------------------------------------------------
Q: upsc, upsstats, and the other clients say "access denied". The device
communication port (serial, USB or network) permissions are fine, so what
gives?
A: In this case, "access denied" means the access to upsd, not the device
communication port. You're being denied since the system has no
permission to speak to upsd according to the access controls.
There can be various reasons. To fix it, check:
- the LISTEN directive in upsd.conf. It should allow your local or remote
access method,
- your firewall rules. Port 3493/tcp must be opened to incoming connexions,
- your tcp-wrappers configuration (hosts.allow and hosts.deny).
Refer to the upsd(8) and upsd.conf(5) manpages for more information.
-----------------------------------------------------------------------------
Q: I have an APC Smart-UPS connected with a grey APC cable and it won't
work. The Back-UPS type in the genericups driver works but then I
don't get to use all the nifty features in there. Why doesn't the
right driver work?
A: The problem lies in your choice of cable. APC's grey cables
generally only do "dumb" signalling - very basic yes/no info about
the battery and line status. While that is sufficient to detect a
low battery condition while on battery, you miss out on all the
goodies that you paid for.
Note that the 940-0095B happens to be a grey cable, but it is actually
a dual mode cable and can be used in smart mode. If you have
this cable, you need to edit your ups.conf to look like this:
[myups]
driver = apcsmart
port = /dev/whatever
cable = 940-0095B
All other grey cables from APC are assumed to be "dumb".
If your grey cable isn't the 940-0095B, the solution is to dump that
cable and find one that supports APC's "smart" signalling. Typically
these come with the UPS and are black. If your smart cable has
wandered off, one can be built rather easily with some connectors and
cable - there's no fancy wiring or resistors.
See this URL for a handy diagram:
http://random.networkupstools.org/cables/940-0024C.jpg
There is also a text version of that diagram in the docs/cables
directory of the NUT source distribution. Either one should allow
you to build a good clone of APC's 940-0024C cable.
There are simpler solutions involving 3 wires that work just fine
too, but Powerchute won't find the loopback DTR-DCD and RTS-CTS and
will be annoyed. If you don't ever plan to use Powerchute, 3 wires
(RxD, TxD, GND) are sufficient.
It should also be noted that the genericups driver has no way to
detect the UPS, so it will fire up quite happily if it can open the
serial port. Merely having it start up is not necessarily an
indication of success. You should start it and then check the
status with upsc or similar to be sure that it's reading the
hardware properly.
-----------------------------------------------------------------------------
Q: Why does configure fail to find gd?
A: Recent versions of gd should be detected automatically through the
gdlib-config script. Note that gd 2.0.5 through 2.0.7 have an
unusable script, so upgrade to the newest version if you have one
of those installed.
If you're stuck with an older version of gd, you can use it if you
specify the flags manually. Look in gd's Makefile for "LIBS=",
then use that value when you call configure:
./configure --with-gd-libs="<whatever>" --with-cgi
If you don't have gd's Makefile available for some reason, you're
in for a lot of trial and error.
-----------------------------------------------------------------------------
Q: Why PNG? You used to generate GIF bars with upsimage back in 1998
or 1999...
A: http://www.burnallgifs.org/
-----------------------------------------------------------------------------
Q: Why doesn't upsd implement the functionality of upsmon? I have to
run THREE programs to monitor my UPS!
A: I try to follow the "tool for the job" philosophy. It may mean
more programs running, but the flexibility you get is usually
worth it.
Yes, the machine with the UPS attached will generally have 3
processes (driver, upsd, upsmon) running, but this design allows a
much bigger setup. Imagine a data room with a bunch of machines
all drawing power from the same UPS. The rest of them just run
upsmon.
Besides, if upsmon were rolled into upsd, upsd would get even
bigger than it is now. You'd have one less process, but the
RAM consumption would be pretty close to now.
See data-room.txt for more configuration ideas and explanations.
A: If this really bothers you, roll up your sleeves and use the
sockdebug code to write a "upsmon" type program that sits on top of
the state sockets. It won't work over the network, but it means
you don't need upsd. It also means only one host can monitor the
UPS.
This is also a good option to consider if you can't use networked
monitoring code for security or safety reasons.
See ideas.txt for more on this and other related topics.
-----------------------------------------------------------------------------
Q: Why isn't upssched part of upsmon?
A: Most users will never have any reason to use upssched. It's
complicated, and getting it right for your situation can be tricky.
Having it live in a separate program saves resources and lets most
people avoid it completely.
-----------------------------------------------------------------------------
Q: Why doesn't upsmon send a SIGPWR signal to init so it can deal with
power events?
A: New versions of the init man page taken from the sysvinit package
are saying that usage of SIGPWR is discouraged, since /dev/initctl
control channel is the preferred way of communication.
A: The name of the game is portability. Not everyone's init handles
that kind of signalling gracefully. What's more, some admins
might want to do things differently even if they have that kind of
init running.
So, to be compatible, upsmon just invokes a shell command. If you
want to use init's SIGPWR stuff, just put the right "kill" line in
a shell script and make upsmon call it. Everyone wins.
-----------------------------------------------------------------------------
Q: Why can't upsset read my upsset.passwd file?
A: You have an old version of upsset installed, since the current
version doesn't use that file. Install a new version and then try
it again.
Be sure to secure your CGI directory as instructed in the
upsset.conf.
-----------------------------------------------------------------------------
Q: Why won't bestups talk to my Best Fortress UPS?
A: There are at least two different protocols being used for hardware
with very similar names. The bestups driver tends to support the
units built around the newer "PhoenixTec" protocol.
Previous releases of this software included a driver called
bestfortress which supported the older Best hardware. See the
earlier entries about updating old drivers which have been removed
from the tree.
-----------------------------------------------------------------------------
Q: What's this about "data stale"?
A: It means your UPS driver hasn't updated things in a little while.
upsd refuses to serve up data that isn't fresh, so you get the
errors about staleness.
If this happens to you, make sure your driver is still running.
Also look at the syslog. Sometimes the driver loses the connection
to the UPS, and that will also make the data go stale.
Note: some very slow machines have trouble keeping up with the
serial ports during periods of extreme load. My old 486 used to
flip between "stale" and "OK" while running backups.
If this happens a lot, you might consider cranking up DEADTIME
in the upsmon.conf to suppress some of the warnings for shorter
intervals. Use caution when adjusting this number, since it
directly affects how long you run on battery without knowing
what's going on with the UPS.
Note: some drivers occasionally need more time to update than the
default value of MAXAGE (in upsd.conf) allows. As a result, they
are temporarily marked stale even though everything is fine. This
can happen with MGE Ellipse equipment - see the mge-shut man page.
In such cases, you can raise the value of MAXAGE to avoid these
warnings; try a value like 25 or 30.
-----------------------------------------------------------------------------
Q: Why do the client programs say "Driver not connected" when I try
to run them?
A: This means that upsd can't connect to the driver for some reason.
Your ups.conf entry might be wrong, or the driver might not be
running. Maybe your state path is not configured properly.
Check your syslog. upsd will complain regularly if it can't
connect to a driver, and it should say why it can't connect.
Note: if you jumped in with both feet and didn't follow the INSTALL
document, you probably started upsd by itself. You have to run
'upsdrvctl start' to start the drivers after configuring ups.conf.
-----------------------------------------------------------------------------
Q: Everything works perfectly during the shutdown, and the UPS comes
back on, but my system stays off. What's happening?
A: Assuming you don't have the problem in the next question, then you
probably have an ATX motherboard, have APM or ACPI enabled in your
kernel (assuming Linux here), and are reaching the 'halt' at the
bottom of your shutdown scripts.
Your machine obeys and shuts down, and stays down, since it
remembers the 'last state' when the UPS restarts.
One solution is to change your shutdown scripts so you never reach
that point. You *want* the system to die without reaching the
part where the kernel tells it to shut down. A possible script
might look like this:
# other shutdown stuff here (mount -o remount,ro ...)
if (test -f /etc/killpower)
then
/usr/local/ups/bin/upsdrvctl shutdown
sleep 600 # this should never return
# uh oh, we never got shut down! (power race?)
reboot
fi
halt -p
The other solution is to change your BIOS setting to "always power
on" instead of "last state", assuming that's possible.
-----------------------------------------------------------------------------
Q: My system has an ATX power supply. It will power off just fine, but
it doesn't turn back on. What can I do to fix this?
A: This depends on how clueful your motherboard manufacturer is, and
isn't a matter of the OS. You have to do one of the following
things depending on what's supported:
- Set a jumper on the motherboard that means "return after outage"
- Set something in the BIOS that says "power up after power failure"
- Try using something (like a capacitor) across the power button
to "push" it for you - this might not work if it needs a delay
- Hack the cable between the power supply and the motherboard to fool
it into powering up whenever line power is present
- Teach a monkey to watch the machine and press the power button
when the outage is over.
This might work, but it creates high produce bills.
If you can't use one of the first two options, give the board to
an enemy. Let them worry about it.
-----------------------------------------------------------------------------
Q: My PowerMac G4 won't power back up by itself (into Linux) after the
UPS shuts down. What can I do about this?
A: This is about the same situation as the ATX question above, only
worse. Earlier Macs apparently supported a hack where you could
cat some magic characters at /dev/adb to enable "server mode".
This would instruct the system to reboot while unattended.
From Usenet post <6boftzxz51.fsf@ecc-office.sp.cs.cmu.edu>:
# Send packet over the ADB bus to the PowerMac CUDA chip
# telling it to reboot automatically when power is restored
# after a power failure.
cat /etc/local/autoboot.adb > /dev/adb
autoboot.adb contains these three bytes (in hex): 01 13 01
Unfortunately, the hardware has evolved and there is no good
equivalent for this hack on today's systems.
If you find out how to do this, please send me some mail, since
this affects one of my systems and my stop-gap solution is getting
cranky.
Note: this question has been in the FAQ for over a year and
there's still no answer. Let me guess: everyone who runs a server
on Mac hardware has a team of trained monkeys, and feeds them
by growing bananas in the tropical environment formed by waste heat
from the equipment.
The rest of us are still waiting for the answer. Booting into the
Mac OS to frob the "file server" panel is not an acceptable
solution.
A: If you're on OS X, this is relatively simple to fix. Go to system
preferences, click on energy saver, click on the options tab, check
"Restart automatically after a power failure".
If you're on some other OS, hope they've figured out how to duplicate
the above in a non-simian manner.
-----------------------------------------------------------------------------
Q: I want to keep the drivers and upsd in their own security domains.
How can this be accomplished?
A: Using a few role accounts and a common group, you can limit access
to resources such as the serial port(s) leading to the UPS
hardware.
This is just an example. Change the values to suit your systems.
Create a user called 'nutdev' and another called 'nutsrv'. Put
them both in a group called 'nut'.
Change the owner of any serial ports that will be used to nutdev,
and set the mode to 0600. Then change the ownership of your state
directory (usually /var/state/ups) to nutdev.nut.
For my development system this yields the following /dev entries:
0 crw------- 1 nutdev tty 4, 64 Sep 3 17:11 /dev/ttyS0
0 crw------- 1 nutdev tty 4, 65 Sep 3 17:11 /dev/ttyS1
Switch to root, then start the drivers:
# /usr/local/ups/bin/upsdrvctl -u nutdev start
The listing for /var/state/ups then looks like this:
4 drwxrwx--- 2 nutdev nut 4096 Aug 20 18:37 .
4 drwxr-xr-x 4 root root 4096 May 14 21:20 ..
4 srw-rw---- 1 nutdev nut 0 Sep 3 17:10 apcsmart-ttyS0
4 srw-rw---- 1 nutdev nut 0 Sep 3 17:10 megatec-ttyS1
You may have to remove old socket or state files first if you are
changing to this security scheme from an older version. The drivers
will create new files with the right owners and modes.
Note that /var/state/ups is group writable since upsd will
place the upsd.pid file here.
You may have to change the groups of upsd.conf and upsd.users to
make them readable. These files should not be owned by nutsrv,
since someone could compromise the daemon and change the config
files. Instead, put nutsrv in a group ("nut" in this example), then
make the files owned by root.nut, with mode 0640.
Once the config files are ready, start upsd:
# /usr/local/ups/sbin/upsd -u nutsrv
Check your syslog to be sure everything's happy, then be sure to
update your startup scripts so it uses this procedure on your next
boot.
If you like this, you'll probably also find the chroot process to
be useful and interesting. See chroot.txt for more details.
-----------------------------------------------------------------------------
Q: What's the point of that 'security domains' concept above?
A: The point is limiting your losses. If someone should happen to
break into upsd in that environment, they should only gain access
to that one user account. Direct access to the serial device is
not possible, since that is owned by another user.
There is also the possibility of running the drivers and upsd in a
chroot jail. See the chroot.txt provided in the source
distribution for an example implementation.
Why give would-be vandals any sort of help?
Put it this way - I *wrote* good chunks of this stuff, and I still
run the programs this way locally. You should definitely consider
using this technique.
-----------------------------------------------------------------------------
Q: How can I make upsmon shut down my system after some fixed interval?
A: You probably don't want to do this, since it doesn't maximize your
runtime on battery. Assuming you have a good reason for it (see
the next entry), then look at upssched.txt or the upssched man
page for some ideas.
-----------------------------------------------------------------------------
Q: Why doesn't upsmon shut down my system? I pulled the plug and nothing
happened.
A: Wait. upsmon doesn't consider a UPS to be critical until it's both
'on battery' and 'low battery' at the same time. This is by design.
Nearly every UPS supports the notion of detecting the low battery
all by itself. When the voltage drops below a certain point, it
_will_ let you know about it.
If your system has a really complicated shutdown procedure, you
might need to shut down before the UPS raises the low battery flag.
For most users, however, the default behavior is adequate.
Ask yourself this: why buy a nice big UPS with the matching battery
and corresponding runtime and then shutdown early? If anything, I'd
rather have a few more minutes running on battery during which the
power might return. Once the power's back, it's business as usual
with no visible interruption in service.
If you purposely shut down early, you guarantee an interruption in
service by bringing down the box.
See upssched.txt for information on how you can shutdown early if
this is what you really want to do.
-----------------------------------------------------------------------------
Q: The CGI programs report "access to that host is not authorized" -
what's going on?
A: Those programs need to see a host in your hosts.conf before they
will attempt communications. This keeps people from feeding it
random "host=" settings, which would annoy others with outgoing
connection attempts from your system.
If your hosts.conf turns out to be configured correctly with
MONITOR entries and all that, check the permissions. Your web
server may be running the CGI programs as a user that can't read
the file.
If you run your web server in a chroot jail, make sure the programs
can still read hosts.conf. You may have to copy it into the jail
for this to work. If you do that, make sure it's not writable by
any of the user accounts which run inside the jail.
-----------------------------------------------------------------------------
Q: upsd is running, so why can't I connect to it?
A: Assuming you haven't changed the TCP port number on the command line
or at compile-time, then you probably have some sort of firewall
blocking the connection.
upsd listens on TCP port 3493 by default.
-----------------------------------------------------------------------------
Q: How do you make upsmon reload the config file?
Q: How do you make upsd reload the config file?
A: Either find the pid of the background process and send it a SIGHUP,
or just start it again with '-c reload'.
If you send the signals yourself instead of using -c, be sure you
hit the right process. There are usually two upsmons, and you
should only send signals to one of them. To be safe, read the pid
file.
-----------------------------------------------------------------------------
Q: I just bought a new WhizBang UPS that has a USB connector. How do
I monitor it?
A: There are several driver to support USB models.
- usbhid-ups supports various manufacturers complying to the HID standard,
- tripplite_usb supports various Tripp-Lite units,
- bcmxcp_usb supports various Powerware units.
Refer to the "driver-name" (8) manpage for more information.
-----------------------------------------------------------------------------
Q: What is this usbhid-ups (formerly newhidups) about?
A: The basic USB UPS support was done until NUT 2.2 using hidups. To allow
a wider support accross platforms for USB/HID compliant devices,
usbhid-ups driver uses libusb (which is available for a wide range of
operating systems) and libhid (currently, a modified internal version
of it).
As of NUT 2.2, usbhid-ups completely replaces the legacy hidups driver
and provide support for various manufacturers. At that time, it will
be renamed to usbhid-ups.
usbhid-ups is built automatically if possible (libusb development files
need to be installed) and installed by the "make install" command.
-----------------------------------------------------------------------------
Q: Why doesn't my package work?
Q: I can't run this because there's no package for it. Why isn't this
in a package yet?
A: Sorry, can't help you there. All official releases are source code
and are posted on http://www.networkupstools.org/ along with PGP
signatures for verification.
This means all packages have been built by a third party. If you
have an issue that's related to packaging, you will need to seek
help with whoever built it for you.
-----------------------------------------------------------------------------
Q: Why are there two copies of upsmon running?
A: It's not really two complete copies if your OS forks efficiently.
By default, upsmon runs most of the grunt work as an unprivileged
user and keeps a stub process around with root powers that can
only shut down the system when necessary. This should make it much
harder to gain root in the event a hole is ever discovered in
upsmon.
If this really bothers you and you like running lots of code as
root, start upsmon with -p and it will go back to being one big
process. This is not recommended, so don't blame me if something
bad happens in this mode.
-----------------------------------------------------------------------------
Q: I have <some problem> with <some old version> ...
A: Get the latest stable release, and see if it still happens. If it
goes away, it means someone else reported it and got it fixed a
long time ago.
If that doesn't work, try the latest development version.
If your problem is STILL there, then contact the mailing lists.
Hint: check the release date on the version you have. If it's more
than about 6 months old, there's probably a newer stable tree
version out there.
-----------------------------------------------------------------------------
Q: Do you have to use a serial connection to monitor the UPS?
What about direct network connections (SNMP or otherwise)?
A: No. NUT currently support USB communication through usbhid-ups,
tripplite_usb and bcmxcp_usb, and SNMP communication through snmp-ups.
Any time there is a gap in features, it's usually because the
group of people who own that hardware and the group of people who
write code don't overlap. The fix is to make them overlap -
turn an owner into a developer or vice-versa.
-----------------------------------------------------------------------------
Q: What happened to the patch I sent?
A: If a release goes by and your patch hasn't been included, it was
probably dropped. There can be a lot of patches waiting for
inclusion at some points, and occasionally some have to be
rejected.
Design issues or severe coding style problems can be the reason
for this. I try to point out what the problems are, but there are
limits. See developers.txt for some pointers on submitting
patches.
Sometimes patches are put on hold due to a feature freeze. If it
doesn't show up once the new version opens up, send it again.
-----------------------------------------------------------------------------
Q: I'm not much of a programmer. How can I help?
A: There's always work to be done outside of the realm of code bashing.
Documentation might not always be so clear. A user's perspective
is sometimes needed to appreciate this. Bug reports on a project's
documentation are just as valuable as those for the actual source.
Fielding questions on the mailing lists is also helpful. This
lets other people to focus on coding issues while allowing the
original poster to get some information at the same time. It's
quite a relief to open that mailbox and find that someone else
has already handled it successfully.
-----------------------------------------------------------------------------
Q: I replaced the battery in my APC Smart-UPS and now it thinks the
battery is low all the time. How do you fix this?
Q: My APC UPS keeps reporting "OL LB", even after it's been charging
for many hours. What can I do about this?
A: This happened to me, and some other people too. The combination of
our experiences should prove useful to you.
First, you need to realize that the UPS apparently stores data about
the battery, load, and runtime. After replacing the battery, it
needs to be clued in to the new situation. If the traditional
runtime calibration doesn't work, you have to try something a
little more drastic.
You need to *completely* drain the UPS while it has a good ground.
This means you can't just pull the plug. You also have to
disconnect it from the computer so this software won't shut it
down.
The easiest way to do this is to first unplug your computer(s) from
it, and plug in a token load like a lamp. Also, move the UPS to a
power strip that doesn't switch the ground line or an outlet that
you can switch off at your panel.
Once the UPS is up at 100% charge (this is important), disconnect
the power. It _must_ remain connected to the ground, or the
results may not be accurate. Ignore the sounds it makes, and go
away until it's done. Don't do anything to the front panel while
this is happening.
After all of this, put things back the way they should be and let
it charge up. You should find that it again gives reasonable
values and behavior, as it was when it was new.
Thanks to Matthew Dharm for helping me nail down this procedure.
-----------------------------------------------------------------------------
Q: multimon.cgi seems to be stuck at an old version, even though I
just installed a new one.
A: multimon was removed during the 1.1 development cycle. upsstats
now does everything it used to do, and then some. You should just
delete those files and start using upsstats directly.
-----------------------------------------------------------------------------
Q: OK, I switched to upsstats. Now it's giving me Celsius. I like
Fahrenheit. Where's the config file to switch it back?
A: Temperature scales are handled by the template files, so edit your
upsstats.html and change it from TEMPC to TEMPF.
-----------------------------------------------------------------------------
Q: Why is the mailing list ignoring me?
A: You probably asked a question that's answered in this FAQ or
somewhere else in the documentation and nobody wants to quote it
for you.
Convincing the other subscribers that you've actually read down this
far might be useful. You might mention "queequeg" for better results.
This URL may also be helpful:
http://www.catb.org/~esr/faqs/smart-questions.html
-----------------------------------------------------------------------------
Q: I found some information about another kind of UPS protocol you
don't support yet, but I don't know what to do with it. Can you
help?
A: If you're not a programmer, you can still help others by making
that protocol available. You might host the document somewhere and
send the URL to one of the mailing lists.
-----------------------------------------------------------------------------
Q: How can you answer questions to situations that nobody's encountered
yet? Isn't this a frequently asked questions file?
A: Magic.
A: It's both that and a frequently *anticipated* questions file, too.
The idea is to write it up in here so that nobody asks the mailing
list when it finally does get released.
-----------------------------------------------------------------------------

13
docs/Makefile.am Normal file
View file

@ -0,0 +1,13 @@
# nothing to build here, but still need a Makefile to define which
# files to distribute
EXTRA_DIST = acpi.txt big-servers.txt chroot.txt \
commands.txt config-files.txt configure.txt contact-closure.txt \
data-room.txt design.txt developers.txt FAQ hid-subdrivers.txt \
ideas.txt macros.txt megatec.txt new-drivers.txt new-names.txt \
nut-hal.txt osd-notify.txt \
pager.txt powersaving.txt protocol.txt README shutdown.txt snmp.txt \
sock-protocol.txt ssl.txt upssched.txt cables/apc-rs500-serial.txt \
cables/apc.txt cables/ge-imv-victron.txt cables/imv.txt \
cables/mgeups.txt cables/powerware.txt cables/repotec.txt \
cables/sms.txt

423
docs/Makefile.in Normal file
View file

@ -0,0 +1,423 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# nothing to build here, but still need a Makefile to define which
# files to distribute
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = docs
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nut_arg_with.m4 \
$(top_srcdir)/m4/nut_check_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.m4 \
$(top_srcdir)/m4/nut_check_libusb.m4 \
$(top_srcdir)/m4/nut_check_libwrap.m4 \
$(top_srcdir)/m4/nut_check_os.m4 \
$(top_srcdir)/m4/nut_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_NAME = @OS_NAME@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
cgiexecdir = @cgiexecdir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
hotplugdir = @hotplugdir@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
EXTRA_DIST = acpi.txt big-servers.txt chroot.txt \
commands.txt config-files.txt configure.txt contact-closure.txt \
data-room.txt design.txt developers.txt FAQ hid-subdrivers.txt \
ideas.txt macros.txt megatec.txt new-drivers.txt new-names.txt \
nut-hal.txt osd-notify.txt \
pager.txt powersaving.txt protocol.txt README shutdown.txt snmp.txt \
sock-protocol.txt ssl.txt upssched.txt cables/apc-rs500-serial.txt \
cables/apc.txt cables/ge-imv-victron.txt cables/imv.txt \
cables/mgeups.txt cables/powerware.txt cables/repotec.txt \
cables/sms.txt
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu docs/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

9
docs/README Normal file
View file

@ -0,0 +1,9 @@
When creating files in here, use the following 4 headers:
Desc: A brief description of the document
File: The filename (this is for tracking which one is the original)
Date: The date of last modification
Auth: The author, i.e. "First Last <foo@example.com>".
Note: anything in the form <.*@.*> will be removed when converted to HTML
to reduce the number of e-mail addresses harvested from the web servers.

32
docs/acpi.txt Normal file
View file

@ -0,0 +1,32 @@
Desc: Equivalence between ACPI and NUT variable naming
File: acpi.txt
Date: 30 September 2005
Auth: Arnaud Quette <aquette.dev@gmail.com>
This document presents an equivalence table between ACPI data
and NUT variable naming.
+-------------------------------------------------------+---------------------------------------+
|PowerSummary.CapacityMode | percent | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.DesignCapacity | 100 | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.FullChargeCapacity | 100 | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Rechargeable | true / yes / 1 | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.ConfigVoltage | output.voltage.nominal | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.WarningCapacityLimit | ? battery.charge.low | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.RemainingCapacityLimit | battery.charge.low | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.CapacityGranularity1 | ? | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.CapacityGranularity2 | ? | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iProduct | ups.model | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iSerialNumber | ups.serial | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iDeviceChemistry | battery.type | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.iOEMInformation | ? | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Discharging | ups.status = DISCHRG | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Charging | ups.status = CHRG | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.BelowRemainingCapacityLimit | ups.status = LB | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Current | ? output.current | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.RemainingCapacity | battery.charge | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.Voltage | output.voltage | +-------------------------------------------------------+---------------------------------------+
|PowerSummary.RemainingCapacityLimit | battery.charge.low | +-------------------------------------------------------+---------------------------------------+
| PowerSummary.ACPresent | ups.status = OL |
+-------------------------------------------------------+---------------------------------------+

68
docs/big-servers.txt Normal file
View file

@ -0,0 +1,68 @@
Desc: Typical setups for big servers
File: big-servers.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
By using multiple MONITOR statements in upsmon.conf, you can configure
an environment where a large machine with redundant power monitors
multiple separate UPSes. For the examples in this document, I will use
a HP NetServer LH4 in the stock configuration with 3 of the 4 power
supplies installed.
Compared to some systems, the LH4 is unusual because it has common power
cords for multiple power supplies. One cord feeds two supplies. As a
result, each UPS drives two of the power supplies, so losing that UPS
affects both at the same time.
For our examples, UPS "Alpha" is connected to the cord that drives the
two power supplies, and ups "Beta" is connected to the other with just a
single power supply.
Since the server needs two supplies to stay alive, we can lose "Beta" at
any time, but losing "Alpha" is a showstopper. We make a note of them
when configuring upsmon:
MONITOR ups-alpha@myhost 2 monuser mypass master
MONITOR ups-beta@myhost 1 monuser mypass master
MINSUPPLIES 2
With that configuration, upsmon will only shut down when Alpha reaches
a critical (on battery + low battery) condition, since Beta by itself
is not enough to keep the system running. Beta, on the other hand,
can go up and down as much as it wants and nothing will happen as long
as the other one keeps working.
The MINSUPPLIES line tells upsmon that we need at least 2 power supplies
to be receiving power from a good UPS (on line or on battery, just not
on battery and low battery).
Adding redundancy
=================
The above example assumed the stock hardware configuration. Let's say
we have successfully cajoled the boss into providing the money for a
fourth power supply. Now both power cords run two power supplies, and
the system is maxed out in terms of redundancy.
The upsmon.conf must be updated to reflect this:
MONITOR ups-alpha@myhost 2 monuser mypass master
MONITOR ups-beta@myhost 2 monuser mypass master
MINSUPPLIES 2
Beta is now driving two power supplies, so we upgrade its power value.
This means that either Alpha *or* Beta can totally shut down and the
server will be able to keep running.
As an added bonus, this means you can move a running server from one UPS
to another without bringing it down since the minimum power will be
provided at all times.
Other configurations
====================
There are a lot of ways to handle this and they all come down to how many
power supplies, power cords and independent UPS connections you have. A
system with a 1:1 cord:supply ratio has more wires stuffed behind it, but
it's much easier to move things around since any given UPS drives a smaller
percentage of the overall power.

View file

@ -0,0 +1,34 @@
Desc: APC UPS cable - for Back-UPS RS 500
File: apc-rs500-serial.txt
Date: 14 July 2004
Auth: Russell Kroll <rkroll@exploits.org>, Martin Edlman <edlman@fortech.cz>
This document was constructed from a mail from Martin. He figured out
the pinouts to make the Back-UPS RS 500 work with a normal serial port.
Here are the details:
---
UPS side PC side
RJ45 (8 pins) DB9F
1 orange/white 2,8,9
2 orange 1
3 green/white chassis/ground
4 blue -
5 blue/white -
6 green 5
7 brown/white 4,6
8 brown -
+---+
+-----+ +-----+
| |
+---------------+
8 7 6 5 4 3 2 1
view from back (cable entry)
---
Note this results in OL=-CTS, LB=DCD, SD=ST, CP=RTS, so it should work
with the existing genericups type 20.

233
docs/cables/apc.txt Normal file
View file

@ -0,0 +1,233 @@
Desc: APC UPS cables
File: apc.txt
Date: 12 Februari 2010
Auth: Arjen de Korte <adkorte-guest@alioth.debian.org
http://lists.alioth.debian.org/pipermail/nut-upsuser/2005-August/000118.html
+-----------------------------------------------------------------+
| |
| Black APC 940-0024C Smart Signalling UPS Cable Wiring Diagram |
| This information is verified and tested to be 100% correct. |
| |
+-----------------------------------------------------------------+
| |
| DB9M(UPS) 2m Cable DB9F(Computer) |
| --------- -------- -------------- |
| |
| (SHELL)<---------+----//----+----------------<(SHELL) |
| | | |
| - - |
| | | | | |
| CHASSIS 9<--------------//---------------------<5 SG |
| | | | | |
| TXD 2<--------------//---------------------<2 RXD |
| | | | | |
| RXD 1<--------------//---------------------<3 TXD |
| | | | | |
| - - +--<1 DCD |
| | |
| +--<4 DTR |
| NOTES: |
| Cable type is shielded 28AWG. +--<7 RTS |
| The DB shells are connected | |
| to each other via the shield. +--<8 CTS |
| |
+-----------------------------------------------------------------+
| |
| Operation: The UPS communicates with the Computer via |
| ordinary RS-232 serial protocol at 2400-8N1 with software |
| flow control. Jumpered pins in the DB9F connector are for |
| automatic or PNP cable identification by UPS software. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
| |
| Gray APC 940-0020B Simple Signalling UPS Cable Wiring Diagram |
| This information is verified and tested to be 100% correct. |
| |
+-----------------------------------------------------------------+
| |
| DB9M(UPS) 2m Cable DB9F(Computer) |
| --------- -------- -------------- |
| |
| (SHELL)<-------+----//----+-------------------<(SHELL) |
| | | |
| CHASSIS 9<--+ - - |
| | | | | | |
| COMMON 4<--+---------//------------------------<5 SG |
| | | | | |
| POWER-FAIL 2<------------//------------------------<8 CTS |
| | | | | |
| SHUTDOWN 1<------------//------------------------<4 DTR |
| | | | | |
| BATTERY-LOW 5<------------//--------47K--+--47K--+--<7 RTS |
| | | | | | | |
| - - | E | |
| NOTES: |B |<--+ |
| RTS must be held at +V SPACE. +---| |
| TXD must be held at -V MARK. 2N3906 |---+--<1 DCD |
| All resistors are 5% 1/8W CF. C | |
| Cable type is shielded 28AWG. 4K7 |
| The DB shells are connected | |
| to each other via the shield. +--<3 TXD |
| |
+-----------------------------------------------------------------+
| |
| Operation: The UPS communicates with the Computer via |
| the RS-232 handshaking lines only, and does not use any |
| serial protocol. Upon power fail, the UPS forces CTS to |
| -V MARK. When the battery is low, the UPS forces DCD to |
| +V SPACE via the transistor. When the Computer forces a |
| +V SPACE on DTR, the UPS will shut down and turn off. |
| Presence of the cable can be sensed by signaling on TXD |
| while monitoring DCD. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
| |
| Gray APC 940-0095A Smart Signalling UPS Cable Wiring Diagram |
| This information is verified and tested to be 100% correct. |
| |
+-----------------------------------------------------------------+
| |
| DB9M(UPS) 2m Cable DB9F(Computer) |
| --------- -------- -------------- |
| |
| (SHELL)<-------+----//----+--------------------<(SHELL) |
| | | |
| CHASSIS 9<--+ - - |
| | | | | | |
| COMMON 4<--+---------//-------------------------<5 SG |
| | | | | |
| BATTERY-LOW 5<------------//--------47K--+--47K--+---<4 DTR |
| | | | | | | |
| | +---<6 DSR |
| | | | | | E | |
| NOTES: |B |<--+---<8 CTS |
| DTR must be held at +V SPACE. | | +---| |
| TXD must be held at -V MARK. 2N3906 |---+---<1 DCD |
| All resistors are 5% 1/8W CF. | | C | |
| Cable type is shielded 28AWG. 4K7 |
| The DB shells are connected | | | |
| to each other via the shield. +----4K7---+---<3 TXD |
| | | | | | |
| | |
| | | | | | 1N4148 |
| SHUTDOWN 1<------------//----------+----|<|-------<7 RTS |
| | | | | K A |
| POWER-FAIL 2<------------//---------------------+---<2 RXD |
| | | | | | |
| - - +---<9 RI |
| |
+-----------------------------------------------------------------+
| |
| Operation: The UPS can communicate with the Computer |
| solely via the RS-232 handshaking lines, or via RS-232 |
| serial protocol at 2400-8N1 with software flow control. |
| Upon power fail, the UPS forces RI to -V MARK. When the |
| battery is low, the UPS forces DCD to +V SPACE via the |
| transistor. When the Computer forces a +V SPACE on RTS, |
| the UPS will shut down and turn off. Jumpered pins in |
| the DB9F connector allow for automatic automatic or PNP |
| cable identification by UPS software. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
| |
| Universal APC serial extension cable for use in conjunction |
| with an APC UPS cable. This cable is verified to work. |
| |
+-----------------------------------------------------------------+
| |
| DB9M to UPS cable Shielded Cable DB9F to Computer |
| ----------------- --- 28AWG ---- ---------------- |
| |
| (SHELL)<----+-------------//-------------+----<(SHELL) |
| | | |
| - - |
| | | | | |
| 1<------------------//------------------<1 DCD |
| | | | | |
| 2<------------------//------------------<2 RXD |
| | | | | |
| 3<------------------//------------------<3 TXD |
| | | | | |
| 4<------------------//------------------<4 DTR |
| | | | | |
| 5<------------------//------------------<5 SG |
| | | | | |
| 6<------------------//------------------<6 DSR |
| | | | | |
| 7<------------------//------------------<7 RTS |
| | | | | |
| 8<------------------//------------------<8 CTS |
| | | | | |
| 9<------------------//------------------<9 RI |
| | | | | |
| - - |
| NOTE: The DB shells are connected to each other via the shield. |
| |
+-----------------------------------------------------------------+
| |
| Male (pins) Female (holes) |
| DB9 RS-232 PC |
| type connector 1 5 5 1 |
| ---------------- _______________ _______________ |
| Pinout numbering \ . . . . . / \ o o o o o / |
| looking into the \ . . . . / \ o o o o / |
| end of the cable ----------- ----------- |
| 6 9 9 6 |
| |
| NOTE: Solder a wire to the metal shell for use as a FRAME-GND |
| |
+-----------------------------------------------------------------+

View file

@ -0,0 +1,59 @@
Desc: IMV Victron UPS cables
File: victron.txt
Date: 13 April 2002
Auth: Daniel Prynych <Daniel.Prynych@hornet.cz>
Data cable 1 for UPS:
GE/IMV/Victron Match - 500 700 700L 1000 1000L 1500 2200 3000
GE/IMV/Victron NetPro (NetPro 19 ") - 600 1000 1200 2000 3000 4000
Driver: victronups (newvictronups)
UPS PC 9 pin [2~connector
1 --------- 3
2 --------- 2
5 --------- 5 GND
4 DTR
|
1 DCD
------------------------------------
Data cable 2 for UPS:
GE/IMV Victron Match Lite (all types)
Driver: victronups (newvictronups)
UPS PC 9 pin connector
2 --------- 3
3 --------- 2
4 --------- 5 GND
4 DTR
|
1 DCD
-----------------------------------
Crack cable: for UPS
Victron Lite (no IMV Victron Match Lite)
Driver: genericsups
UPS PC 9 pin connector
1 ---------- 4 DTR
7 ---------- 1 DCD ----------+
9 ---------- 8 CTS -----+ |
5 ---------- 5 GND | |
| |
R R 6,8k - 10k ohm
| |
7 RTS------+----+
----------------------------------------------
GE is General Electric Company.
On July 31, 2001, the General Electric Company, acquisited IMV (Victron) company.

12
docs/cables/imv.txt Normal file
View file

@ -0,0 +1,12 @@
Desc: IMV Match19 700 - 1500
File: imv.txt
Date: 06 April 2002
Auth: Niels S. Richthof <niels@richthof.de>
"UPS-VIC23-2" PC 9 pin connector
1 ---------------- 3
2 ---------------- 2
4 ---------------- 7
5 ---------------- 5

52
docs/cables/mgeups.txt Normal file
View file

@ -0,0 +1,52 @@
Desc: MGE UPS SYSTEMS serial cable
File: mgeups.txt
Date: 10 April 2002
Auth: Arnaud Quette <arnaud.quette@free.fr> or <arnaud.quette@mgeups.com>
This document describes the cable for MGE smart protocols : UTalk (ASCII),
and SHUT (Serial HID UPS Transfer, binary) .
First notice that MGE UPS SYSTEMS supply a standard cable, bundled with
the UPS unit and compatible with MS Windows and Unices (Ref 66049). For
more information, see below note about serial cable, PnP and Unix.
Cable description
-----------------
UPS COMPUTER
MALE DB9 FEMALE DB9
2 ---------------- 2 TX
3 ---------------- 3 RX
5 ---------------- 5 GND
-- 4
|
-- 6
-- 7
|
-- 8
UPS connector description
-------------------------
5 4 3 2 1
_______________
\o o o o o/
\ o o o o/
---------
9 8 7 6
9 pin Male DB-9 connector on UPS
Notes
-----
- this is a universal serial cable, so it should work with
any MGE serial model.
- max. length of cable is 1,80 m.
- Computer pin 6 (RTS) is reserved for PnP use, which could
trouble communication on some Unices if cabled. However, new
models (such as Ellipse, Evolution, Pulsar and Comet EXtreme,
EXtreme C, ...) handle this, so you can safely cable pin 6 or
use a standard (bundled) "windows" cable (Ref 66049).

26
docs/cables/powerware.txt Normal file
View file

@ -0,0 +1,26 @@
Desc: Powerware 3115 factory cable
File: powerware.txt
Date: 22 July 2005
Auth: various
1) Powerware 3115 factory cable
From Peter Åstrand <altic@lysator.liu.se>
UPS PC 9 pin connector
5 --------- 1
2 --------- 2
1 --------- 3
4 --------- 5
6 --------- 8
2) Powerware 5119 RM Cable Layout
From Daniel Thompson <danht@callthenet.com>
UPS <-----------> PC
DB9-M <--------> DB9-F
Pin 1 <-----------> Pin 3
Pin 2 <-----------> Pin 8
Pin 4 <-----------> Pin 4
Pin 5 <-----------> Pin 1
Shells Grounded Both Ends

26
docs/cables/repotec.txt Normal file
View file

@ -0,0 +1,26 @@
Desc: Repotec 800A (800VA) & 162A (1600VA) cable
File: repotec.txt
Date: 11 April 2001
Auth: Theodor Milkov <zimage@delbg.com>
PC UPS
1 (DCD) <----+---------- 2
|
R 5.6k
|
7 (RTS) >----+
3 (Tx) >--------------- 6
4 (DTR) <----+---------- 5
|
R 5.6k
|
8 (CTS) >----+
5 (GND) -------------+-- 4
|
+-- 7

16
docs/cables/sms.txt Normal file
View file

@ -0,0 +1,16 @@
Desc: SMS UPS cables, for Upsilon compatible SMS UPS
File: sms.txt
Date: 9 October 2001
Auth: Marcio Gomes <tecnica@microlink.com.br>
COMPUTER UPS
FEMEA DB9 MACHO DB9
2 ---------- 6
3 ---------- 9
4/8 ---------- 5
5 ---------- 8
- This cable is working with Manager III 1300 VA and 650 VA, SMS Ups's
- Jump in computer side pins 4/8 and conect to pin 1 in UPS side
- Use megatec driver from Nut Package

110
docs/chroot.txt Normal file
View file

@ -0,0 +1,110 @@
Desc: chrooting and other forms of paranoia
File: chroot.txt
Date: 24 August 2003
Auth: Russell Kroll <rkroll@exploits.org>
It has been possible to run the drivers and upsd in a chrooted jail for
some time, but it involved a number of evil hacks. The 1.3 series adds
much saner chroot behavior, using BIND 9 as an inspiration.
The old way involved creating an entire tree, complete with libraries, a
shell (!), and many auxiliary files. This was hard to maintain and
could have become an interesting playground for an intruder. The new
way is minimal, and leaves little in the way of usable materials within
the jail.
This document assumes that you already have created at least one user
account for the software to use. If you're still letting it fall back
on "nobody", stop right here and go figure that out first. It also
assumes that you have everything else configured and running happily all
by itself.
Essentially, you need to create your configuration directory and state
path in their own little world, plus a special device or two.
For the purposes of this example, the chroot jail is /chroot/nut. The
programs have been built with the default prefix, so they are using
/usr/local/ups. First, create the confpath and bring over a few files.
mkdir -p /chroot/nut/usr/local/ups/etc
cd /chroot/nut/usr/local/ups/etc
cp -a /usr/local/ups/etc/upsd.users .
cp -a /usr/local/ups/etc/upsd.conf .
cp -a /usr/local/ups/etc/ups.conf .
I'm using 'cp -a' to maintain the permissions on those files.
Now bring over your state path, maintaining the same permissions as
before.
mkdir -p /chroot/nut/var/state
cp -a /var/state/ups /chroot/nut/var/state
Next we must put /etc/localtime inside the jail, or you may get very
strange readings in your syslog. You'll know you have this problem if
upsd shows up as UTC in the syslog while the rest of the system doesn't.
mkdir -p /chroot/nut/etc
cp /etc/localtime /chroot/nut/etc
Note that this is not "cp -a", since we want to copy the *content*, not
the symlink that it may be on some systems.
Finally, create a tiny bit of /dev so the programs can enter the
background properly - they redirect fds into the bit bucket to make sure
nothing else grabs 0-2.
mkdir -p /chroot/nut/dev
cp -a /dev/null /chroot/nut/dev
Try to start your driver(s) and make sure everything fires up as before.
upsdrvctl -r /chroot/nut -u nutdev start
Once your drivers are running properly, try starting upsd.
upsd -r /chroot/nut -u nutsrv
Check your syslog. If nothing is complaining, try running clients like
upsc and upsmon. If they seem happy, then you're done.
symlinks
--------
After you do this, you will have two copies of many things, like the
confpath and the state path. I recommend deleting the 'real'
/var/state/ups, replacing it with a symlink to
/chroot/nut/var/state/ups. That will let other programs reference the
.pid files without a lot of hassle.
You can also do this with your confpath and point /usr/local/ups/etc at
/chroot/nut/usr/local/ups/etc unless you're worried about something
hurting the files inside that directory. In that case, you should
maintain a 'master' copy and push it into the chroot path after
making changes.
upsdrvctl itself does not chroot, so the ups.conf still needs to be in
the usual confpath.
upsmon
------
This has not yet been applied to upsmon, since it can be quite
complicated when there are notifiers that need to be run. One
possibility would be for upsmon to have three instances:
- privileged root parent that listens for a shutdown command
- unprivileged child that listens for notify events
- unprivileged chrooted child that does network I/O
This one is messy, and may not happen for some time, if ever.
Config files
------------
You may now set chroot= and user= in the global section of ups.conf.
upsd chroots before opening any config files, so there is no way to
add support for that in upsd.conf at the present time.

62
docs/commands.txt Normal file
View file

@ -0,0 +1,62 @@
Desc: Commands sent to the UPS drivers
File: commands.txt
Date: 9 January 2004
Auth: Russell Kroll <rkroll@exploits.org>
upsd can call drivers to store values in read/write variables and to kick
off instant commands. This is how you register handlers for those events.
The driver core (drivers/main.c) has a structure called upsh. You
should populate it with function pointers in your upsdrv_initinfo()
function. Right now, there are only two possibilities:
- setvar = setting UPS variables (SET VAR protocol command)
- instcmd = instant UPS commands (INSTCMD protocol command)
SET
---
If your driver's function for handling variable set events is called
my_ups_set(), then you'd do this to add the pointer:
upsh.setvar = my_ups_set;
my_ups_set() will receive two parameters:
const char * - the variable being changed
const char * - the new value
You should return either STAT_SET_HANDLED if your driver recognizes the
command, or STAT_SET_UNKNOWN if it doesn't. Other possibilities will be
added at some point in the future.
INSTCMD
-------
This works just like the set process, with slightly different values
arriving from the server.
upsh.instcmd = my_ups_cmd;
Your function will receive two args:
const char * - the command name
const char * - (reserved)
You should return either STAT_INSTCMD_HANDLED or STAT_INSTCMD_UNKNOWN
depending on whether your driver can handle the requested command.
Notes
-----
Use strcasecmp. The command names arriving from upsd should be treated
without regards to case.
Responses
---------
Drivers will eventually be expected to send responses to commands.
Right now, there is no channel to get these back through upsd to
the client, so this is not implemented.
This will probably be implemented with a polling scheme in the clients.

64
docs/config-files.txt Normal file
View file

@ -0,0 +1,64 @@
Desc: Details about the configuration files
File: config-files.txt
Date: 30 April 2003
Auth: Russell Kroll <rkroll@exploits.org>
All configuration files within this package are parsed with a common
state machine, which means they all can use a number of extras described
in this file.
First, most of the programs use an uppercase word to declare a
configuration directive. This may be something like MONITOR, NOTIFYCMD,
or ACCESS. The case does matter here. "monitor" won't be recognized.
Next, the parser does not care about whitespace between words. If you
like to indent things with tabs or spaces, feel free to do it here.
If you need to set a value to something containing spaces, it has to be
contained within "quotes" to keep the parser from splitting up the line.
That is, you want to use something like this:
SHUTDOWNCMD "/sbin/shutdown -h +0"
Without the quotes, it would only see the first word on the line.
OK, so let's say you really need to embed that kind of quote within your
configuration directive for some reason. You can do that too.
NOTIFYCMD "/bin/notifyme -foo -bar \"hi there\" -baz"
In other words, \ can be used to escape the ".
Finally, for the situation where you need to put the \ character into your
string, you just escape it.
NOTIFYCMD "/bin/notifyme c:\\dos\\style\\path"
The \ can actually be used to escape any character, but you only really
need it for \, ", and # as they have special meanings to the parser.
# is the comment character. Anything after an unescaped # is ignored.
Something like this...
identity = my#1ups
... will actually turn into "identity = my", since the # stops the
parsing. If you really need to have a # in your configuration, then
escape it.
identity = my\#1ups
Much better.
Line spanning
=============
You can put a backslash at the end of the line to join it to the next
one. This creates one virtual line that is composed of more than one
physical line.
Also, if you leave the "" quote container open before a newline, it will
keep scanning until it reaches another one. If you see bizarre behavior
in your configuration files, check for an unintentional instance of
quotes spanning multiple lines.

327
docs/configure.txt Normal file
View file

@ -0,0 +1,327 @@
Desc: Configure options
File: configure.txt
Date: 24 December 2008
Auth: Russell Kroll <rkroll@exploits.org>
Auth: Peter Selinger <selinger@sourceforge.net>
Auth: Arnaud Quette <aquette.dev@gmail.com>
There are a few options that can be given to configure to tweak compiles.
See also "./configure --help" for a current and complete listing.
Contents:
=========
1. Driver selection
2. Optional features
3. Other configuration options
4. Installation directories
5. Directories used by NUT at run-time
6. Things the compiler might need to find
1. Driver selection:
====================
--with-serial
Build and install the serial drivers (default: yes)
--with-usb
Build and install the USB drivers (default: auto-detect)
Note that you need to install the libusb development package or files.
--with-snmp
Build and install the SNMP drivers (default: auto-detect)
Note that you need to install libsnmp development package or files.
--with-neon
Build and install the XML drivers (default: auto-detect)
Note that you need to install neon development package or files.
--with-drivers=<driver>,<driver>,...
Specify exactly which driver or drivers to build and install (this
works for serial, usb, and snmp drivers, and overrides the
preceding three options).
As of the time of this writing (2006), there are 47 UPS drivers
available. Most users will only need one, a few will need two or
three, and very few people will need all of them.
To save time during the compile and disk space later on, you can
use this option to just build and install a subset of the drivers.
To select apcsmart and usbhid-ups, you'd do this:
--with-drivers=apcsmart,usbhid-ups
If you need to build more drivers later on, you will need to rerun
configure with a different list. To make it build all of the
drivers from scratch again, run 'make clean' before starting.
2. Optional features:
=====================
--with-cgi (default: no)
Build and install the optional CGI programs, HTML files, and sample
CGI configuration files. This is not enabled by default, as they
are only useful on web servers. See data/html/README for additional
information on how to set up CGI programs.
--with-lib (default: no)
Build and install the upsclient library and header files.
--with-all (no default)
Build and install all of the above (the serial, USB, and SNMP
drivers, the CGI programs and HTML files, and the upsclient
library).
--with-ssl (default: auto-detect)
Enable SSL development code. Read docs/ssl.txt for instructions on
SSL support.
--with-wrap (default: auto-detect)
Enable libwrap (tcp-wrappers) support. Refer to upsd man page for
more information.
--with-ipv6 (default: auto-detect)
Enable IPv6 support.
--with-hal (default: no)
Build and install Hardware Abstraction Layer support.
If you own a USB unit, only protect your local system and run the
Gnome or KDE desktop, this will enable a full Plug & Play usage.
See docs/nut-hal.txt for additional information on how to set up
and use HAL support.
--with-powerman (default: auto-detect)
Build and install Powerman PDU client driver.
This allows to interact with the Powerman daemon, and the numerous
Power Distribution Units (PDU) supported by the project.
3. Other configuration options:
===============================
--with-port=PORT
Change the TCP port used by the network code. Default is 3493.
Ancient versions of upsd used port 3305. NUT 2.0 and up use a
substantially different network protocol and are not able to
communicate with anything older than the 1.4 series.
If you have to monitor a mixed environment, use the last 1.4 version,
as it contains compatibility code for both the old "REQ" and the new
"GET" versions of the protocol.
--with-user=<username>
--with-group=<groupname>
Programs started as root will setuid() to <username> for somewhat
safer operation. You can override this with -u <user> in several
programs, including upsdrvctl (and all drivers by extension), upsd,
and upsmon. The "user" directive in ups.conf overrides this at run
time for the drivers.
Note: upsmon does not totally drop root because it may need to
initiate a shutdown. There is always at least a stub process
remaining with root powers. The network code runs in another
(separate) process as the new user.
The <groupname> is used for the permissions of some files,
particularly the hotplugging rules for USB. The idea is that the
device files for any UPS devices should be readable and writable by
members of that group.
The default value for both the username and groupname is "nobody".
This was done since it's slightly better than staying around as
root. Running things as nobody is not a good idea, since it's a
hack for NFS access. You should create at least one separate user
for this software.
If you use one of the --with-user and --with-group options, then
you have to use the other one too.
See the INSTALL document and the FAQ for more on this topic.
--with-logfacility=FACILITY
Change the facility used when writing to the log file. Read the man
page for openlog to get some idea of what's available on your system.
Default is LOG_DAEMON.
4. Installation directories:
============================
--prefix=PATH
This is a fairly standard option with GNU autoconf, and it sets the
base path for most of the other install directories. The default
is /usr/local/ups, which puts everything but the state sockets in one
easy place.
If you like having things to be at more of a "system" level, setting
the prefix to /usr/local or even /usr might be better.
--exec_prefix=PATH
This sets the base path for architecture dependent files. By
default, it is the same as <prefix>.
--sysconfdir=PATH
Changes the location where NUT's configuration files are stored.
By default this path is <prefix>/etc. Setting this to /etc or
/etc/ups might be useful.
The NUT_CONFPATH environment variable overrides this at run time.
--bindir=PATH
--sbindir=PATH
Where executable files will be installed. Files that are normally
executed by root (upsd, upsmon, upssched) go to sbindir, all others
to bindir. The defaults are <exec_prefix>/bin and <exec_prefix>/sbin.
--datadir=PATH
Change the data directory, i.e., where architecture independent
read-only data is installed. By default this is <prefix>/share,
i.e., /usr/local/ups/share. At the moment, this directory only
holds two files - the optional cmdvartab and driver.list.
--mandir=PATH
Sets the base directories for the man pages. The default is
<prefix>/man, i.e., /usr/local/ups/man.
--includedir=PATH
Sets the path for include files to be installed when --with-lib is
selected. For example, upsclient.h is installed here. The default
is <prefix>/include.
--libdir=PATH
Sets the installation path for libraries. This is just the
upsclient library for now. The default is <exec_prefix>/lib.
--with-drvpath=PATH
The UPS drivers will be installed to this path. By default they
install to "<exec_prefix>/bin", i.e., /usr/local/ups/bin.
The "driverpath" global directive in the ups.conf file overrides this
at run time.
--with-cgipath=PATH
The CGI programs will be installed to this path. By default, they
install to "<exec_prefix>/cgi-bin", which is usually /usr/local/ups/cgi-bin.
If you set the prefix to something like /usr, you should set the
cgipath to something else, because /usr/cgi-bin is pretty ugly and
non-standard.
The CGI programs are not built or installed by default. Use
"./configure --with-cgi" to request that they are built and
installed.
--with-htmlpath=PATH
HTML files will be installed to this path. By default, this is
"<prefix>/html". Note that HTML files are only installed if
--with-cgi is selected.
--with-pkgconfig-dir=PATH
Where to install pkg-config *.pc files. This option only has an
effect if --with-lib is selected, and causes a pkg-config file to
be installed in the named location. The default is
<exec_prefix>/pkgconfig.
Use --without-pkgconfig-dir to disable this feature altogether.
--with-hotplug-dir=PATH
Where to install Linux 2.4 hotplugging rules. The default is
/etc/hotplug, if that directory exists, and not to install it
otherwise. Note that this installation directory is not a
subdirectory of <prefix> by default. When installing NUT as a
non-root user, you may have to override this option.
Use --without-hotplug-dir to disable this feature altogether.
--with-udev-dir=PATH
Where to install Linux 2.6 hotplugging rules, for kernels that have
the "udev" mechanism. The default is /etc/udev, if that directory
exists, and not to install it otherwise. Note that this
installation directory is not a subdirectory of <prefix> by
default. When installing NUT as a non-root user, you may have to
override this option.
Use --without-udev-dir to disable this feature altogether.
5. Directories used by NUT at run-time:
=======================================
--with-pidpath=PATH
Changes the directory where pid files are stored. By default this is
/var/run. Certain programs like upsmon will leave files here.
--with-altpidpath=PATH
Programs that normally don't have root powers, like the drivers and
upsd, write their pid files here. By default this is whatever the
statepath is, as those programs should be able to write there.
--with-statepath=PATH
Change the default location of the state sockets created by the
drivers.
The NUT_STATEPATH environment variable overrides this at run time.
Default is /var/state/ups.
6. Things the compiler might need to find:
==========================================
--with-gd-includes="-I/foo/bar"
If you installed gd in some place where your C preprocessor can't
find the header files, use this switch to add additional -I flags.
--with-gd-libs="-L/foo/bar -labcd -lxyz"
If your copy of gd isn't linking properly, use this to give the
proper -L and -l flags to make it work. See LIBS= in gd's Makefile.
Note: the --with-gd switches are not necessary if you have gd 2.0.8
or higher installed properly. The gdlib-config script will be
detected and used by default in that situation.
--with-ssl-includes, --with-usb-includes, --with-snmp-includes,
--with-neon-includes, --with-powerman-includes="-I/foo/bar"
If your system doesn't have pkg-config and support for any of the
above libraries isn't found (but you know it is installed), you must
specify the compiler flags that are needed.
--with-ssl-libs, --with-usb-libs, --with-snmp-libs,
--with-neon-libs, --with-powerman-libs="-L/foo/bar -labcd -lxyz"
If your system doesn't have pkg-config and support for any of the
above libraries isn't found (but you know it is installed), you must
specify the linker flags that are needed.

108
docs/contact-closure.txt Normal file
View file

@ -0,0 +1,108 @@
Desc: Contact closure hardware
File: contact-closure.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
This is a collection of notes that apply to contact closure UPS
hardware, specifically those monitored by the genericups driver.
Definitions
-----------
"Contact closure" refers to a situation where one line is connected to
another inside UPS hardware to indicate some sort of situation. These
can be relays, or some other form of switching electronics. The generic
idea is that you either have a signal on a line, or you don't. Think
binary.
Usually, the source for a signal is the host PC. It provides a high
(logic level 1) from one of its outgoing lines, and the UPS returns it
on one or more lines to communicate. The rest of the time, the UPS
either lets it float or connects it to the ground to indicate a 0.
Other equipment generates the high and low signals internally, and does
not require cable power. These signals just appear on the right lines
without any special configuration on the PC side.
Bad levels
----------
Some evil cabling and UPS equipment uses the transmit or receive lines
as their reference points for these signals. This is not sufficient to
register as a high signal on many serial ports. If you have problems
reading certain signals on your system, make sure your UPS isn't trying
to do this.
Signals
-------
Unlike their smarter cousins, this kind of UPS can only give you very
simple yes/no answers. Due to the limited number of serial port lines
that can be used for this purpose, you typically get two pieces of data:
1. "On line" or "on battery"
2. "Battery OK" or "Low battery"
That's it. Some equipment actually swaps the second one for a
notification about whether the battery needs to be replaced, which makes
life interesting for those users.
Most hardware also supports an outgoing signal from the PC which means
"shut down the load immediately". This is generally implemented in such
a way that it only works when running on battery. Most hardware or
cabling will ignore the shutdown signal when running on line power.
New genericups types
--------------------
If none of the existing types in the genericups driver work completely,
make a note of which ones (if any) manage to work partially. This can
save you some work when creating support for your hardware.
Use that information to create a list of where the signals from your UPS
appear on the serial port at the PC end, and whether they are active
high or active low. You also need to know what outgoing lines, if any,
need to be raised in order to supply power to the contacts. This is
known as cable power. Finally, if your UPS can shut down the load, that
line must also be identified.
There are only 4 incoming and 2 outgoing lines, so not many combinations
are left. The other lines on a typical 9 pin port are transmit,
receive, and the ground. Anything trying to do a high/low signal on
those three is beyond the scope of the genericups driver. The only
exception is an outgoing BREAK, which we already support.
When editing the genericups.h, the values have the following meanings:
Outgoing lines:
line_norm = what to set to make the line "normal" - i.e. cable power
line_sd = what to set to make the UPS shut down the load
Incoming lines:
line_ol = flag that appears for on line / on battery
val_ol = value of that flag when the UPS is on battery
line_bl = flag that appears for low battery / battery OK
val_bl = value of that flag when the battery is low
This may seem a bit confusing to have two variables per value that
we want to read, but here's how it works. If you set line_ol to
TIOCM_RNG, then the value of TIOCM_RNG (0x080 on my box) will be anded
with the value of the serial port whenever a poll occurs. If that flag
exists, then the result of the and will be 0x80. If it does not exist,
the result will be 0.
So, if line_ol = foo, then val_ol can only be foo or 0.
As a general case, if line_ol == val_ol, then the value you're reading
is active high. Otherwise, it's active low. Check out the guts of
upsdrv_updateinfo() to see how it really works.
Custom definitions
------------------
Late in the 1.3 cycle, a feature was merged which allows you to create
custom monitoring settings without editing the model table. Just set
upstype to something close, then use settings in ups.conf to adjust the
rest. See the genericups man page for more details.

54
docs/data-room.txt Normal file
View file

@ -0,0 +1,54 @@
Desc: Typical setups for data rooms
File: data-room.txt
Date: 27 May 2002
Auth: Russell Kroll <rkroll@exploits.org>
The split nature of this UPS monitoring software allows a wide variety of
power connections. This document will help you identify how things should
be configured using some general descriptions.
There are two main elements:
1. There's a UPS attached to a serial port on this system.
2. This system depends on a UPS for power.
You can play "mix and match" with those two to arrive at these descriptions
for individual hosts:
A: 1 but not 2
B: 2 but not 1
C: 1 and 2
A small to medium sized data room usually has one C and a bunch of Bs.
This means that there's a system (type C) hooked to the UPS which depends
on it for power. There are also some other systems in there (type B)
which depend on that same UPS for power, but aren't directly connected to
it.
Larger data rooms or those with multiple UPSes may have several "clusters"
of the "single C, many Bs" depending on how it's all wired.
Finally, there's a special case. Type A systems are connected to a UPS's
serial port, but don't depend on it for power. This usually happens when
a UPS is physically close to a box and can reach the serial port, but
the wiring is such that it doesn't actually feed it.
Once you identify a system's type, use this list to decide which of the
programs need to be run for monitoring:
A: driver and upsd
B: upsmon (as slave)
C: driver, upsd, and upsmon (as master)
To further complicate things, you can have a system that is hooked to
multiple UPSes, but only depends on one for power. This particular
situation makes it an "A" relative to one UPS, and a "C" relative to the
other. The software can handle this - you just have to tell it what to
do.
Multi-power supply boxes
========================
If you are running large server-class systems that have more than one
power feed, see big-servers.txt for information on how to handle it
properly.

219
docs/design.txt Normal file
View file

@ -0,0 +1,219 @@
Desc: Network UPS Tools design document
File: design.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
This software is designed around a layered scheme with drivers, a
server and clients. These layers communicate with text-based
protocols for easier maintenance and diagnostics.
The layering
============
CLIENTS: upsmon, upsc, upsrw, upsstats, upsset, etc. (via upsclient)
< network: TCP sockets, typically on port 3493 >
SERVER: upsd
< Unix domain sockets with text-based messages >
DRIVERS: apcsmart, bestups, powercom, etc.
< serial communications, SNMP, USB, etc. >
EQUIPMENT: Smart-UPS 700, Fenton PowerPal 660, etc. (actual UPS hardware)
How information gets around
===========================
From the equipment
------------------
DRIVERS talk to the EQUIPMENT and receive updates. For most hardware this
is polled (DRIVER asks EQUIPMENT about a variable), but forced updates are
also possible. The exact method is not important, as it is abstracted
by the driver.
From the driver
---------------
The core of all DRIVERS maintains internal storage for every variable
that is known along with the auxiliary data for those variables. It
sends updates to this data to any process which connects to the Unix
domain socket.
The DRIVERS will also provide a full atomic copy of their internal
knowledge upon receiving the "DUMPALL" command on the socket. The dump
is in the same format as updates, and is followed by "DUMPDONE". When
"DUMPDONE" has been received, the view is complete.
The SERVER will connect to the socket of each DRIVER and will request a
dump at that time. It retains this data in local storage for later use.
It continues to listen on the socket for additional updates.
This protocol is documented in sock-protocol.txt.
From the server
---------------
The SERVER's internal storage maintains a complete copy of the data
which is in the DRIVER, so it is capable of answering any request
immediately. When a request for data arrives from a CLIENT, the SERVER
looks through the internal storage for that UPS and returns the
requested data if it is available.
The format for requests from the CLIENT is documented in protocol.txt.
Instant commands
================
Instant commands is the term given to a set of actions that result in
something happening to the UPS. Some of the common ones are
test.battery.start to initiate a battery test and test.panel.start to
test the front panel of the UPS.
They are passed to the SERVER from a CLIENT using an authenticated
network connection. The SERVER first checks to make sure that the instant
command is valid for the DRIVER. If it's supported, a message is sent
via a socket to the DRIVER containing the command and any auxiliary
information.
At this point, there is no confirmation to the SERVER of the command's
execution. This is (still) planned for a future release. This has been
delayed since returning a response involves some potentially interesting
timing issues. Remember that upsd services clients in a round-robin
fashion, so all queries must be lightweight and speedy.
Setting variables
=================
Some variables in the DRIVER or EQUIPMENT can be changed, and carry the
FLAG_RW flag. Upon receiving a SET command from the CLIENT, the SERVER
first verifies that it is valid for that DRIVER in terms of writability
and data type. If those checks pass, it then sends the SET command
through the socket, much like the instant command design.
The DRIVER is expected to commit the value to the EQUIPMENT and update
its internal representation of that variable.
Like the instant commands, there is currently no acknowledgement of the
command's completion from the DRIVER. This, too, is planned for a future
release.
Example data path
=================
Here's the path a piece of data might take through this architecture.
The event is a UPS going on battery, and the final result is a pager
delivering the alpha message to the admin.
1. EQUIPMENT reports on battery by setting flag in status register
2. DRIVER notices this flag and stores it in the ups.status variable as
OB. This update gets pushed out to any listeners via the sockets.
3. SERVER upsd sees activity on the socket, reads it, parses it, and
commits the new data to its local version of the status variable.
4. CLIENT upsmon does a routine poll of SERVER for "ups.status" and
gets "OB".
5. CLIENT upsmon then invokes its NOTIFYCMD which is upssched.
6. upssched starts up a daemon to handle a timer which will expire about
30 seconds into the future.
7. 30 seconds later, the timer expires since the UPS is still on battery,
and upssched calls the CMDSCRIPT upssched-cmd.
8. upssched-cmd parses the args and calls sendmail.
9. Avian carriers, smoke signals, SMTP, and some magic result in the
message getting from the pager company's gateway to a transmitter
and then to the admin's pager.
This scenario requires some configuration, obviously:
1. There's a UPS driver running.
(Whatever applies for the hardware)
2. upsd has a valid UPS entry in ups.conf for this UPS.
[myups]
driver = upsdriver
port = /dev/ttySx
3. upsd has a valid user for upsmon in upsd.users.
[monuser]
password = somepass
upsmon master
4. upsmon is set to monitor this UPS in upsmon.conf.
MONITOR myups@localhost 1 monuser somepass master
5. upsmon is set to EXEC the NOTIFYCMD for the ONBATT condition in
upsmon.conf.
NOTIFYFLAG ONBATT EXEC
6. upsmon calls upssched as the NOTIFYCMD in upsmon.conf.
NOTIFYCMD /path/to/upssched
7. upssched has a 30 second timer for ONBATT in upssched.conf.
AT ONBATT * START-TIMER upsonbatt 30
8. upssched calls upssched-cmd as the CMDSCRIPT in upssched.conf.
CMDSCRIPT /path/to/upssched-cmd
8. upssched-cmd knows what to do with "upsonbatt" as its first argument
(A quick case..esac construct, see the examples)
==============================================================================
History
=======
The oldest versions of this software (1998) had no separation between
the driver and the network server and only supported the latest APC
Smart-UPS hardware as a result. The network protocol used brittle
binary structs. This had numerous bad implications for compatibility
and portability.
After the driver and server were separated, data was shared through the
state file concept. Status was written into a static array (the "info
array") by drivers, and that array was stored on disk. upsd would
periodically read that file into a local copy of that array.
Shared memory mode was added a bit later, and that removed some of the
lag from the status updates. Unfortunately, it didn't have any locking
originally, and the possibility for corruption due to races existed.
mmap() support was added at some point after that, and became the
default. The drivers and upsd would mmap() the file into memory and
read or write from it. Locking was done using the state file as the
token, so contention problems were avoided. This method was relatively
quick, but it involved at least 3 copies of the data (driver, disk/mmap,
server) and a whole lot of locking and unlocking. It could occasionally
delay the driver or server when waiting for a lock.
In April 2003, the entire state management subsystem was removed and
replaced with a single local socket. The drivers listen for
connections and push updates asynchronously to any listeners. They also
recognize a few commands. Drivers also dampen updates, and only push
them out when something actually changes.
As a result, upsd no longer has to poll any files on the disk, and can
just select() all of its fds and wait for activity. When one of them is
active, it reads the fd and parses the results. Updates from the
hardware now get to upsd about as fast as they possibly can.
Drivers used to call setinfo() to change the local array, and then would
call writeinfo() to push the array onto the disk, or into the
mmap/shared memory space. This introduced a lag since many drivers poll
quite a few variables during an update.

374
docs/developers.txt Normal file
View file

@ -0,0 +1,374 @@
Desc: Information for developers
File: developers.txt
Date: 18 February 2004
Auth: Russell Kroll <rkroll@exploits.org>
This document is intended to explain some of the more useful things
within the tree and provide a standard for working on the code.
General stuff - common subdirectory
===================================
String handling
---------------
Use snprintf. It's even provided with a compatibility module if the
target host doesn't have it natively.
If you use snprintf to load some value into a buffer, make sure you
provide the format string. Don't use user-provided format strings,
since that's an easy way to open yourself up to an exploit.
Don't use strcat. We have a neat wrapper for snprintf called snprintfcat
that allows you to append to char * with a format string and all the usual
string length checking of snprintf.
Error reporting
---------------
Don't call syslog() directly. Use upslog_with_errno() and upslogx().
They may write to the syslog, stderr, or both as appropriate. This
means you don't have to worry about whether you're running in the
background or not.
upslog_with_errno prints your message plus the string expansion of
errno. upslogx just prints the message.
fatal_with_errno and fatalx work the same way, but they
exit(EXIT_FAILURE) afterwards. Don't call exit() directly.
Debugging information
---------------------
upsdebug_with_errno(), upsdebugx() and upsdebug_hex() use the
global nut_debug_level so you don't have to mess around with
printfs yourself. Use them.
Memory allocation
-----------------
xmalloc, xcalloc, xrealloc and xstrdup all check the results of the base
calls before continuing, so you don't have to. Don't use the raw calls
directly.
Config file parsing
-------------------
The configuration parser, called parseconf, is now up to its fourth
major version. It has multiple entry points, and can handle many
different jobs. It's usually used for parsing files, but it can also
take input a line at a time or even a character at a time.
You must initialize a context buffer with pconf_init before using any
other parseconf function. pconf_encode is the only exception, since it
operates on a buffer you supply and is an auxiliary function.
Escaping special characters and quoting multiple-word elements is all
handled by the state machine. Using the same code for all config files
avoids code duplication.
Note: this does not apply to drivers. Driver authors should use the
upsdrv_makevartable() scheme to pick up values from ups.conf. Drivers
should not have their own config files.
Drivers may have their own data files, such as lists of hardware,
mapping tables, or similar. The difference between a data file and a
config file is that users should never be expected to edit a data file
under normal circumstances. This technique might be used to add more
hardware support to a driver without recompiling.
<time.h> vs. <sys/time.h>
-------------------------
This is already handled by autoconf, so just include "timehead.h" and you
will get the right headers on every system.
UPS drivers - main.c
====================
The UPS drivers use main.c as their core. The only exception is
dummycons, which only looks like a driver by using the same dstate
function calls.
To write a new driver, you create a file with a series of support
functions that will be called by main. These all have names that start
with "upsdrv_", and they will be called at different times by main
depending on what needs to happen.
See new-drivers.txt for information on writing drivers, and also refer
to the skeletal driver in skel.c.
Portability
===========
Avoid things that will break on other systems. All the world is not an
x86 Linux box.
There are still older systems out there that don't do C++ style comments.
That means you have to comment /* like this */, and // this is right out.
Newer versions of gcc allow you to declare a variable inside a function
somewhat like the way C++ operates, like this:
function do_stuff(void)
{
check_something();
int a;
a = do_something_else();
}
While this will compile and run on these newer versions, it will fail
miserably for anyone on an older system. That means you must not use
it. gcc only warns about this with -pedantic.
Coding style
============
This is how I do things.
int open_subspace(char *ship, int privacy)
{
if (!privacy)
return insecure_channel(ship);
if (!init_privacy(ship))
fatal_with_errno("Can't open secure channel");
return secure_channel(ship);
}
(The example that used to be in this file wasn't particularly clear)
The basic idea is that I try to group things into functions, and then
find ways to drop out of them when we can't go any further. There's
another way to program this involving a big else chunk and a bunch of
braces, and it can be hard to follow. You can read this from top to
bottom and have a pretty good idea of what's going on without having to
track too much { } nesting and indenting.
I don't really care for pretentiousVariableNamingSchemes, but you can
probably get away with it in your own driver that I will never have to
touch. If your function or variable names start pushing important code
off the right margin of the screen, expect them to meet the byte
chainsaw sooner or later.
All types defined with typedef should end in "_t", because this is
easier to read, and it enables tools (such as indent and emacs) to
display the source code correctly.
Indenting with tabs vs. spaces
------------------------------
Another thing to notice is that the indenting happens with tabs instead
of spaces. This lets everyone have their personal tab-width setting
without inflicting much pain on other developers. If you use a space,
then you've fixed the spacing in stone and have really annoyed half of
the people out there.
If you write something that uses spaces, you may get away with it in a
driver that's relatively secluded. However, if I have to work on that
code, expect it to get reformatted according to the above.
Patches to existing code that don't conform to the coding style being
used in that file will probably be dropped. If it's something we really
need, it will be grudgingly reformatted before being included.
When in doubt, have a look at Linus's take on this topic in the Linux
kernel - Documentation/CodingStyle. He's done a far better job of
explaining this.
Line breaks
-----------
It is better to have lines that are longer than 80 characters than to
wrap lines in random places. This makes it easier to work with tools
such as "grep", and it also lets each developer choose their own
window size and tab setting without being stuck to one particular
choice.
Of course, this does not mean that lines should be made unnecessarily
long when there is a better alternative (see the note on
pretentiousVariableNamingSchemes above). Certainly there should not
be more than one statement per line. Please do not use
if (condition) break;
but use the following:
if (condition) {
break;
}
Miscellaneous coding style tools
--------------------------------
You can go a long way towards converting your source code to the NUT
coding style by piping it through the following command:
indent -kr -i8 -T FILE -l1000 -nhnl
This next command does a reasonable job of converting most C++ style
comments (but not URLs and DOCTYPE strings):
sed 's#\(^\|[ \t]\)//[ \t]*\(.*\)[ \t]*#/* \2 */#'
Emacs users can adjust how tabs are displayed. For example, it is
possible to set a tab stop to be 3 spaces, rather than the usual 8.
(Note that in the saved file, one indentation level will still
correspond to one tab stop; the difference is only how the file is
rendered on screen). It is even possible to set this on a
per-directory basis, by putting something like this into your .emacs
file:
;; NUT style
(defun nut-c-mode ()
"C mode with adjusted defaults for use with the NUT sources."
(interactive)
(c-mode)
(c-set-style "K&R")
(setq c-basic-offset 3) ;; 3 spaces C-indentation
(setq tab-width 3)) ;; 3 spaces per tab
;; apply NUT style to all C source files in all subdirectories of nut/
(setq auto-mode-alist (cons '(".*/nut/.*\\.[ch]$". nut-c-mode)
auto-mode-alist))
Finishing touches
-----------------
I like code that uses const and static liberally. If you don't need to
expose a function or global variable to the outside world, static is
your friend. If nobody should edit the contents of some buffer that's
behind a pointer, const keeps them honest.
We always compile with -Wall, so things like const and static help you
find implementation flaws. Functions that attempt to modify a constant
or access something outside their scope will throw a warning or even
fail to compile in some cases. This is what we want.
Spaghetti
---------
If you use a goto, expect me to drop it when my head stops spinning.
It gives me flashbacks to the BASIC code I wrote on the 8 bit systems of
the 80s. I've tried to clean up my act, and you should make the effort
as well.
I'm not making a blanket statement about gotos, since everything
probably has at least one good use. There are a few cases where a goto
is more efficient than any other approach, but you probably won't
encounter them in this software.
Hint: there *was* a good use of a goto in upsd until the 1.3 series. At
this point we are back to zero gotos since that code was replaced by
another technique that doesn't need it.
Legacy code
-----------
There are parts of the source tree that do not yet conform to these
specs. Part of this is due to the fact that the coding style has been
evolving slightly over the course of the project. Some of the code you
see in these directories is 5 years old, and things have gotten cleaner
since then. Don't worry - it'll get cleaned up the next time something
in the vicinity gets a visit.
Memory leak checking
--------------------
I can't say enough good things about valgrind. If you do anything with
dynamic memory in your code, you need to use this. Just compile with -g
and start the program inside valgrind. Run it through the suspected
area and then exit cleanly. valgrind will tell you if you've done
anything dodgy like freeing regions twice, reading uninitialized memory,
or if you've leaked memory anywhere.
http://valgrind.kde.org/
Conclusion
----------
The summary: please be kind to my eyes. There's a lot of stuff in here.
Submitting patches
==================
Patches that arrive in unified format (diff -u) as plain text with no
HTML, no attachments and a brief summary at the top are the easiest to
handle. They show the context, explain what's going on, and get saved as
one message. Everything stays together until it's time to merge.
Patches that arrive as attachments have to be moved around as separate
files - the body of the message is one, and the patch is in another.
This is not my preferred mode of operation.
When sending patches to the lists, be sure to add me as an explicit
recipient to make sure it is considered for merging. A patch which only
goes to a list is generally treated as a RFC and is relatively low
priority.
If your mailer is brain dead and rewrites tabs into spaces, wraps your
patch body, or anything else like that, just attach the patch. I'd
rather deal with an attachment instead of a patch that has tab damage,
rewrapped lines, or worse.
Patch cohesion
==============
Patches should have some kind of unifying element. One patch set is one
message, and it should all touch similar things. If you have to edit 6
files to add support for neutrino detection in UPS hardware, that's
fine.
However, sending one huge patch that does massive separate changes
all over the tree is not recommended. That kind of patch has to be
split up and evaluated separately, assuming I care enough to do that
instead of just dropping it.
If you have to make big changes in lots of places, send multiple
patches - one per item.
Man pages
=========
If you change something that involves an argument to a program or
configuration file parsing, the man page is probably now out of date.
If you don't update it, I have to, and I have enough to do as it is.
If you write a new driver, send in the man page when you send me the
source code for your driver. Otherwise, I will be forced to write a
skeletal man page that will probably miss many of the finer points of
the driver and hardware.
Repository etiquette and quality assurance
==========================================
Please keep the SVN trunk in working condition at all times. The trunk
may be used to generate daily tarballs, and should not contain broken
code if possible. If you need to commit incremental changes that leave
the system in a broken state, please do so in a separate branch and
merge the changes back to the trunk once they are complete.
Before committing, please remember to:
* update the ChangeLog, if appropriate. Dates are listed in UTC
("date --utc").
* run "make distcheck-light". This checks that the Makefiles are not
broken, that all the relevant files are distributed, and that there
are no compilation or installation errors.
Running "make distcheck-light" is especially important if you have
added or removed files, or updated configure.in or some Makefile.am.
Remember: simply adding a file to SVN does not mean it will be
distributed. To distribute a file, you must update the corresponding
Makefile.am.
There is also "make distcheck", which runs an even stricter set of
tests, but will not work unless you have all the optional libraries
and features installed.

221
docs/hid-subdrivers.txt Normal file
View file

@ -0,0 +1,221 @@
Desc: How to make a new subdriver to support another USB/HID UPS
File: hid-subdrivers.txt
Date: 08 January 2007
Auth: Peter Selinger <selinger@users.sourceforge.net>
Overall concept
===============
USB (Universal Serial Port) devices can be divided into several
different classes (audio, imaging, mass storage etc). Almost all UPS
devices belong to the "HID" class, which means "Human Interface
Device", and also includes things like keyboards and mice. What HID
devices have in common is a particular (and very flexible) interface
for reading and writing information (such as x/y coordinates and
button states, in case of a mouse, or voltages and status information,
in case of a UPS).
The Nut "usbhid-ups" driver is a meta-driver that handles all HID UPS
devices. It consists of a core driver that handles most of the work of
talking to the USB hardware, and several sub-drivers to handle
specific UPS manufacturers (MGE, APC, and Belkin are currently
supported). Adding support for a new HID UPS device is easy, because
it requires only the creation of a new sub-driver.
There are a few USB UPS devices that are not HID devices. These
devices typically implement some version of the manufacturer's serial
protocol over USB (which is a really dumb idea, by the way). An
example is the Tripplite USB. Such devices are *not* supported by the
usbhid-ups driver, and are not covered in this document. If you need to
add support for such a device, read new-drivers.txt and see the
tripplite_usb driver for inspiration.
HID Usage Tree
==============
From the point of view of writing a HID subdriver, a HID device
consists of a bunch of variables. Some variables (such as the current
input voltage) are read-only, whereas other variables (such as the
beeper enabled/disabled/muted status) can be read and written. These
variables are usually grouped together and arranged in a hierarchical
tree shape, similar to directories in a file system. This tree is
called the "usage" tree. For example, here is part of the usage tree
for a typical APC device. Variable components are separated by ".".
Typical values for each variable are also shown for illustrative
purposes.
UPS.Battery.Voltage 11.4 V
UPS.Battery.ConfigVoltage 12 V
UPS.Input.Voltage 117 V
UPS.Input.ConfigVoltage 120 V
UPS.AudibleAlarmControl 2 (=enabled)
UPS.PresentStatus.Charging 1 (=yes)
UPS.PresentStatus.Discharging 0 (=no)
UPS.PresentStatus.ACPresent 1 (=yes)
As you can see, variables that describe the battery status might be
grouped together under "Battery", variables that describe the input
power might be grouped together under "Input", and variables that
describe the current UPS status might be grouped together under
"PresentStatus". All of these variables are grouped together under
"UPS".
This hierarchical organization of data has the advantage of being very
flexible; for example, if some device has more than one battery, then
similar information about each battery could be grouped under
"Battery1", "Battery2" and so forth. If your UPS can also be used as a
toaster, then information about the toaster function might be grouped
under "Toaster", rather than "UPS".
However, the disadvantage is that each manufacturer will have their
own idea about how the usage tree should be organized, and usbhid-ups
needs to know about all of them. This is why manufacturer specific
subdrivers are needed.
To make matters more complicated, usage tree components (such as
"UPS", "Battery", or "Voltage") are internally represented not as
strings, but as numbers (called "usages" in HID terminology). These
numbers are defined in the "HID Usage Tables", available from
http://www.usb.org/developers/hidpage/. The standard usages for UPS
devices are defined in a document called "Usage Tables for HID Power
Devices".
For example,
0x00840010 = UPS
0x00840012 = Battery
0x00840030 = Voltage
0x00840040 = ConfigVoltage
0x0084001a = Input
0x0084005a = AudibleAlarmControl
0x00840002 = PresentStatus
0x00850044 = Charging
0x00850045 = Discharging
0x008500d0 = ACPresent
Thus, the above usage tree is internally represented as
00840010.00840012.00840030
00840010.00840012.00840040
00840010.0084001a.00840030
00840010.0084001a.00840040
00840010.0084005a
00840010.00840002.00850044
00840010.00840002.00850045
00840010.00840002.008500d0
To make matters worse, most manufacturers define their own additional
usages, even in cases where standard usages could have been used. for
example Belkin defines 00860040 = ConfigVoltage (which is incidentally
a violation of the USB specification, as 00860040 is reserved for
future use).
Thus, subdrivers generally need to provide:
- manufacturer-specific usage definitions,
- a mapping of HID variables to NUT variables.
Moreover, subdrivers might have to provide additional functionality,
such as custom implementations of specific instant commands (load.off,
shutdown.restart), and conversions of manufacturer specific data
formats.
Writing a subdriver
===================
In preparation for writing a subdriver for a device that is currently
unsupported, run usbhid-ups with the following command line:
drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX auto
(substitute your device's 4-digit VendorID instead of "XXXX").
This will produce a bunch of debugging information, including a number
of lines starting with "Path:" that describe the device's usage tree.
This information forms the initial basis for a new subdriver.
You should save this information to a file, e.g.
drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX auto >& /tmp/info
You can create an initial "stub" subdriver for your device by using
script scripts/subdriver/path-to-subdriver.sh. Note: this only creates
a "stub" and needs to be futher customized to be useful (see
CUSTOMIZATION below).
Use the script as follows:
scripts/subdriver/path-to-subdriver.sh < /tmp/info
where /tmp/info is the file where you previously saved the debugging
information.
This script prompts you for a name for the subdriver; use only letters
and digits, and use natural capitalization such as "Belkin" (not
"belkin" or "BELKIN"). The script may prompt you for additional
information.
You should put the generated files into the drivers/ subdirectory, and
update usbhid-ups.c by adding the appropriate #include line and by
updating the definition of subdriver_list in usbhid-ups.c. You must
also add the subdriver to USBHID_UPS_SUBDRIVERS in drivers/Makefile.am
and call "autoreconf" and/or "./configure" from the top level NUT directory.
You can then recompile usbhid-ups, and start experimenting with the new
subdriver.
CUSTOMIZATION: The initially generated subdriver code is only a stub,
and will not implement any useful functionality (in particular, it
will be unable to shut down the UPS). In the beginning, it simply
attempts to monitor some UPS variables. To make this driver useful,
you must examine the NUT variables of the form "unmapped.*" in the
hid_info_t data structure, and map them to actual NUT variables and
instant commands. There are currently no step-by-step instructions for
how to do this. Please look at the files
mge-hid.c/h
apc-hid.c/h
belkin-hid.c/h
to see how the currently implemented subdrivers are written.
Shutting down the UPS
=====================
It is desireable to support shutting down the UPS. Usually (for
devices that follow the HID Power Device Class specification), this
requires sending the UPS two commands. One for shutting down the UPS
(with an 'offdelay') and one for restarting it (with an 'ondelay'),
where offdelay < ondelay. The two NUT commands for which this is
relevant, are 'shutdown.return' and 'shutdown.stayoff'.
Since the one-to-one mapping above doesn't allow sending two HID
commands to the UPS in response to sending one NUT command to the
driver, this is handled by the driver. In order to make this work,
you need to define the following four NUT values:
ups.delay.start (variable, R/W)
ups.delay.shutdown (variable, R/W)
load.off.delay (command)
load.on.delay (command)
If the UPS supports it, the following variables can be used to show
the countdown to start/shutdown:
ups.timer.start (variable, R/O)
ups.timer.shutdown (variable, R/O)
The 'load.on' and 'load.off' commands will be defined implicitly by
the driver (using a delay value of '0'). Define these commands
yourself, if your UPS requires a different value to switch on/off
the load without delay.
Note that the driver expects the 'load.off.delay' and 'load.on.delay'
to follow the HID Power Device Class specification, which means that
the 'load.on.delay' command should NOT switch on the load in the
absence of mains power. If your UPS switches on the load regardless of
the mains status, DO NOT define this command. You probably want to
define the 'shutdown.return' and/or 'shutdown.stayoff' commands in
that case. Commands defined in the subdriver will take precedence over
the ones that are composed in the driver.
When running the driver with the '-k' flag, it will first attempt to
send a 'shutdown.return' command and if that fails, will fallback to
'shutdown.reboot'.

85
docs/ideas.txt Normal file
View file

@ -0,0 +1,85 @@
Desc: Ideas for future expansion and features
File: ideas.txt
Date: 20 October 2003
Auth: Russell Kroll <rkroll@exploits.org>
Here are some ideas that have come up over the years but haven't
been implemented yet. This may be a good place to start if you're
looking for a rainy day hacking project.
Non-network "upsmon"
====================
Some systems don't want a daemon listening to the network. This can be
for security reasons, or perhaps because the system has been squashed
down and doesn't have TCP/IP available. For these situations you could
run a driver and program that sits on top of the driver socket to do
local monitoring.
This also makes monitoring extremely easy to automate - you don't need
to worry about usernames, passwords or firewalling. Just start a driver
and drop this program on top of it.
- Parse ups.conf and open the state socket for a driver
- Send DUMPALL and enter a select loop
- Parse SETINFOs that change ups.status
- When you get OB LB, shut down
Completely unprivileged upsmon
==============================
upsmon currently retains root in a forked process so it can call the
shutdown command. The only reason it needs root on most systems is that
only privileged users can signal init or send a message on /dev/initctl.
In the case of systems running sysvinit (Slackware, others?), upsmon
could just open /dev/initctl while it has root and then drop it
completely. When it's time to shut down, fire a control structure at
init across the lingering socket and tell it to enter runlevel 0.
This has been shown to work in local tests, but it's not portable. It
could only be offered as an option for those systems which run that
flavor of init. It also needs to be tested to see what happens to
the lingering fd over time, such as when init restarts after an upgrade.
For other systems, there is always the possibility of having a suid
program which does nothing but prod init into starting a shutdown. Lock
down the group access so only upsmon's unprivileged user can access it,
and make that your SHUTDOWNCMD. Then it could drop root completely.
Chrooted upsmon
===============
upsmon could run the network monitoring part in a chroot jail if it had
a pipe to another process running outside for NOTIFY dispatches. Such a
pipe would have to be constructed extremely carefully so an attacker
could not compromise it from the jailed process.
A state machine with a tightly defined sequence could do this safely.
All it has to do is dispatch the UPS name and event type.
[start] [type] [length] <name> [stop]
Monitor program with interpreted language
=========================================
Once in awhile, I get requests for a way to shut down based on the UPS
temperature, or ambient humidity, or at a certain battery charge level,
or any number of things other than an "OB LB" status. It should be
obvious that adding a way to monitor all of that in upsmon would bloat
upsmon for all those people who really don't need anything like that.
A separate program that interprets a list of rules and uses it to
monitor the UPS equipment is the way to solve this. If you have a
condition that needs to be tested, add a rule.
Some of the tools that such a language would need include simple
greater-than/less-than testing (if battery.charge < 20), equivalence
testing (if ups.model = "SMART-UPS 700"), and some way to set and clear
timers.
Due to the expected size and limited audience for such a program, it
might have to be distributed separately.

66
docs/macros.txt Normal file
View file

@ -0,0 +1,66 @@
Desc: NUT-specific autoconf macros
File: macros.txt
Date: 27 December 2006
Auth: Peter Selinger <selinger@users.sourceforge.net>
The following NUT-specific autoconf macros are defined in the m4/
directory.
- Macro: NUT_TYPE_SOCKLEN_T
- Macro: NUT_TYPE_UINT8_T
- Macro: NUT_TYPE_UINT16_T
Check for the corresponding type in the system header files, and
#define a replacement if necessary.
- Macro: NUT_CHECK_LIBGD
- Macro: NUT_CHECK_LIBHAL
- Macro: NUT_CHECK_LIBNEON
- Macro: NUT_CHECK_LIBNETSNMP
- Macro: NUT_CHECK_LIBPOWERMAN
- Macro: NUT_CHECK_LIBSSL
- Macro: NUT_CHECK_LIBUSB
- Macro: NUT_CHECK_LIBWRAP
Determine the compiler flags for the corresponding library. On
success, set nut_have_libxxx="yes" and set LIBXXX_CFLAGS and
LIBXXX_LDFLAGS. On failure, set nut_have_libxxx="no". This macro
can be run multiple times, but will do the checking only once.
Here "xxx" should of course be replaced by the respective library name.
The checks for each library grow organically to compensate for
various bugs in the libraries, pkg-config, etc. This is why we have
a separate macro for each library.
- Macro: NUT_CHECK_IPV6
Check for various features required to compile the IPv6 support.
dnl Check for various features required for IPv6 support. Define a
preprocessor symbol for each individual feature (HAVE_GETADDRINFO,
HAVE_FREEADDRINFO, HAVE_STRUCT_ADDRINFO, HAVE_SOCKADDR_STORAGE,
SOCKADDR_IN6, IN6_ADDR, HAVE_IN6_IS_ADDR_V4MAPPED,
HAVE_AI_ADDRCONFIG). Also set the shell variable nut_have_ipv6=yes
if all the required features are present. Set nut_have_ipv6=no
otherwise.
- Macro: NUT_CHECK_OS
Check for the exact system name and type.
This was only used in the past to determine the packaging rule to be used
through the OS_NAME variable, but may be useful for other purposes in the
future.
- Macro: NUT_REPORT_FEATURE(FEATURE, VALUE)
Schedule a line for the end-of-configuration feature summary. The
FEATURE is a descriptive string such that the sentence "Checking
whether to FEATURE" makes sense, and VALUE describes the decision
taken (typically yes or no). The feature is also reported to the
terminal.
- Macro: NUT_REPORT(FEATURE, VALUE)
Schedule a line for the end-of-configuration feature summary, without
printing anything to the terminal immediately.
- Macro: NUT_PRINT_FEATURE_REPORT
Print out a list of the features that have been reported by
previous NUT_REPORT_FEATURE macro calls.
- Macro: NUT_ARG_WITH(FEATURE, DESCRIPTION, DEFAULT)
Declare a simple --with-FEATURE option with the given DESCRIPTION
and DEFAULT. Sets the variable nut_with_FEATURE.

69
docs/megatec.txt Normal file
View file

@ -0,0 +1,69 @@
Desc: Issues and direction for the megatec driver
File: megatec.txt
Date: 29 March 2006
Auth: Carlos Rodrigues <carlos.efr@mail.telepac.pt>
Overall concept
===============
The "powermust" driver was originally developed to support the Mustek Powermust
series of UPSes, but since there are some other drivers implementing (mostly)
the same protocol, an idea came up to unify all these other drivers under a
renamed version of "powermust": "megatec".
The idea is to support all the hardware previously supported by the other
drivers with a minimum number of special cases. Most of the time this isn't
difficult, as the protocol states that all unknown/unimplemented commands
should be ignored (the commands are simply echoed back).
Target drivers
==============
The following drivers are targeted for "assimilation":
* blazer (1)
* fentonups (1)
* mustek (1)
* esupssmart (1)
* ippon (1)
* sms (1)
* masterguard (3)
(1) megatec already supercedes this driver in functionality.
(2) megatec partially supercedes this driver in functionality, but some
small features are missing (non-critical for normal operation).
(3) megatec partially supercedes this driver in functionality, but some
important features are missing, which means some hardware may not be
supported.
The above status is infered from some testing and from looking at the code
of the drivers. Although I have a high degree of certainty about it, more
testing is needed/welcome.
Notes
=====
The "masterguard" driver seems to be the most problematic: it implements a
"Q3" command (similar to "Q1" but with extra information), and the command
to get information from the UPS is "WH" instead of "I" (with a different
response also).
All drivers cancel the battery tests with "CT". The protocol seems to imply
that the 10 second battery test can't be cancelled (which makes sense).
The beeper can be toggled with "Q", but there doesn't seem to exist a way to
check if it is on or off, which may confuse users when a "beeper.on" command
actually turns it off and vice-versa (maybe some models default to "on", and
others to "off", this may make this command fit better as a blind
"beeper.toggle").
The "sms" driver implements a simple watchdog (send and "SxxRxxx" command to
power cycle the UPS every time the "reset.watchdog" command is called).
There are two battery tests: failure ("T" - 10sec?) and until LOWBATT ("TL").
Moreover, there are some "S.3" or "S.3R0003" commands which fly in the face
of "S05R0003" which the driver also issues (this last one matches all the
other drivers, the first two seem to imply that the UPS also accepts those
format variations to the standard "SxxRxxxx" shutdown+return commands).
--
Carlos Rodrigues

620
docs/new-drivers.txt Normal file
View file

@ -0,0 +1,620 @@
Desc: How to make a new driver to support another UPS
File: new-drivers.txt
Date: 14 March 2004
Auth: Russell Kroll <rkroll@exploits.org>
Arnaud Quette <arnaud.quette@gmail.com>
Smart vs. Contact-closure
=========================
If your UPS only does contact closure readings, then go straight to the
contact-closure.txt document for information on adding support. It's a
lot easier to add a few lines to a header file than it is to create a
whole new driver.
Serial vs. USB vs. SNMP and more
================================
If your UPS connects to your computer via a USB port, then go straight
to the document hid-subdrivers.txt. You can probably add support for
your device by writing a new subdriver to the existing usbhid-ups
driver, which is easier than writing an entire new driver.
Similarly, if your UPS connects to your computer via an SNMP network
card, you can probably add support for your device by writing a new
subdriver to the existing snmp-ups driver, which is easier than writing
an entire new driver.
Overall concept
===============
The basic design of drivers is simple. main.c handles most of the work
for you. You don't have to worry about arguments, config files, or
anything else like that. Your only concern is talking to the hardware
and providing data to the outside world.
Skeleton driver
===============
Familiarize yourself with the design of skel.c in the drivers directory.
It shows a few examples of the functions that main will call to obtain
updated information from the hardware.
Essential structure
===================
upsdrv_info_t
-------------
This structure tracks several description information about the driver:
* name: the driver full name, for banner printing.
* version: the driver's own version. For sub driver information, refer below
to sub_upsdrv_info. This value has the form "X.YZ", and is
published by main as "driver.version.internal".
* authors: the driver's author(s) name. If multiple authors are listed, separate
them with '\n' so that it can be broken up by author if needed.
* status: the driver development status. The following values are allowed:
- DRV_BROKEN: setting this value will cause main to print an error
and exit. This is only used during conversions of the driver core
to keep users from using drivers which have not been converted.
Drivers in this state will be removed from the tree after some
period if they are not fixed.
- DRV_EXPERIMENTAL: set this value if your driver is potentially
broken. This will trigger a warning when it starts so the user
doesn't take it for granted.
- DRV_BETA: this value means that the driver is more stable and
complete. But it is still not recommended for production systems.
- DRV_STABLE: the driver is suitable for production systems, but not
100 % feature complete.
- DRV_COMPLETE: this is the gold level! It implies that 100 % of the
protocol is implemented, and a full QA pass.
* subdrv_info: array of upsdrv_info_t for sub driver(s) information. This
is used for example by usbhid-ups and megatec.
These information are currently used for the startup banner printing and tests.
Essential functions
===================
upsdrv_initups
--------------
Open the port (device_path) and do any low-level things that it may need
to start using that port. If you have to set DTR or RTS on a serial
port, do it here.
Don't do any sort of hardware detection here, since you may be going
into upsdrv_shutdown next.
upsdrv_initinfo
---------------
Try to detect what kind of UPS is out there, if any, assuming that's
possible for your hardware. If there is a way to detect that hardware
and it doesn't appear to be connected, display an error and exit. This
is the last time your driver is allowed to bail out.
This is usually a good place to create variables like ups.mfr,
ups.model, ups.serial, and other "one time only" items.
upsdrv_updateinfo
-----------------
Poll the hardware, and update any variables that you care about
monitoring. Use dstate_setinfo() to store the new values.
Do at most one pass of the variables. You MUST return from this
function or upsd will be unable to read data from your driver. main
will call this function at regular intervals.
Don't spent more than a couple of seconds in this function. Typically
five (5) seconds is the maximum time allowed before you risk that the
server declares the driver stale. If your UPS hardware requires a
timeout period of several seconds before it answers, consider returning
from this function after sending a command immediately and read the
answer the next time it is called.
You must never abort from upsdrv_updateinfo(), even when the UPS doesn't
seem to be attached anymore. If the connection with the UPS is lost, the
driver should retry to re-establish communication for as long as it is
running. Calling exit() or any of the fatal*() functions is specifically
not allowed anymore.
upsdrv_shutdown
---------------
Do whatever you can to make the UPS power off the load but also return
after the power comes back on. You may use a different command that
keeps the UPS off if the user has requested that with a configuration
setting.
You should attempt the UPS shutdown command even if the UPS detection
fails. If the UPS does not shut down the load, then the user is
vulnerable to a race if the power comes back on during the shutdown
process.
Data types
==========
To be of any use, you must supply data in ups.status. That is the
minimum needed to let upsmon do its job. Whenever possible, you should
also provide anything else that can be monitored by the driver. Some
obvious things are the manufacturer name and model name, voltage data,
and so on.
If you can't figure out some value automatically, use the ups.conf
options to let the user tell you. This can be useful when a driver
needs to support many similar hardware models but can't probe to see
what is actually attached.
Manipulating the data
=====================
All status data lives in structures that are managed by the dstate
functions. All access and modifications must happen through those
functions. Any other changes are forbidden, as they will not pushed out
as updates to things like upsd.
Adding variables
----------------
dstate_setinfo("ups.model", "Mega-Zapper 1500");
Many of these functions take format strings, so you can build the new
values right there:
dstate_setinfo("ups.model", "Mega-Zapper %d", rating);
Setting flags
-------------
Some variables have special properties. They can be writable, and some
are strings. The ST_FLAG_* values can be used to tell upsd more about
what it can do.
dstate_setflags("input.transfer.high", ST_FLAG_RW);
Status data
===========
UPS status flags like on line (OL) and on battery (OB) live in
ups.status. Don't manipulate this by hand. There are functions which
will do this for you.
status_init() - before doing anything else
status_set(val) - add a status word (OB, OL, etc)
status_commit() - push out the update
Possible values for status_set:
OL - On line (mains is present)
OB - On battery (mains is not present)
LB - Low battery
RB - The battery needs to be replaced
CHRG - The battery is charging
DISCHRG - The battery is discharging (inverter is providing load power)
BYPASS - UPS bypass circuit is active - no battery protection is available
CAL - UPS is currently performing runtime calibration (on battery)
OFF - UPS is offline and is not supplying power to the load
OVER - UPS is overloaded
TRIM - UPS is trimming incoming voltage (called "buck" in some hardware)
BOOST - UPS is boosting incoming voltage
Anything else will not be recognized by the usual clients. Coordinate
with me before creating something new, since there will be duplication
and ugliness otherwise.
Note: upsd injects "FSD" by itself following that command by a master
upsmon process. Drivers must not set that value.
Note: the OL and OB flags are an indication of the input line status only.
UPS alarms
==========
These work like ups.status, and have three special functions which you
must use to manage them.
alarm_init() - before doing anything else
alarm_set() - add an alarm word
alarm_commit() - push the value into ups.alarm
Note: the ALARM flag in ups.status is automatically set whenever you use
alarm_set. To remove that flag from ups.status, call alarm_init and
alarm_commit without calling alarm_set in the middle.
You should never try to set or unset the ALARM flag manually.
If you use UPS alarms, the call to status_commit() should be after
alarm_commit(), otherwise there will be a delay in setting the ALARM
flag in ups.status.
There is no official list of alarm words as of this writing, so don't
use these functions until you check with the upsdev list.
Staleness control
=================
If you're not talking to a polled UPS, then you must ensure that it
is still out there and is alive before calling dstate_dataok(). Even
if nothing is changing, you should still "ping" it or do something
else to ensure that it is really available. If the attempts to
contact the UPS fail, you must call dstate_datastale() to inform the
server and clients.
- dstate_dataok()
You must call this if polls are succeeding. A good place to call this
is the bottom of upsdrv_updateinfo().
- dstate_datastale()
You must call this if your status is unusable. A good technique is
to call this before exiting prematurely from upsdrv_updateinfo().
Don't hide calls to these functions deep inside helper functions. It is
very hard to find the origin of staleness warnings, if you call these from
various places in your code. Basically, don't call them from any other
function than from within upsdrv_updateinfo(). There is no need to call
either of these regularly as was stated in previous versions of this
document (that requirement has long gone).
Serial port handling
====================
Drivers which use serial port functions should include serial.h and use
these functions whenever possible:
- int ser_open(const char *port)
This opens the port and locks it if possible, using one of fcntl, lockf,
or uu_lock depending on what may be available. If something fails, it
calls fatal for you. If it succeeds, it always returns the fd that was
opened.
- int ser_set_speed(int fd, const char *port, speed_t speed)
This sets the speed of the port and also does some basic configuring
with tcgetattr and tcsetattr. If you have a special serial
configuration (other than 8N1), then this may not be what you want.
The port name is provided again here so failures in tcgetattr() provide
a useful error message. This is the only place that will generate a
message if someone passes a non-serial port /dev entry to your driver,
so it needs the extra detail.
- int ser_set_dtr(int fd, int state)
- int ser_set_rts(int fd, int state)
These functions can be used to set the modem control lines to provide
cable power on the RS232 interface. Use state = 0 to set the line to 0
and any other value to set it to 1.
- int set_get_dsr(int fd)
- int ser_get_cts(int fd)
- int set_get_dcd(int fd)
These functions read the state of the modem control lines. They will
return 0 if the line is logic 0 and a non-zero value if the line is
logic 1.
- int ser_close(int fd, const char *port)
This function unlocks the port if possible and closes the fd. You
should call this in your upsdrv_cleanup handler.
- int ser_send_char(int fd, char ch)
This attempts to write one character and returns the return value from
write. You could call write directly, but using this function allows
for future error handling in one place.
- int ser_send_pace(int fd, unsigned long d_usec,
const char *fmt, ...)
If you need to send a formatted buffer with an intercharacter delay, use
this function. There are a number of UPS controllers which can't take
commands at the full speed that would normally be possible at a given
bit rate. Adding a small delay usually turns a flaky UPS into a solid
one.
The return value is the number of characters that was sent to the port,
or -1 if something failed.
- int ser_send(int fd, const char *fmt, ...)
Like ser_send_pace, but without a delay. Only use this if you're sure
that your UPS can handle characters at the full line rate.
- int ser_send_buf(int fd, const char *buf, size_t buflen)
This sends a raw buffer to the fd. It is typically used for binary
transmissions. It returns the results of the call to write.
- int ser_send_buf_pace(int fd, unsigned long d_usec, const char *buf,
size_t buflen)
This is just ser_send_buf with an intercharacter delay.
- int ser_get_char(int fd, char *ch, long d_sec, long d_usec)
This will wait up to d_sec seconds + d_usec microseconds for one
character to arrive, storing it at ch. It returns 1 on success, -1
if something fails and 0 on a timeout.
Note: the delay value must not be too large, or your driver will not get
back to the usual idle loop in main in time to answer the PINGs from
upsd. That will cause an oscillation between staleness and normal
behavior.
- int ser_get_buf(int fd, char *buf, size_t buflen, long d_sec,
long d_usec)
Like ser_get_char, but this one reads up to buflen bytes storing all of
them in buf. The buffer is zeroed regardless of success or failure. It
returns the number of bytes read, -1 on failure and 0 on a timeout.
This is essentially a single read() function with a timeout.
- int ser_get_buf_len(int fd, char *buf, size_t buflen, long d_sec,
long d_usec)
Like ser_get_buf, but this one waits for buflen bytes to arrive,
storing all of them in buf. The buffer is zeroed regardless of success
or failure. It returns the number of bytes read, -1 on failure
and 0 on a timeout.
This should only be used for binary reads. See ser_get_line for
protocols that are terminated by characters like CR or LF.
- int ser_get_line(int fd, char *buf, size_t buflen, char endchar,
const char *ignset, long d_sec, long d_usec)
This is the reading function you should use if your UPS tends to send
responses like "OK\r" or "1234\n". It reads up to buflen bytes and
stores them in buf, but it will return immediately if it encounters
endchar. The endchar will not be stored in the buffer. It will also
return if it manages to collect a full buffer before reaching the
endchar. It returns the number of bytes stored in the buffer, -1 on
failure and 0 on a timeout.
If the character matches the ignset with strchr(), it will not be added
to the buffer. If you don't need to ignore any characters, just pass it
an empty string - "".
The buffer is always cleared and is always null-terminated. It does
this by reading at most (buflen - 1) bytes.
Note: any other data which is read after the endchar in the serial
buffer will be lost forever. As a result, you should not use this
unless your UPS uses a polled protocol.
Let's say your endchar is \n and your UPS sends "OK\n1234\nabcd\n".
This function will read() all of that, find the first \n, and stop
there. Your driver will get "OK", and the rest is gone forever.
This also means that you should not "pipeline" commands to the UPS.
Send a query, then read the response, then send the next query.
- int ser_get_line_alert(int fd, char *buf, size_t buflen,
char endchar, const char *ignset, const char *alertset,
void handler(char ch), long d_sec, long d_usec)
This is just like ser_get_line, but it allows you to specify a set of
alert characters which may be received at any time. They are not added
to the buffer, and this function will call your handler function,
passing the character as an argument.
Implementation note: this function actually does all of the work, and
ser_get_line is just a wrapper that sets an empty alertset and a NULL
handler.
- int ser_flush_in(int fd, const char *ignset, int verbose)
This function will drain the input buffer. If verbose is set to a
positive number, then it will announce the characters which have been
read in the syslog. You should not set verbose unless debugging is
enabled, since it could be very noisy.
This function returns the number of characters which were read, so you
can check for extra bytes by looking for a nonzero return value. Zero
will also be returned if the read fails for some reason.
- int set_flush_io(int fd)
This function drains both the in- and output buffers. Return zero on
success.
- void ser_comm_fail(const char *fmt, ...)
Call this whenever your serial communications fail for some reason. It
takes a format string, so you can use variables and other things to
clarify the error. This function does built-in rate-limiting so you
can't spam the syslog.
By default, it will write 10 messages, then it will stop and only write
1 in 100. This allows the driver to keep calling this function while
the problem persists without filling the logs too quickly.
In the old days, drivers would report a failure once, and then would be
silent until things were fixed again. Users had to figure out what was
happening by finding that single error message, or by looking at the
repeated complaints from upsd or the clients.
If your UPS frequently fails to acknowledge polls and this is a known
situation, you should make a couple of attempts before calling this
function.
Note: this does not call dstate_datastale. You still need to do that.
- void ser_comm_good(void)
This will clear the error counter and write a "re-established" message
to the syslog after communications have been lost. Your driver should
call this whenever it has successfully contacted the UPS. A good place
for most drivers is where it calls dstate_dataok.
USB port handling
=================
Drivers which use USB functions should include usb-common.h and use these:
* structure and macro:
You should us the usb_device_id structure, and the USB_DEVICE macro to
declare the supported devices. This allows the automatic extraction of
USB information, to generate the HAL, Hotplug and udev support files.
For example:
/* SomeVendor name */
#define SOMEVENDOR_VENDORID 0xXXXX
/* USB IDs device table */
static usb_device_id sv_usb_device_table [] = {
/* some models 1 */
{ USB_DEVICE(SOMEVENDOR_VENDORID, 0xYYYY), NULL },
/* various models */
{ USB_DEVICE(SOMEVENDOR_VENDORID, 0xZZZZ), NULL },
{ USB_DEVICE(SOMEVENDOR_VENDORID, 0xAAAA), NULL },
/* Terminating entry */
{ -1, -1, NULL }
};
* function:
- is_usb_device_supported(usb_device_id **usb_device_id_list,
int dev_VendorID, int dev_ProductID)
Call this in your device opening / matching function. Pass your usb_device_id
structure, and a set of VendorID / DeviceID.
This function returns one of the following value:
NOT_SUPPORTED (0), POSSIBLY_SUPPORTED (1) or SUPPORTED (2)
POSSIBLY_SUPPORTED is returned when the VendorID is matched, but the DeviceID
is unknown.
For implementation examples, refer to the various USB drivers, and search for
the above patterns.
This set of USB helpers is due to expand is the near future...
Variable names
==============
PLEASE don't make up new variables and commands just because you can.
The new dstate functions give us the power to create just about
anything, but that is a privilege and not a right. Imagine the mess
that would happen if every developer decided on their own way to
represent a common status element.
Check new-names.txt first to find the closest fit. If nothing matches,
contact the upsdev list or mail me directly, and we'll figure it out.
Patches which introduce unlisted names may be modified or dropped.
Message passing support
=======================
See commands.txt.
Enumerated types
================
If you have a variable that can have several specific values, it is
enumerated. You should add each one to make it available to the client:
dstate_addenum("input.transfer.low", "92");
dstate_addenum("input.transfer.low", "95");
dstate_addenum("input.transfer.low", "99");
dstate_addenum("input.transfer.low", "105");
Writable strings
================
Strings that may be changed by the client should have the ST_FLAG_STRING
flag set, and a maximum length byte set in the auxdata.
dstate_setinfo("ups.id", "Big UPS");
dstate_setflags("ups.id", ST_FLAG_STRING | ST_FLAG_RW);
dstate_setaux("ups.id", 8);
If the variable is not writable, don't bother with the flags or the
auxiliary data. It won't be used.
Instant commands
================
If your hardware and driver can support a command, register it.
dstate_addcmd("load.on");
Delays and ser_* functions
==========================
The new ser_* functions may perform reads faster than the UPS is able to
respond in some cases. This means that your driver will call select()
and read() numerous times if your UPS responds in bursts. This also
depends on how fast your system is.
You should check your driver with strace or its equivalent on your
system. If the driver is calling read() multiple times, consider adding
a call to usleep before going into the ser_read_* call. That will give
it a chance to accumulate so you get the whole thing with one call to
read without looping back for more.
This is not a request to save CPU time, even though it may do that. The
important part here is making the strace/ktrace output easier to read.
write(4, "Q1\r", 3) = 3
nanosleep({0, 300000000}, NULL) = 0
select(5, [4], NULL, NULL, {3, 0}) = 1 (in [4], left {3, 0})
read(4, "(120.0 084.0 120.0 0 60.0 22.6"..., 64) = 47
Without that delay, that turns into a mess of selects and reads.
The select returns almost instantly, and read gets a tiny chunk of the
data. Add the delay and you get a nice four-line status poll.
Canonical input mode processing
===============================
If your UPS uses '\n' and/or '\r' as endchar, consider the use of
Canonical Input Mode Processing instead of the ser_get_line* functions.
Using a serial port in this mode means that select() will wait until
a full line is received (or times out). This relieves you from waiting
between sending a command and reading the reply. Another benefit is,
that you no longer have to worry about the case that your UPS sends
"OK\n1234\nabcd\n". This will be broken up cleanly in "OK\n", "1234\n"
and "abcd\n" on consecutive reads, without risk of losing data (which
is an often forgotten side effect of the ser_get_line* functions).
Currently an example how this works can be found in the safenet and
upscode2 drivers. The first uses a single '\r' as endchar, while the
latter accepts either '\n', "\n\r" or "\r\n" as line termination. You
can define other termination characters as well, but can't undefine
'\r' and '\n' (so if you need these as data, this is not for you).

574
docs/new-names.txt Normal file
View file

@ -0,0 +1,574 @@
Desc: New command and variable naming scheme
File: new-names.txt
Date: 09 September 2005
Auth: Russell Kroll <rkroll@exploits.org>
Arnaud Quette <arnaud.quette@mgeups.com>
*** NOTE *** : When updating this file, also update data/cmdvartab.
This is a dump of the standard variables and command names used in NUT.
Don't use a name with any of the dstate functions unless it exists here.
If you need a new variable or command name, contact the Development Team
first.
Put another way: if you make up a name that's not in this list and it
gets into the tree, and then we come up with a better name later, clients
that use the undocumented variable will break when it is changed.
Note: "opaque" means programs should not attempt to parse the value for
that variable as it may vary greatly from one UPS to the next. These
strings are best handled directly by the user.
Variables
device: General unit information
Note: these data will be redundant with some ups.* information
during a transition period. The ups.* data will then be removed.
+-------------------------------------------------------------------------+
| Name | Description | Typical value |
|-----------------------+---------------------------+---------------------|
| device.model | Device model | BladeUPS |
|-----------------------+---------------------------+---------------------|
| device.mfr | Device manufacturer | Eaton |
|-----------------------+---------------------------+---------------------|
| device.serial | Device serial number | WS9643050926 |
| | (opaque string) | |
|-----------------------+---------------------------+---------------------|
| device.type | Device type (ups, pdu) | ups |
+-------------------------------------------------------------------------+
ups: General unit information
+-------------------------------------------------------------------------+
| Name | Description | Typical value |
|-----------------------+------------------------------+------------------|
| ups.status | UPS status | OL (see |
| | | new-drivers.txt) |
|-----------------------+------------------------------+------------------|
| ups.alarm | UPS alarms | OVERHEAT |
|-----------------------+------------------------------+------------------|
| ups.time | Internal UPS clock time | 12:34 |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.date | Internal UPS clock date | 01-02-03 |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.model | UPS model | SMART-UPS 700 |
|-----------------------+------------------------------+------------------|
| ups.mfr | UPS manufacturer | APC |
|-----------------------+------------------------------+------------------|
| ups.mfr.date | UPS manufacturing date | 10/17/96 |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.serial | UPS serial number (opaque | WS9643050926 |
| | string) | |
|-----------------------+------------------------------+------------------|
| ups.vendorid | Vendor ID for USB devices | 0463 |
|-----------------------+------------------------------+------------------|
| ups.productid | Product ID for USB devices | 0001 |
|-----------------------+------------------------------+------------------|
| ups.firmware | UPS firmware (opaque string) | 50.9.D |
|-----------------------+------------------------------+------------------|
| ups.firmware.aux | Auxiliary device firmware | 4Kx |
|-----------------------+------------------------------+------------------|
| ups.temperature | UPS temperature (degrees C) | 042.7 |
|-----------------------+------------------------------+------------------|
| ups.load | Load on UPS (percent) | 023.4 |
|-----------------------+------------------------------+------------------|
| ups.load.high | Load when UPS | 100 |
| | switches to overload | |
| | condition ("OVER") (percent) | |
|-----------------------+------------------------------+------------------|
| ups.id | UPS system identifier | Sierra |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| | Interval to wait before | |
| ups.delay.start | restarting the load | 0 |
| | (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.delay.reboot | Interval to wait before | 60 |
| | rebooting the UPS (seconds) | |
|-----------------------+------------------------------+------------------|
| | Interval to wait after | |
| ups.delay.shutdown | shutdown with delay command | 20 |
| | (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.timer.start | Time before the load will be | 30 |
| | started (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.timer.reboot | Time before the load will be | 10 |
| | rebooted (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.timer.shutdown | Time before the load will be | 20 |
| | shutdown (seconds) | |
|-----------------------+------------------------------+------------------|
| ups.test.interval | Interval between self tests | 1209600 (two |
| | (seconds) | weeks) |
|-----------------------+------------------------------+------------------|
| ups.test.result | Results of last self test | Bad battery pack |
| | (opaque string) | |
|-----------------------+------------------------------+------------------|
| ups.display.language | Language to use on front | E |
| | panel (*** opaque) | |
|-----------------------+------------------------------+------------------|
| ups.contacts | UPS external contact sensors | F0 |
| | (*** opaque) | |
|-----------------------+------------------------------+------------------|
| ups.power | Current value of apparent | 500 |
| | power (Volt-Amps) | |
|-----------------------+------------------------------+------------------|
| ups.power.nominal | Nominal value of apparent | 500 |
| | power (Volt-Amps) | |
|-----------------------+------------------------------+------------------|
| ups.realpower | Current value of real | 300 |
| | power (Watts) | |
|-----------------------+------------------------------+------------------|
| ups.realpower.nominal | Nominal value of real | 300 |
| | power (Watts) | |
|-----------------------+------------------------------+------------------|
| ups.beeper.status | UPS beeper status | enabled |
| | (enabled, disabled or muted) | |
|-----------------------+------------------------------+------------------|
| ups.type | UPS type (*** opaque) | offline |
|-----------------------+------------------------------+------------------|
| ups.watchdog.status | UPS watchdog status | disabled |
| | (enabled or disabled) | |
|-----------------------+------------------------------+------------------|
| ups.start.auto | UPS starts when mains is | yes |
| | (re)applied | |
+-----------------------+------------------------------+------------------+
| ups.start.battery | Allow to start UPS from | yes |
| | battery | |
+-----------------------+------------------------------+------------------+
| ups.start.reboot | UPS coldstarts from battery | yes |
| | (enabled or disabled) | |
+-------------------------------------------------------------------------+
input: Incoming line/power information
+------------------------------------------------------------------------+
| Name | Description | Typical value |
|---------------------------+----------------------------+---------------|
| input.voltage | Input voltage | 121.5 |
|---------------------------+----------------------------+---------------|
| input.voltage.maximum | Maximum incoming voltage | 130 |
| | seen | |
|---------------------------+----------------------------+---------------|
| input.voltage.minimum | Minimum incoming voltage | 100 |
| | seen | |
|---------------------------+----------------------------+---------------|
| input.voltage.nominal | Nominal input voltage | 120 |
|---------------------------+----------------------------+---------------|
| input.voltage.extended | Extended input voltage | no |
| | range | |
|---------------------------+----------------------------+---------------|
| input.transfer.reason | Reason for last transfer | T |
| | to battery (*** opaque) | |
|---------------------------+----------------------------+---------------|
| input.transfer.low | Low voltage transfer point | 91 |
|---------------------------+----------------------------+---------------|
| input.transfer.high | High voltage transfer | 132 |
| | point | |
|---------------------------+----------------------------+---------------|
| input.transfer.low.min | smallest settable low | 85 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.low.max | greatest settable low | 95 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.high.min | smallest settable high | 131 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.high.max | greatest settable high | 136 |
| | voltage transfer point | |
|---------------------------+----------------------------+---------------|
| input.sensitivity | Input power sensitivity | H (high) |
|---------------------------+----------------------------+---------------|
| input.quality | Input power quality (*** | FF |
| | opaque) | |
|---------------------------+----------------------------+---------------|
| input.current | Input current (A) | 4.25 |
|---------------------------+----------------------------+---------------|
| input.current.nominal | Nominal input current (A) | 5.0 |
|---------------------------+----------------------------+---------------|
| input.frequency | Input line frequency (Hz) | 60.00 |
|---------------------------+----------------------------+---------------|
| input.frequency.nominal | Nominal input line | 60 |
| | frequency (Hz) | |
|---------------------------+----------------------------+---------------|
| input.frequency.low | Input line frequency low | 47 |
| | (Hz) | |
|---------------------------+----------------------------+---------------|
| input.frequency.high | Input line frequency high | 63 |
| | (Hz) | |
|---------------------------+----------------------------+---------------|
| input.frequency.extended | Extended input frequency | no |
| | range | |
|---------------------------+----------------------------+---------------|
| input.transfer.boost.low | Low voltage boosting | 190 |
| | transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.boost.high | High voltage boosting | 210 |
| | transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.trim.low | Low voltage trimming | 230 |
| | transfer point | |
|---------------------------+----------------------------+---------------|
| input.transfer.trim.high | High voltage trimming | 240 |
| | transfer point | |
+------------------------------------------------------------------------+
output: Outgoing power/inverter information
+------------------------------------------------------------------------+
| output.voltage | Output voltage (V) | 120.9 |
|-------------------------------+--------------------------------+-------|
| output.voltage.nominal | Nominal output voltage (V) | 120 |
|-------------------------------+--------------------------------+-------|
| output.frequency | Output frequency (Hz) | 59.9 |
|-------------------------------+--------------------------------+-------|
| output.frequency.nominal | Nominal output frequency (Hz) | 60 |
|-------------------------------+--------------------------------+-------|
| output.current | Output current (A) | 4.25 |
|-------------------------------+--------------------------------+-------|
| output.current.nominal | Nominal output current (A) | 5.0 |
+------------------------------------------------------------------------+
Three-phase additions:
----------------------
The additions for three-phase measurements would produce a very long table
due to all the combinations that are possible, so these additions are
broken down to their base components.
PHASE COUNT DETERMINATION:
--------------------------
input.phases (3 for 3phase, absent or 1 for 1phase)
output.phases (as for input.phases)
DOMAINs:
--------
Any input or output is considered a valid DOMAIN.
input (should really be called input.mains, but keep this for compat)
input.bypass
input.servicebypass
output (should really be called output.load, but keep this for compat)
output.bypass
output.inverter
output.servicebypass
SPECIFICATION (SPEC):
-------------------------
Voltage, current, frequency, etc are considered to be a specification of
the measurement.
With this notation, the old 1phase naming scheme becomes DOMAIN.SPEC
Example: input.current
CONTEXT:
--------
When in 3phase mode we need some way to specify the target for most
measurements in more detail, we call this the CONTEXT.
With this notation, the naming scheme becomes DOMAIN.CONTEXT.SPEC when
in 3phase mode.
Example: input.L1.current
Valid CONTEXTs:
---------------
L1-L2 \
L2-L3 \
L3-L1 for voltage measurements
L1-N /
L2-N /
L3-N /
L1 \
L2 for currrent and power measurements
L3 /
N - for current measurement
Valid SPECs:
-----------
Valid with/without context (ie. per phase or aggregated/averaged)
current Current (A)
current.maximum Maximum seen current (A)
current.minimum Minimum seen current (A)
peakcurrent Peak current
voltage Voltage (V)
voltage.nominal Nominal voltage (V)
voltage.maximum Maximum seen voltage (V)
voltage.minimum Minimum seen voltage (V)
power Apparent power (VA)
power.maximum Maximum seen apparent power (VA)
power.minimum Maximum seen apparent power (VA)
power.percent Percentage of apparent power related to maximum load
power.maximum.percent Max seen percentage of apparent power
power.minimum.percent Min seen percentage of apparent power
realpower Real power (W)
powerfactor Power Factor (dimensionless value between 0.00 and 1.00)
Valid without context (ie. aggregation of all phases):
frequency Frequency (Hz)
frequency.nominal Nominal frequency (Hz)
EXAMPLES:
---------
Partial Three phase - Three phase example:
input.phases: 3
input.frequency: 50.0
input.L1.current: 133.0
input.bypass.L1-L2.voltage: 398.3
output.phases: 3
output.L1.power: 35700
output.powerfactor: 0.82
Partial Three phase - One phase example:
input.phases: 3
input.L2.current: 48.2
input.N.current: 3.4
input.L3-L1.voltage: 405.4
input.frequency: 50.1
output.phases: 1
output.current: 244.2
output.voltage: 120
output.frequency.nominal: 60.0
battery: Any battery details
+------------------------------------------------------------------------+
| battery.charge | Battery charge (percent) | 100.0 |
|-------------------------+------------------------------+---------------|
| battery.charge.low | Remaining battery level when | 20 |
| | UPS switches to LB (percent) | |
|-------------------------+------------------------------+---------------|
| battery.charge.restart | Minimum battery level for | 20 |
| | UPS restart after power-off | |
|-------------------------+------------------------------+---------------|
| battery.charge.warning | Battery level when UPS | |
| | switches to "Warning" state | 50 |
| | (percent) | |
|-------------------------+------------------------------+---------------|
| battery.voltage | Battery voltage (V) | 24.84 |
|-------------------------+------------------------------+---------------|
| battery.capacity | Battery capacity (Ah) | 7.2 |
|-------------------------+------------------------------+---------------|
| battery.current | Battery current (A) | 1.19 |
|-------------------------+------------------------------+---------------|
| battery.temperature | Battery temperature (degrees | 050.7 |
| | C) | |
|-------------------------+------------------------------+---------------|
| battery.voltage.nominal | Nominal battery voltage (V) | 024 |
|-------------------------+------------------------------+---------------|
| battery.runtime | Battery runtime (seconds) | 1080 |
|-------------------------+------------------------------+---------------|
| battery.runtime.elapsed | Elapsed battery runtime | 60 |
| | (seconds) | |
|-------------------------+------------------------------+---------------|
| | Remaining battery runtime | |
| battery.runtime.low | when UPS switches to LB | 180 |
| | (seconds) | |
|-------------------------+------------------------------+---------------|
| battery.alarm.threshold | Battery alarm threshold | 0 (immediate) |
|-------------------------+------------------------------+---------------|
| battery.date | Battery change date (opaque | 11/14/00 |
| | string) | |
|-------------------------+------------------------------+---------------|
| battery.mfr.date | Battery manufacturing date | 2005/04/02 |
| | (opaque string) | |
|-------------------------+------------------------------+---------------|
| battery.packs | Number of battery packs | 001 |
|-------------------------+------------------------------+---------------|
| battery.packs.bad | Number of bad battery packs | 000 |
+-------------------------+------------------------------+---------------+
| battery.type | Battery chemistry | PbAc |
| | (opaque string) | |
+-------------------------+------------------------------+---------------+
| battery.protection | Prevent deep discharge of | yes |
| | battery | |
+-------------------------+------------------------------+---------------+
| battery.energysave | Switch off when running on | no |
| | battery and no/low load | |
+------------------------------------------------------------------------+
ambient: Conditions from external probe equipment
+--------------------------------------------------------------------------+
| ambient.temperature | Ambient temperature | 25.40 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.alarm | Temperature alarm | enabled |
| | (enabled/disabled) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.high | Temperature threshold high | 40 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.low | Temperature threshold low | 5 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.maximum | Maximum temperature seen | 37.6 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.temperature.minimum | Minimum temperature seen | 18.1 |
| | (degrees C) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity | Ambient relative humidity | 038.8 |
| | (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.alarm | Relative humidity alarm | enabled |
| | (enabled/disabled) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.high | Relative humidity | 80 |
| | threshold high (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.low | Relative humidity | 10 |
| | threshold high (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.maximum | Maximum relative humidity | 60 |
| | seen (percent) | |
|-----------------------------------+----------------------------+---------|
| ambient.humidity.minimum | Minimum relative humidity | 13 |
| | seen (percent) | |
+--------------------------------------------------------------------------+
outlet: Smart outlet management (smart on/off switch, ...)
+------------------------------------------------------------------------+
| | Outlet system | |
| outlet.n.id | identifier (opaque | 1 |
| | string) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.desc | Outlet description | Main outlet |
| | (opaque string) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.switch | Outlet switch control | on |
| | (on/off) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.status | Outlet switch status | on |
| | (on/off) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.switchable | Outlet switch ability | yes |
| | (yes/no) | |
|--------------------------------+-------------------------+-------------|
| | Remaining battery level | |
| outlet.n.autoswitch.charge.low | to power off this | 90 |
| | outlet (percent) | |
|--------------------------------+-------------------------+-------------|
| | Interval to wait before | |
| outlet.n.delay.shutdown | shutting down this | 180 |
| | outlet (seconds) | |
|--------------------------------+-------------------------+-------------|
| | Interval to wait before | |
| outlet.n.delay.start | restarting this outlet | 120 |
| | (seconds) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.current | Current (A) | 0.19 |
|--------------------------------+-------------------------+-------------|
| outlet.n.current.maximum | Maximum seen current | 0.56 |
| | (A) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.realpower | Current value of real | 28 |
| | power (W) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.voltage | Voltage (V) | 247.0 |
|--------------------------------+-------------------------+-------------|
| | Power Factor | |
| outlet.n.powerfactor | (dimensionless value | 0.85 |
| | between 0 and 1) | |
|--------------------------------+-------------------------+-------------|
| outlet.n.power | Apparent power (VA) | 46 |
+------------------------------------------------------------------------+
driver: Internal driver information
+------------------------------------------------------------------------+
| driver.name | Driver name | apcsmart |
|-------------------------+----------------------------+-----------------|
| driver.version | Driver version (NUT | X.Y.Z |
| | release) | |
|-------------------------+----------------------------+-----------------|
| driver.version.internal | Internal driver version | 1.23.45 |
| | (if tracked separately) | |
|-------------------------+----------------------------+-----------------|
| driver.parameter.xxx | Parameter xxx (ups.conf or | (varies) |
| | cmdline -x) setting | |
|-------------------------+----------------------------+-----------------|
| driver.flag.xxx | Flag xxx (ups.conf or | enabled (or not |
| | cmdline -x) status | present) |
+------------------------------------------------------------------------+
server: Internal server information
+------------------------------------------------------------------------+
| server.info | Server | Network UPS Tools upsd vX.Y.Z - |
| | information | http://www.networkupstools.org/ |
|----------------+----------------+--------------------------------------|
| server.version | Server version | X.Y.Z |
+------------------------------------------------------------------------+
Instant commands
+------------------------------------------------------------------------+
| Name | Description |
|--------------------------+---------------------------------------------|
| load.off | Turn off the load immediately |
|--------------------------+---------------------------------------------|
| load.on | Turn on the load immediately |
|--------------------------+---------------------------------------------|
| shutdown.return | Turn off the load possibly after a delay |
| | and return when power is back |
|--------------------------+---------------------------------------------|
| shutdown.stayoff | Turn off the load possibly after a delay |
| | and remain off even if power returns |
|--------------------------+---------------------------------------------|
| shutdown.stop | Stop a shutdown in progress |
|--------------------------+---------------------------------------------|
| shutdown.reboot | Shut down the load briefly while rebooting |
| | the UPS |
|--------------------------+---------------------------------------------|
| shutdown.reboot.graceful | After a delay, shut down the load briefly |
| | while rebooting the UPS |
|--------------------------+---------------------------------------------|
| test.panel.start | Start testing the UPS panel |
|--------------------------+---------------------------------------------|
| test.panel.stop | Stop a UPS panel test |
|--------------------------+---------------------------------------------|
| test.failure.start | Start a simulated power failure |
|--------------------------+---------------------------------------------|
| test.failure.stop | Stop simulating a power failure |
|--------------------------+---------------------------------------------|
| test.battery.start | Start a battery test |
|--------------------------+---------------------------------------------|
| test.battery.start.quick | Start a "quick" battery test |
|--------------------------+---------------------------------------------|
| test.battery.start.deep | Start a "deep" battery test |
|--------------------------+---------------------------------------------|
| test.battery.stop | Stop the battery test |
|--------------------------+---------------------------------------------|
| calibrate.start | Start runtime calibration |
|--------------------------+---------------------------------------------|
| calibrate.stop | Stop runtime calibration |
|--------------------------+---------------------------------------------|
| bypass.start | Put the UPS in bypass mode |
|--------------------------+---------------------------------------------|
| bypass.stop | Take the UPS out of bypass mode |
|--------------------------+---------------------------------------------|
| reset.input.minmax | Reset minimum and maximum input voltage |
| | status |
|--------------------------+---------------------------------------------|
| reset.watchdog | Reset watchdog timer (forced reboot of |
| | load) |
|--------------------------+---------------------------------------------|
| beeper.enable | Enable UPS beeper/buzzer |
|--------------------------+---------------------------------------------|
| beeper.disable | Disable UPS beeper/buzzer |
|--------------------------+---------------------------------------------|
| beeper.mute | Temporarily mute UPS beeper/buzzer |
|--------------------------+---------------------------------------------|
| beeper.toggle | Toggle UPS beeper/buzzer |
+------------------------------------------------------------------------+

118
docs/nut-hal.txt Normal file
View file

@ -0,0 +1,118 @@
Desc: NUT integration with FreeDesktop HAL - Hardware Abstraction Layer
File: nut-hal.txt
Date: 05 March 2008
Auth: Arnaud Quette <aquette.dev@gmail.com>
This document introduces NUT integration with FreeDesktop HAL
(Hardware Abstraction Layer), also called Integrated Power Management (IPM).
Introduction
------------
This feature, also known as the Common Power Management integration,
allows NUT drivers to feed the HAL system, which will itself feeds
applications such as the Gnome Power Manager, in charge of the
system protection and notification.
This allows a better integration with the HAL supported systems
(Linux, *BSD and Solaris), and to reuse applications that have
been written to support laptop batteries. This also means that
we avoid the code / application redundancy by not using the upsd
and upsmon / NUT Client layer.
Since the NUT driver subset is limited to USB only, at least for
the moment, this should allow this feature to be shipped with a
base system.
From a user point of view, since all the needed components are
present on the system, we can achieve a full plug and play system.
That is to say when you plug your USB UPS, the needed driver is
automatically loaded and the according application (ie GPM) is
made available (displayed) at runtime without having to install
anything else than the base system. Nothing more to install,
nothing more to configure...
Detailed usage
---------------
Since this feature is still a work in progress, the below information
details how to get, install and test it.
Note that the minimum HAL version required is 0.5.8
* install libhal-dev and its dependencies (libdbus-dev)
or equivalent packages for your system.
* "./configure --with-hal && make" from within the nut dir
* either do a "make install" or simply copy the file
drivers/hald-addon* to the HAL addons directory (ie
/usr/lib/hal/ on Debian) or equivalent dir.
* copy the scripts/hal/20-ups-nut-device.fdi file to
$datadir/hal/fdi/information/20thirdparty
for example on Debian: /usr/share/hal/fdi/information/20thirdparty/
* create the (nut user and) group for the udev rule:
addgroup --quiet --system nut
* add the hal user (ex: haldaemon) to the nut group using:
adduser --quiet haldaemon nut
* restart HAL (ie using "/etc/init.d/dbus restart").
I've personaly used "killall hal" and restarted it using
"hald --daemon=no --verbose=yes" to see the verbose logs
* plug your UPS' USB cord into your computer
* you should now see the UPS using:
- [kde-]hal-device-manager,
- gnome power manager (standard applet for battery management), which
will pop up and state that there is an UPS
- ...
Packaging information
---------------------
The HAL support in NUT must currently be packaged separatly (ie in a
specific nut-hal package) and must conflict with the classic nut packages.
This is in order to:
- allow shipping of the HAL support only in the base system,
without including all the NUT drivers and software,
- prevent the NUT HAL addons to get an exclusive
and automatic access on a device, when a user only want to use the
USB support with a classic NUT installation.
This will be addressed when the new NUT configuration framework
will be merged in the main code branch.
Developing information
----------------------
As of NUT 2.2.2, the HAL integration also provide a DBus interface to
allow the calling of two method:
- Shutdown
- SetBeeper (boolean)
Example:
dbus-send --system --print-reply --dest=org.freedesktop.Hal \
/org/freedesktop/Hal/devices/usb_device_463_ffff_1H2E300AH \
org.freedesktop.Hal.Device.UPS.Shutdown
For development purposes, you might want to set the environment variable
"NUT_HAL_DEBUG" to something between "1" and "5". This matches the NUT debug
levels (-DDDDD).
Credits
-------
Thanks to the following people who made this possible:
- David Zeuthen, HAL Project Leader,
- Richard Hughes, Gnome Power Manager Developer.
References
----------
* FreeDesktop HAL: http://freedesktop.org/wiki/Software_2fhal
* Gnome Power Manager: http://www.gnome.org/projects/gnome-power-manager/

86
docs/osd-notify.txt Normal file
View file

@ -0,0 +1,86 @@
Desc: Using upsmon to make On Screen Display (OSD) notification
File: osd-notify.txt
Date: 12 April 2003
Auth: Arnaud Quette <arnaud.quette@free.fr>
This document presents how to display NUT notification using
an On Screen Display (OSD) system.
It is a complement to Russell Kroll's pager.txt, which
can be found on NUT website, or in NUT source tree. Have
a look at this document before reading more.
Pre requisites
--------------
You must have a running NUT installation (driver, upsd and upsmon).
Refer, if necessary, to NUT documentation for installing
and configuring those.
You also need X OSD to be installed. You can either:
- get it on: http://www.ignavus.net/software.html
- Debian: apt-get install xosd-bin
- Mandrake: urpmi xosd
- Others RPM based: get and install xosd (for example, from
http://rpmfind.net/linux/rpm2html/search.php)
Creating osd-notify shell script
--------------------------------
X OSD provides a really nice program, called osd_cat.
For more information on osd_cat, look at its manpage.
For convenience, I've written a small script called
osd-notify which should be available with the present
file.
You can adjust osd-notify settings to match your needs.
In particular, you must put a valid font in "FONT".
Use xfontsel to find one.
Configuring upsmon to use osd-notify
------------------------------------
1) You need to set EXEC flags on the event you want to
be osd-displayed in upsmon.conf. For example
NOTIFYFLAG ONBATT EXEC
NOTIFYFLAG ONLINE EXEC
You can of course set other actions, like WALL or SYSLOG,
and other events. Look at upsmon.conf manual page.
2) Copy osd-notify somewhere on your system (/usr/local/bin
or whatever).
3) Test osd-notify script by calling:
$> osd-notify NUT
4) Tell upsmon where your script is
NOTIFYCMD /path/to/osd-notify
Show time
---------
You need to adjust X11 access right to allow upsmon's
user to display OSD notification on your screen. This
is done with, from within a xterm, by using:
$> xhost +local:nutmon
Don't forget to adjust upsmon's user name according to
your system settings. This must match the value of the
"RUN_AS_USER" field in upsmon.conf
Now, restart upsmon, pull the plug, and see what happens...
For screenshots, have a look at X OSD website:
http://www.ignavus.net/software.html
Conclusion
----------
What great things we can do with a small nut ;-)
Feel free to send me your comments and enhancements.

68
docs/pager.txt Normal file
View file

@ -0,0 +1,68 @@
Desc: Using upsmon and your pager together
File: pager.txt
Date: 28 May 2001
Auth: Russell Kroll <rkroll@exploits.org>
upsmon can call out to a helper script or program when the UPS changes
state. The example upsmon.conf has a full list of which state changes
are available - ONLINE, ONBATT, LOWBATT, and more.
The simple approach
-------------------
- Set EXEC flags on various things in upsmon.conf
NOTIFYFLAG ONBATT EXEC
NOTIFYFLAG ONLINE EXEC
If you want other things like WALL or SYSLOG to happen, just add them.
NOTIFYFLAG ONBATT EXEC+WALL+SYSLOG
You get the idea.
- Tell upsmon where your script is
NOTIFYCMD /path/to/my/script
- Make a simple script like this at that location:
#! /bin/bash
echo "$*" | sendmail -F"ups@mybox" bofh@pager.example.com
- Restart upsmon, pull the plug, and see what happens.
That approach is bare-bones, but you should get the text content of the
alert in the body of the message, since upsmon passes the alert text
(from NOTIFYMSG) as an argument.
This will send mail every time something happens which may become annoying
rather quickly, especially for simple power fluctuations. To only send
messages after some interval, see the upssched.txt file for information
on offset events.
Using more advanced features
----------------------------
Your helper script will be run with a few environment variables set.
UPSNAME - the name of the system that generated the change.
This will be one of your identifiers from the MONITOR
lines in upsmon.conf.
NOTIFYTYPE - this will be ONLINE, ONBATT, or whatever event took
place which made upsmon call your script.
You can use these to do different things based on which system has
changed state. You could have it only send pages for an important
system while totally ignoring a known trouble spot, for example.
Suppressing notify storms
-------------------------
upsmon will call your script every time an event happens that has the
EXEC flag set. This means a quick power failure that lasts mere seconds
might generate several pages in a row. To suppress this sort of
annoyance, use upssched as your NOTIFYCMD program, and configure it to
send pages after a timer has elapsed. See upssched.txt for more
information.

135
docs/powersaving.txt Normal file
View file

@ -0,0 +1,135 @@
Desc: NUT Powersaving features and using outlet collection
File: powersaving.txt
Date: 14 June 2003
Auth: Arnaud Quette <arnaud.quette@free.fr>
This document introduces NUT PowerSaving features, and Smart
Outlet Management using Network UPS Tools.
This feature is sponsored by MGE UPS SYSTEMS.
Introduction
------------
This feature, which is supported by various manufacturers,
under various names, allows to manage separately the outlets
of an UPS, or a Power Distrubition Unit (PDU). This allows to
program a limited backup time to non-critical loads in order
to keep the maximum of the battery reserve for critical
equipment. This also allows a remote electrical management of
devices, which is very useful in DataCenters for example.
On small setup, you can plug printers, hubs, (...) on
PowerSave'd outlets. During a power outage, the UPS will
turn off those after X minutes of back-up time (or when
passing below X % of battery charge) depending on your
UPS model and settings. This will ensure that all
remaining battery power is available for the computer.
On huger setup (with a huger UPS), this is about the
same with the ability to (power and) control servers in
a smart way (need to notify those to shutdown first !).
Manufacturers Powersaving technologies presentation
===================================================
1) MGE UPS SYSTEMS and MGE Office Protection Systems
----------------------------------------------------
This feature is called "PowerShare" and is available
on lots of models, with different behaviours.
Features will vary according to your exact model.
For example:
- on Pulsar Ellipse Premium 650/800/1200, you can
only set a low battery level which triggers a power
off of the PowerShare outlet(s).
Check http://www.mgeups.com/products/pdt230/smallups/ellipsep/ellipsep1.htm
- on Pulsar Evolution (all models), you can either
do the same as above, or set a timer to shutdown
the outlet when expired. This latter needs to be
used in conjonction with upsmon/upssched to act
upon a power outage, and cancel the timer when
the power is back...
2) Eaton | Powerware ePDU
Depending on the exact model, you can see various measurements
(like current, voltage, power, ...) of the various outlets. You may
also have the hability to start, stop and cycle these.
For more information: http://www.epdu.com
3) Other manufacturers (Belkin, ...)
To be completed...
Integration into the new NUT naming scheme
==========================================
Have a look at new-names.txt, "outlet" section.
Note on outlet collection usage
===============================
1) outlet.{id, desc, ...} represents the
whole outlets (includes all outlet.x.*),
also called Main Outlet.
An interesting fact is that _ALL_ models
have at least that outlet, which is always
considered as the UPS itself. Some values
from the "ups" collection are linked to
the outlet.*, ie:
- outlet.load is mapped from ups.load
- outlet.delay.* is mapped from ups.delay.*
2) Indexes for other outlets begin by 1. So
the first outlet is "outlet.1.*".
Examples of upsc tree
=====================
1) Here is an MGE Evolution tree with the
main and 2 outlets.
...
outlet.desc: Main Outlet
outlet.id: 0
outlet.switchable: 0
outlet.1.autoswitch.charge.low: 0
outlet.1.delay.shutdown: -1
outlet.1.delay.start: -1
outlet.1.desc: PowerShare Outlet 1
outlet.1.id: 1
outlet.1.switch: 1
outlet.1.switchable: 1
outlet.2.autoswitch.charge.low: 0
outlet.2.delay.shutdown: -1
outlet.2.delay.start: -1
outlet.2.desc: PowerShare Outlet 2
outlet.2.id: 2
outlet.2.switch: 1
outlet.2.switchable: 1
...
2) Here is another MGE Ellipse Premium
tree with the main and 1 PowerSaving
outlets.
...
outlet.desc: Main Outlet
outlet.id: 0
outlet.switchable: 0
outlet.1.autoswitch.charge.low: 0
outlet.1.desc: PowerShare Outlet 1
outlet.1.id: 1
outlet.1.switch: 1
outlet.1.switchable: 1
...

518
docs/protocol.txt Normal file
View file

@ -0,0 +1,518 @@
Desc: Network protocol info
File: protocol.txt
Date: 18 February 2004
Auth: Russell Kroll <rkroll@exploits.org>
As of May 2002, this protocol now has an official port number from IANA,
which is 3493. The old number (3305) was a relic of the original code's
ancestry, and conflicted with other services. Version 0.50.0 and up
use 3493 by default.
This protocol runs over TCP. UDP support was dropped in July 2003. It
had been deprecated for some time and was only capable of the simplest
query commands as authentication is impossible over a UDP socket.
A library, named libupsclient, that implement this protocol is provided
in both static and shared version to help the client application development.
Old command removal notice
==========================
Before version 1.5.0, a number of old commands were supported. These
have been removed from the specification. For more information, consult
an older version of the software.
Command reference
=================
Multi-word elements are contained within "quotes" for easier parsing.
Embedded quotes are escaped with backslashes. Embedded backslashes are
also escaped by representing them as \\. This protocol is intended to
be interpreted with parseconf or something similar.
GET
===
Retrieve a single response from the server.
Possible sub-commands:
NUMLOGINS
---------
Form: GET NUMLOGINS <upsname>
GET NUMLOGINS su700
Response: NUMLOGINS <upsname> <value>
NUMLOGINS su700 1
<value> is the number of clients which have done LOGIN for this UPS.
This is used by the master upsmon to determine how many clients are
still connected when starting the shutdown process.
This replaces the old "REQ NUMLOGINS" command.
UPSDESC
-------
Form: GET UPSDESC <upsname>
GET UPSDESC su700
Response: UPSDESC <upsname> "<description>"
UPSDESC su700 "Development box"
<description> is the value of "desc=" from ups.conf for this UPS. If it
is not set, upsd will return "Unavailable".
This can be used to provide human-readable descriptions instead of a
cryptic "upsname@hostname" string.
VAR
---
Form: GET VAR <upsname> <varname>
GET VAR su700 ups.status
Response: VAR <upsname> <varname> "<value>"
VAR su700 ups.status "OL"
This replaces the old "REQ" command.
TYPE
----
Form: GET TYPE <upsname> <varname>
GET TYPE su700 input.transfer.low
Response: TYPE <upsname> <varname> <type>...
TYPE su700 input.transfer.low ENUM
<type> can be several values, and multiple words may be returned:
RW - this variable may be set to another value with SET
ENUM - an enumerated type, which supports a few specific values
STRING:n - this is a string of maximum length n
ENUM and STRING are usually associated with RW, but not always.
This replaces the old "VARTYPE" command.
DESC
----
Form: GET DESC <upsname> <varname>
GET DESC su700 ups.status
Response: DESC <upsname> <varname> "<description>"
DESC su700 ups.status "UPS status"
<description> is a string that gives a brief explanation of the named
variable. upsd may return "Unavailable" if the file which provides this
description is not installed.
Different versions of this file may be used in some situations to
provide for localization and internationalization.
This replaces the old "VARDESC" command.
CMDDESC
-------
Form: GET CMDDESC <upsname> <cmdname>
GET CMDDESC su700 load.on
Response: CMDDESC <upsname> <cmdname> "<description>"
CMDDESC su700 load.on "Turn on the load immediately"
This is like DESC above, but it applies to the instant commands.
This replaces the old "INSTCMDDESC" command.
LIST
====
The LIST functions all share a common container format. They will
return "BEGIN LIST" and then repeat the initial query. The list then
follows, with as many lines are necessary to convey it. "END LIST" with
the initial query attached then follows.
The formatting may seem a bit redundant, but it makes a different form
of client possible. You can send a LIST query and then go off and wait
for it to get back to you. When it arrives, you don't need complicated
state machines to remember which list is which.
UPS
---
Form: LIST UPS
Response: BEGIN LIST UPS
UPS <upsname> "<description>"
...
END LIST UPS
BEGIN LIST UPS
UPS su700 "Development box"
END LIST UPS
<upsname> is a name from ups.conf, and <description> is the value of
desc= from ups.conf, if available. It will be set to "Unavailable"
otherwise.
This can be used to determine what values of <upsname> are valid before
calling other functions on the server. This is also a good way to
handle situations where a single upsd supports multiple drivers.
Clients which perform a UPS discovery process may find this useful.
VAR
---
Form: LIST VAR <upsname>
LIST VAR su700
Response: BEGIN LIST VAR <upsname>
VAR <upsname> <varname> "<value>"
...
END LIST VAR <upsname>
BEGIN LIST VAR su700
VAR su700 ups.mfr "APC"
VAR su700 ups.mfr.date "10/17/96"
...
END LIST VAR su700
This replaces the old "LISTVARS" command.
RW
--
Form: LIST RW <upsname>
LIST RW su700
Response: BEGIN LIST RW <upsname>
RW <upsname> <varname> "<value>"
...
END LIST RW <upsname>
BEGIN LIST RW su700
RW su700 output.voltage.nominal "115"
RW su700 ups.delay.shutdown "020"
...
END LIST RW su700
This replaces the old "LISTRW" command.
CMD
---
Form: LIST CMD <upsname>
LIST CMD su700
Response: BEGIN LIST CMD <upsname>
CMD <upsname> <cmdname>
...
END LIST CMD <cmdname>
BEGIN LIST CMD su700
CMD su700 load.on
CMD su700 test.panel.start
...
END LIST CMD su700
This replaces the old "LISTINSTCMD" command.
ENUM
----
Form: LIST ENUM <upsname> <varname>
LIST ENUM su700 input.transfer.low
Response: BEGIN LIST ENUM <upsname> <varname>
ENUM <upsname> <varname> "<value>"
...
END LIST ENUM <upsname> <varname>
BEGIN LIST ENUM su700 input.transfer.low
ENUM su700 input.transfer.low "103"
ENUM su700 input.transfer.low "100"
...
END LIST ENUM su700 input.transfer.low
This replaces the old "ENUM" command.
Note: this does not support the old "SELECTED" notation. You must
request the current value separately.
SET
---
Form: SET VAR <upsname> <varname> "<value>"
SET VAR su700 ups.id "My UPS"
INSTCMD
-------
Form: INSTCMD <upsname> <cmdname>
INSTCMD su700 test.panel.start
LOGOUT
======
Form: LOGOUT
Returns: OK Goodbye (recent versions)
Used to disconnect gracefully from the server.
Older versions just said "Goodbye...".
LOGIN
=====
Form: LOGIN <upsname>
Returns: OK (upon success)
or various errors
Requires: "upsmon slave" or "upsmon master" in upsd.users
Use this to log the fact that a system is drawing power from this UPS.
The upsmon master will wait until the count of attached systems reaches
1 - itself. This allows the slaves to shut down first.
NOTE: You probably shouldn't send this command unless you are upsmon,
or a upsmon replacement.
MASTER
======
Form: MASTER <upsname>
Returns: OK (upon success)
or various errors
Requires: "upsmon master" in upsd.users
This function doesn't do much by itself. It is used by upsmon to make
sure that master-level functions like FSD are available if necessary.
FSD
===
Form: FSD <upsname>
Returns: OK FSD-SET (success)
or various errors
Requires: "upsmon master" in upsd.users
or "FSD" action granted in upsd.users
upsmon in master mode is the primary user of this function. It sets this
"forced shutdown" flag on any UPS when it plans to power it off. This is
done so that slave systems will know about it and shut down before the
power disappears.
Setting this flag makes "FSD" appear in a STATUS request for this UPS.
Finding "FSD" in a status request should be treated just like a "OB LB".
It should be noted that FSD is currently a latch - once set, there is
no way to clear it short of restarting upsd or dropping then re-adding
it in the ups.conf. This may cause issues when upsd is running on a
system that is not shut down due to the UPS event.
PASSWORD
========
Form: PASSWORD <password>
Returns: OK (upon success)
or various errors
Sets the password associated with a connection. Used for later
authentication for commands that require it.
USERNAME
========
Form: USERNAME <username>
Returns: OK (upon success)
or various errors
Sets the username associated with a connection. This is also used for
authentication, specifically in conjunction with the upsd.users file.
STARTTLS
========
Form: STARTTLS
Returns: OK STARTTLS
or various errors
This tells upsd to switch to TLS mode internally, so all future
communications will be encrypted. You must also change to TLS mode in
the client after receiving the OK, or the connection will be useless.
Other commands
==============
HELP - lists the commands supported by this server
VER - shows the version of the server currently in use
These two are not intended to be used directly by programs. Humans can
make use of this program by using telnet or netcat. If you use
telnet, make sure you don't have it set to negotiate extra options.
upsd doesn't speak telnet and will probably misunderstand your first
request due to the extra junk in the buffer.
Error responses
===============
ERR <message> [<extra>...]
<message> is always one element; it never contains spaces. This may
be used to allow additional information (<extra>) in the future.
ACCESS-DENIED
- The client's host and/or authentication details (username, password)
are not sufficient to execute the requested command.
UNKNOWN-UPS
- The UPS specified in the request is not known to upsd. This usually
means that it didn't match anything in ups.conf.
VAR-NOT-SUPPORTED
- The specified UPS doesn't support the variable in the request.
This is also sent for unrecognized variables which are in a space
which is handled by upsd, such as server.*.
CMD-NOT-SUPPORTED
- The specified UPS doesn't support the instant command in the request.
INVALID-ARGUMENT
- The client sent an argument to a command which is not recognized or
is otherwise invalid in this context. This is typically caused by
sending a valid command like GET with an invalid subcommand.
INSTCMD-FAILED
- upsd failed to deliver the instant command request to the driver.
No further information is available to the client. This typically
indicates a dead or broken driver.
SET-FAILED
- upsd failed to deliver the set request to the driver. This is
just like INSTCMD-FAILED above.
READONLY
- The requested variable in a SET command is not writable.
TOO-LONG
- The requested value in a SET command is too long.
FEATURE-NOT-SUPPORTED
- This instance of upsd does not support the requested feature. This
is only used for TLS/SSL mode (STARTTLS) at the moment.
FEATURE-NOT-CONFIGURED
- This instance of upsd hasn't been configured properly to allow the
requested feature to operate. This is also limited to STARTTLS for
now.
ALREADY-SSL-MODE
- TLS/SSL mode is already enabled on this connection, so upsd can't
start it again.
DRIVER-NOT-CONNECTED
- upsd can't perform the requested command, since the driver for that
UPS is not connected. This usually means that the driver is not
running, or if it is, the ups.conf is misconfigured.
DATA-STALE
- upsd is connected to the driver for the UPS, but that driver isn't
providing regular updates or has specifically marked the data
as stale. upsd refuses to provide variables on stale units to avoid
false readings.
This generally means that the driver is running, but it has lost
communications with the hardware. Check the physical connection
to the equipment.
ALREADY-LOGGED-IN
- The client already sent LOGIN for a UPS and can't do it again.
There is presently a limit of one LOGIN record per connection.
INVALID-PASSWORD
- The client sent an invalid PASSWORD - perhaps an empty one.
ALREADY-SET-PASSWORD
- The client already set a PASSWORD and can't set another. This also
should never happen with normal NUT clients.
INVALID-USERNAME
- The client sent an invalid USERNAME.
ALREADY-SET-USERNAME
- The client has already set a USERNAME, and can't set another. This
should never happen with normal NUT clients.
USERNAME-REQUIRED
- The requested command requires a username for authentication,
but the client hasn't set one.
PASSWORD-REQUIRED
- The requested command requires a passname for authentication,
but the client hasn't set one.
UNKNOWN-COMMAND
- upsd doesn't recognize the requested command.
This can be useful for backwards compatibility with older versions
of upsd. Some NUT clients will try GET and fall back on REQ after
receiving this response.
INVALID-VALUE
- The value specified in the request is not valid. This usually
applies to a SET of an ENUM type which is using a value which is
not in the list of allowed values.
Future ideas
============
Dense lists
-----------
The LIST commands may be given the ability to handle options some day.
For example, "LIST VARS <ups> +DESC" would return the current value
like now, but it would also append the description of that variable.
Command status
--------------
After sending an INSTCMD or SET, a client will eventually be able to
poll to see whether it was completed successfully by the driver.

230
docs/shutdown.txt Normal file
View file

@ -0,0 +1,230 @@
Desc: Configuring automatic UPS shutdowns
File: shutdown.txt
Date: 24 August 2003
Auth: Russell Kroll <rkroll@exploits.org>
Shutdown design
===============
When your UPS batteries get low, the operating system needs to be brought
down cleanly. Also, the UPS load should be turned off so that all devices
that are attached to it are forcibly rebooted.
Here are the steps that occur when a critical power event happens:
1. The UPS goes on battery
2. The UPS reaches low battery (a "critical" UPS)
3. 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)
4. upsmon slave systems see "FSD" and:
- generate a NOTIFY_SHUTDOWN event
- wait FINALDELAY seconds - typically 5
- call their SHUTDOWNCMD
- disconnect from upsd
5. 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.
6. The upsmon master:
- generates a NOTIFY_SHUTDOWN event
- waits FINALDELAY seconds - typically 5
- creates the POWERDOWNFLAG file - usually /etc/killpower
- calls the SHUTDOWNCMD
7. On most systems, init takes over, kills your processes, syncs and
unmounts some filesystems, and remounts some read-only.
8. init then runs your shutdown script. This checks for the
POWERDOWNFLAG, finds it, and tells the UPS driver(s) to power off
the load.
9. The system loses power.
10. Time passes. The power returns, and the UPS switches back on.
11. All systems reboot and go back to work.
How you set it up
=================
1. Make sure your POWERDOWNFLAG setting in upsmon.conf points somewhere
reasonable. Specifically, that filesystem must be mounted when your
shutdown script runs.
2. Edit your shutdown scripts to check for the POWERDOWNFLAG so they know
when to power off the UPS. You must check for this file, as you don't
want this to happen during normal shutdowns!
You can use upsdrvctl to start the shutdown process in your UPS
hardware. Use this script as an example, but change the paths to
suit your system:
if (test -f /etc/killpower)
then
echo "Killing the power, bye!"
/usr/local/ups/bin/upsdrvctl shutdown
sleep 120
# uh oh... the UPS poweroff failed!
# you probably should reboot here to avoid getting stuck
# *** see the section on power races below ***
fi
Make sure the filesystem containing upsdrvctl, ups.conf and your UPS
driver(s) is mounted when the system gets to this point. Otherwise
it won't be able to figure out what to do.
RAID warning
============
NOTE: If you run any sort of RAID equipment, make sure your arrays
are either halted (if possible) or switched to "read-only" mode.
Otherwise you may suffer a long resync once the system comes back up.
The kernel may not ever run its final shutdown procedure, so you
must take care of all array shutdowns in userspace before upsdrvctl
runs.
If you use software RAID (md) on Linux, get mdadm and try using
'mdadm --readonly' to put your arrays in a safe state. This has to
happen after your shutdown scripts have remounted the filesystems.
On hardware RAID or other kernels, you have to do some detective work.
It may be necessary to contact the vendor or the author of your
driver to find out how to put the array in a state where a power loss
won't leave it "dirty".
My understanding is that 3ware devices on Linux will be fine unless
there are pending writes. Make sure your filesystems are remounted
read-only and you should be covered.
Multiple UPS shutdowns
======================
If you have multiple UPSes connected to your system, chances are that you
need to shut them down in a specific order. The goal is to shut down
everything but the one keeping upsmon alive at first, then you do that one
last.
To set the order in which your UPSes receive the shutdown commands, define
the "sdorder" value in your ups.conf.
[bigone]
driver = apcsmart
port = /dev/ttyS0
sdorder = 2
[littleguy]
driver = bestups
port = /dev/ttyS1
sdorder = 1
[misc]
driver = megatec
port = /dev/ttyS2
sdorder = 0
The order runs from 0 to the highest number available. So, for this
configuration, the order of shutdowns would be misc, littleguy, and then
bigone.
If you have a UPS that shouldn't be shutdown when running "upsdrvctl
shutdown", set the sdorder to -1.
Testing shutdowns
=================
To see how upsdrvctl will behave without actually turning off power, use
the -t argument. It will display the sequence without actually calling
the drivers.
Other issues
============
You may delete the POWERDOWNFLAG in the startup scripts, but it is not
necessary. upsmon will clear that file for you when it starts.
Remember that some operating systems unmount a good number of filesystems
when going into read-only mode. If the UPS software is installed to /usr
and it's not mounted, your shutdowns will fail. If this happens, either
make sure it stays mounted at shutdown, or install to another partition.
Power races
===========
There is a situation where the power may return during the shutdown
process. This is known as a race. Here's how we handle it.
"Smart" UPSes typically handle this by using a command that forces the UPS
to power the load off and back on. This way, you are assured that the
systems will restart even if the power returns at the worst possible
moment.
Contact closure units (ala genericups), on the other hand, have the
potential for a race when feeding multiple systems. This is due to the
design of most contact closure UPSes. Typically, the "kill power" line
only functions when running on battery. As a result, if the line power
returns during the shutdown process, there is no way to power down the
load.
The workaround is to force your systems to reboot after some
interval. This way, they won't be stuck in the halted state with the UPS
running on line power.
Testing power races
===================
The easiest way to see if your configuration will handle a power race
successfully is to do 'upsmon -c fsd'. This will force the UPS software
to shut down as if it had a OB+LB situation, and your shutdown script
should call the UPS driver(s) in shutdown mode.
If everything works correctly, the computer will be forcibly powered off,
may remain off for a few seconds to a few minutes (depending on the
driver and UPS type), then will power on again.
If your UPS just sits there and never resets the load, you are vulnerable
to the above power race and should add the "reboot after timeout" hack
at the very least.
Know your hardware
==================
UPS equipment varies from manufacturer to manufacturer and even within
model lines. You should test the shutdown sequence on your systems before
leaving them unattended. A successful sequence is one where the OS halts
before the battery runs out, and the system restarts when power returns.
One more tip
============
If your UPS powers up immediately after a power failure instead of
waiting for the batteries to recharge, you can rig up a little hack to
handle it in software.
Essentially, you need to test for the POWERDOWNFLAG in your *startup*
scripts while the filesystems are still read-only. If it's there, you
know your last shutdown was caused by a power failure and the UPS
battery is probably still quite weak.
In this situation, your best bet is to sleep it off. Pausing in your
startup script to let the batteries recharge with the filesystems in a
safe state is recommended. This way, if the power goes out again, you
won't face a situation where there's not enough battery capacity left
for upsmon to do its thing.
Exactly how long to wait is a function of your UPS hardware, and will
require careful testing.
If this is too evil for you, buy another kind of UPS that will either
wait for a minimum amount of charge, a minimum amount of time, or both.

50
docs/snmp.txt Normal file
View file

@ -0,0 +1,50 @@
Desc: Information about SNMP and Network UPS Tools
File: snmp.txt
Date: 16 March 2003
Auth: Arnaud Quette <arnaud.quette@free.fr> or <arnaud.quette@mgeups.com>
This document presents interactions between SNMP and Network UPS Tools.
This work is mostly sponsored by:
MGE UPS SYSTEMS <http://www.mgeups.com/opensource/>
There are two part in NUT for SNMP support:
1) the agent or server side
An SNMP agent provides information for its hardware.
In general, agents are embedded in SNMP card.
This part has to be implemented as a Net-SNMP sub agent, acting
as a NUT middleware (upsd level). Such software make a bridge
between NUT data and SNMP, thus allowing to monitor, through
SNMP, standard point to point UPSs (serial and USB).
This is part of the "UPS Sub-Agent" project with Net-SNMP team.
2) the client side
* Introduction
An SNMP client communicates with an agent to acquire data.
This part, which has to be a NUT driver, is implemented by snmp-ups.
snmp-ups acts as a bridge from SNMP to NUT, thus allowing to monitor
in NUT any SNMP Agent (embedded or on a host).
The new snmp-ups driver now support multiple MIBS (SNMP structures
declaration). For more information on snmp-ups, have a look at its
manpage (man 8 snmp-ups).
* Extending existing mib2nut information
To be written...
* Adding new mib2nut information
To be written...
References:
- NUT SNMP Protocols Library Available at:
http://random.networkupstools.org/protocols/snmp/

225
docs/sock-protocol.txt Normal file
View file

@ -0,0 +1,225 @@
Desc: Driver/server socket protocol
File: sock-protocol.txt
Date: 1 May 2003
Auth: Russell Kroll <rkroll@exploits.org>
Here's a brief explanation of the text-based protocol which is now used
between the drivers and server.
The drivers may send things on the socket at any time. They will send
out changes to their local storage immediately, without any sort of
prompting from the server. As a result, the server must always check on
any driver sockets for activity.
Formatting
==========
All parsing on either side of the socket is done by parseconf, so the
same rules about escaping characters and "quoting multi-word elements"
apply here. Values which may contain odd characters are typically
sent through pconf_encode to apply \ characters where necessary.
The "" construct is used throughout to force a multi-word value to stay
together on its way to the other end.
Commands used by the drivers
============================
SETINFO
-------
SETINFO <varname> "<value>"
SETINFO ups.status "OB LB"
There is no "ADDINFO" - if a given variable does not exist, it is
created upon receiving the first SETINFO command.
DELINFO
-------
DELINFO <varname>
DELINFO ups.temperature
ADDENUM
-------
ADDENUM <varname> "<value>"
ADDENUM input.transfer.low "95"
DELENUM
-------
DELENUM <varname> "<value>"
DELENUM input.transfer.low "98"
SETAUX
------
SETAUX <varname> <numeric value>
SETAUX ups.id 8
This overrides any previous value. The auxiliary value is presently
used as a length byte for read-write variables that are strings.
SETFLAGS
--------
SETFLAGS <varname> <flag>...
SETFLAGS ups.id RW STRING
Note that this command takes a variable number of arguments, as multiple
flags are supported. Also note that they are not crammed together in
"", since "RW STRING" would mean something completely different.
This also replaces any previous flags for a given variable.
ADDCMD
------
ADDCMD <cmdname>
ADDCMD load.off
DELCMD
------
DELCMD <cmdname>
DELCMD load.on
DUMPDONE
--------
DUMPDONE
This is only used to tell the server that every possible item has been
transmitted in response to its DUMPALL request. Once this has been
received by the server, it can be sure that it knows everything that the
driver does.
PONG
----
PONG
This is sent in response to a PING from the server. It is only used as
a sanity check to make sure that the driver has not gotten stuck
somewhere.
DATAOK
------
DATAOK
This means that the driver is able to communicate with the UPS, and the
data should be treated as usable. It is always sent at the end of the
dump if the data is not stale. It may also be sent at other times.
DATASTALE
---------
DATASTALE
This is sent by the driver to inform any listeners that the data is no
longer usable. This usually means that the driver is unable to get any
sort of meaningful response from the UPS. You must not rely on any
status information once this has been sent.
This will be sent in the beginning of a dump if the data is stale, and
may be repeated. It is cleared by DATAOK.
Commands sent by the server
===========================
PING
----
PING
This is sent to check on the health of a driver. The server should only
send this when it hasn't heard anything valid from a driver recently.
Some drivers have very little to say in terms of updates, and this may
be the only communications they have with the server on a normal basis.
If a driver does not respond with the PONG within a few seconds at the
most, it should be treated as dead/unavailable. Data stored in the
server must not be passed on to the clients when this happens.
INSTCMD
-------
INSTCMD <cmdname>
INSTCMD panel.test.start
SET
---
SET <varname> "<value>"
SET ups.id "Data room"
DUMPALL
-------
DUMPALL
The server uses this to request a complete copy of everything the driver
knows. This is returned in the form of the same commands (SETINFO,
etc.) that would be used if they were being updated normally. As a
result, the same parsing happens either way.
The server can tell when it has a full copy of the data by waiting for
DUMPDONE. That special response from the driver is sent once the entire
set has been transmitted.
Design notes
============
Requests
--------
There is no way to request just one variable. This was done on purpose
to limit the complexity of the drivers. Their job is to send out
updates and handle a few simple requests. DUMPALL is provided to give
the server a known foundation.
To track a limited set of variables, a server just needs to do DUMPALL,
then only have handlers that remember values for the variables that
matter. Anything else should be ignored.
Access/Security
---------------
There are no access controls in the drivers. Anything that can connect
to their sockets can make requests, including SET and INSTCMD if
supported by the driver and hardware. These sockets must be kept
secure. If your operating system does not honor permissions or modes on
sockets, then you must store them in a directory with suitable
permissions to limit access.
Command limitations
-------------------
As parseconf is used to handle decoding and chunking of the data, there
are some limits on what may be used. These default to 32 arguments of
512 characters each, which should be more than enough for everything
which is currently needed by the software.
These limits are strictly for sanity purposes, and may be raised if
necessary. parseconf itself can handle vast numbers of arguments and
characters, with some speed penalty as things get really big.
Re-establishing communications
------------------------------
If the server loses its connection to the driver and later reconnects,
it must flush any local storage and start again with DUMPALL. The
driver may have changed the internal state considerably during that
time, and anything other approach could leave old elements behind.

251
docs/ssl.txt Normal file
View file

@ -0,0 +1,251 @@
Desc: Configuring SSL
File: ssl.txt
Date: 19 February 2004
Auth: Russell Kroll <rkroll@exploits.org>
SSL is now available as a development option. It encrypts sessions with
upsd and can also be used to authenticate servers. This means that
stealing port 3493 from upsd will no longer net you interesting
passwords.
Several things must happen before this will work, however:
------------------------------------------------------------------------------
1. Install OpenSSL.
------------------------------------------------------------------------------
2. Recompile NUT from source, starting with 'configure --with-ssl'.
------------------------------------------------------------------------------
3. Install everything as usual.
------------------------------------------------------------------------------
4. Create a certificate and key for upsd.
openssl (the program) should be in your PATH, unless you installed
it from source yourself, in which case it may be in
/usr/local/ssl/bin.
openssl req -new -x509 -nodes -out upsd.crt -keyout upsd.key
You can also put a "-days nnn" in there to set the expiration. If
you skip this, it may default to 30 days. This is probably not what
you want.
It will ask several questions. What you put in there doesn't matter
a whole lot, since nobody is going to see it for now. Future
versions of the clients may present data from it, so you might use
this opportunity to identify each server somehow.
------------------------------------------------------------------------------
5. Figure out the hash for the key.
openssl x509 -hash -noout -in upsd.crt
You'll get back a single line with 8 hex characters. This is the
hash of the certificate, which is used for naming the client-side
certificate. For the purposes of this example the hash is
0123abcd.
------------------------------------------------------------------------------
6. Install the client-side certificate.
mkdir <certpath>
chmod 0755 <certpath>
cp upsd.crt <certpath>/<hash>.0
Example:
mkdir /usr/local/ups/etc/certs
chmod 0755 /usr/local/ups/etc/certs
cp upsd.crt /usr/local/ups/etc/certs/0123abcd.0
If you already have a file with that name in there, increment the
0 until you get a unique filename that works.
If you have multiple client systems (like upsmon slaves), be sure
to install this file on them as well.
I recommend making a directory under your existing confpath to
keep everything in the same place. Remember the path you created,
since you will need to put it in upsmon.conf later.
It must not be writable by unprivileged users, since someone could
insert a new client certificate and fool upsmon into trusting a
fake upsd.
------------------------------------------------------------------------------
7. Create the combined file for upsd.
cat upsd.crt upsd.key > upsd.pem
chown root:nut upsd.pem
chmod 0640 upsd.pem
This file must be kept secure, since anyone possessing it could
pretend to be upsd and harvest authentication data if they get a
hold of port 3493.
Having it be owned by root and readable by group nut allows upsd
to read the file without being able to change the contents. This
is done to minimize the impact if someone should break into upsd.
------------------------------------------------------------------------------
8. Install the server-side certificate.
mv upsd.pem <upsd certfile path>
Example:
mv upsd.pem /usr/local/ups/etc/upsd.pem
After that, edit your upsd.conf and tell it where to find it:
CERTFILE /usr/local/ups/etc/upsd.pem
------------------------------------------------------------------------------
9. Clean up the temporary files.
rm -f upsd.crt upsd.key
------------------------------------------------------------------------------
10. Restart upsd.
It should come back up without any complaints. If it says something
about keys or certificates, then you probably missed a step.
If you run upsd as a separate user id (like nutsrv), make sure that
user can read the upsd.pem file.
------------------------------------------------------------------------------
11. Point upsmon at the certificates.
Edit your upsmon.conf, and tell it where the CERTPATH is:
CERTPATH <path>
CERTPATH /usr/local/ups/etc/certs
------------------------------------------------------------------------------
12. Recommended: make upsmon verify all connections with certificates.
Put this in upsmon.conf:
CERTVERIFY 1
Without this, there is no guarantee that the upsd is the right host.
Enabling this greatly reduces the risk of man in the middle attacks.
This effectively forces the use of SSL, so don't use this unless
all of your upsd hosts are ready for SSL and have their certificates
in order.
------------------------------------------------------------------------------
13. Recommended: force upsmon to use SSL.
Again in upsmon.conf:
FORCESSL 1
If you don't use CERTVERIFY 1, then this will at least make sure
that nobody can sniff your sessions without a large effort. Setting
this will make upsmon drop connections if the remote upsd doesn't
support SSL, so don't use it unless all of them have it running.
------------------------------------------------------------------------------
14. Restart upsmon.
You should see something like this in the syslog from upsd:
foo upsd[1234]: Client mon@localhost logged in to UPS [myups] (SSL)
If upsd or upsmon give any error messages, or the (SSL) is missing,
then something isn't right.
If in doubt about upsmon, start it with -D so it will stay in
the foreground and print debug messages. It should print something
like this every couple of seconds:
polling ups: myups@localhost [SSL]
Obviously, if the [SSL] isn't there, something's broken.
------------------------------------------------------------------------------
15. Recommended: sniff the connection to see it for yourself.
Using tcpdump, Ethereal, or another network sniffer tool, tell it
to monitor port 3493/tcp and see what happens. You should only see
"STARTTLS" go out, "OK STARTTLS" come back, and the rest will be
certificate data and then seemingly random characters.
If you see any plaintext besides that (USERNAME, PASSWORD, etc.)
then something is not working.
------------------------------------------------------------------------------
SSL support should be considered stable but purposely underdocumented
since various bits of the implementation or configuration may change in
the future. In other words, if you use this and it stops working after
an upgrade, come back to this file to find out what changed.
This is why the other documentation doesn't mention any of these
directives yet. SSL support is a treat for those of you that RTFM.
There are also potential licensing issues for people who ship binary
packages since NUT is GPL and OpenSSL is not compatible with it. You
can still build and use it yourself, but you can't distribute the
results of it. Or maybe you can. It depends on what you consider
"essential system software", and some other legal junk that I'm not
going to touch.
Other packages have solved this by explicitly stating that an exception
has been granted. That is (purposely) impossible here, since NUT is the
combined effort of many people, and all of them would have to agree to a
license change. This is actually a feature, since it means nobody can
unilaterally run off with the source - not even me.
It would be nice if we could also link against gnutls to avoid the
licensing issues.
Potential problems
==================
If you specify a certificate expiration date, you will eventually
see things like this in your syslog:
Oct 29 07:27:25 rktoy upsmon[3789]: Poll UPS [for750@rktoy] failed -
SSL error: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:
certificate verify failed
You can verify that it is expired by using openssl to display the date:
openssl x509 -enddate -noout -in <certfile>
It'll display a date like this:
notAfter=Oct 28 20:05:32 2002 GMT
If that's after the current date, you need to generate another cert/key
pair using the procedure above.
CAs / signed keys
=================
There are probably other ways to handle this, involving keys which have
been signed by a CA you recognize. Contact your local SSL guru.

190
docs/upssched.txt Normal file
View file

@ -0,0 +1,190 @@
Desc: How to use upssched
File: upssched.txt
Date: 01 October 2005
Auth: Russell Kroll <rkroll@exploits.org>
upssched is a helper for upsmon that will invoke commands for you at some
interval relative to a UPS event. It can be used to send pages, mail out
notices about things, or even shut down the box early.
There will be examples scattered throughout. Change them to suit your
pathnames, UPS locations, and so forth.
How it works relative to upsmon
===============================
When an event occurs, upsmon will call whatever you specify as a NOTIFYCMD
in your upsmon.conf, if you also enable the EXEC in your NOTIFYFLAGS. In
this case, we want upsmon to call upssched as the notifier, since it will
be doing all the work for us. So, in the upsmon.conf:
NOTIFYCMD /usr/local/ups/bin/upssched
Then we want upsmon to actually _use_ it for the notify events, so again
in the upsmon.conf we set the flags:
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
... and so on. For the purposes of this document I will only use those
three, but you can set the flags for any of the valid notify types.
Setting up your upssched.conf
=============================
Once upsmon has been configured with the NOTIFYCMD and EXEC flags, you're
ready to deal with the upssched.conf details. In this file, you specify
just what will happen when a given event occurs on a particular UPS.
First you need to define the name of the script or program that will
handle timers that trigger. This is your CMDSCRIPT, and needs to be above
any AT defines. There's an example provided with the program, so we'll
use that here:
CMDSCRIPT /usr/local/ups/bin/upssched-cmd
Then you have to define the variables PIPEFN and LOCKFN; the former
sets the file name of the FIFO that will pass communications between
processes to start and stop timers, while the latter sets the file name
for a temporary file created by upssched in order to avoid a race condition
under some circumstances. Please see the relevant comments in upssched.conf
for additional information and advice about these variables.
Now you can tell your CMDSCRIPT what to do when it is called by upsmon.
The big picture
---------------
The design in a nutshell is:
upsmon ---> calls upssched ---> calls your CMDSCRIPT
Ultimately, the CMDSCRIPT does the actual useful work, whether that's
initiating an early shutdown with 'upsmon -c fsd', sending a page by
calling sendmail, or opening a subspace channel to V'ger.
Establishing timers
-------------------
Let's say that you want to receive a page when any UPS has been running on
battery for 30 seconds. Create a handler that starts a 30 second timer
for an ONBATT condition.
AT ONBATT * START-TIMER onbattwarn 30
This means "when any UPS (the *) goes on battery, start a timer called
onbattwarn that will trigger in 30 seconds". We'll come back to the
onbattwarn part in a moment. Right now we need to make sure that we
don't trigger that timer if the UPS happens to come back before the
time is up. In essence, if it goes back on line, we need to cancel it.
So, let's tell upssched that.
AT ONLINE * CANCEL-TIMER onbattwarn
Executing commands immediately
------------------------------
As an example, consider the scenario where a UPS goes onto battery power.
However, the users are not informed until 60 seconds later - using a timer as
described above. Whilst this may let the *logged in* users know that the UPS
is on battery power, it does not inform any users subsequently logging in. To
enable this we could, at the same time, create a file which is read and
displayed to any user trying to login whilst the UPS is on battery power. If
the UPS comes back onto utility power within 60 seconds, then we can cancel
the timer and remove the file, as described above. However, if the UPS comes
back onto utility power say 5 minutes later then we do not want to use any
timers but we still want to remove the file. To do this we could use:
AT ONLINE * EXECUTE ups-back-on-power
This means that when upsmon detects that the UPS is back on utility power it
will signal upssched. Upssched will see the above command and simply pass
'ups-back-on-power' as an argument directly to CMDSCRIPT. This occurs
immediately, there are no timers involved.
Writing the command script handler
----------------------------------
OK, now that upssched knows how the timers are supposed to work, let's
give it something to do when one actually triggers. The name of the
example timer is onbattwarn, so that's the argument that will be passed
into your CMDSCRIPT when it triggers. This means we need to do some
shell script writing to deal with that input.
#! /bin/sh
case $1 in
onbattwarn)
echo "The UPS has been on battery for awhile" \
| mail -s"UPS monitor" bofh@pager.example.com
ups-back-on-power)
/bin/rm -f /some/path/ups-on-battery
*)
logger -t upssched-cmd "Unrecognized command: $1"
;;
esac
This is a very simple script example, but it shows how you can test for
the presence of a given trigger. With multiple ATs creating various timer
names, you will need to test for each possibility and handle it according
to your desires.
Other possibilities
===================
You can invoke just about anything from inside the CMDSCRIPT. It doesn't
need to be a shell script, either - that's just an example. If you want
to write a program that will parse argv[1] and deal with the
possibilities, that will work too.
Early Shutdowns
===============
One thing that gets requested a lot is early shutdowns in upsmon. With
upssched, you can now have this functionality. Just set a timer for some
length of time at ONBATT which will invoke a shutdown command if it elapses.
Just be sure to cancel this timer if you go back ONLINE before then.
The best way to do this is to use the upsmon callback feature. You can
make upsmon set the "forced shutdown" (FSD) flag on the upsd so your
slave systems shut down early too. Just do something like this in your
CMDSCRIPT:
/usr/local/ups/sbin/upsmon -c fsd
It's not a good idea to call your system's shutdown routine directly
from the CMDSCRIPT, since there's no synchronization with the slave
systems hooked to the same UPS. FSD is the master's way of saying
"we're shutting down *now* like it or not, so you'd better get ready".
Background
==========
This program was written primarily to fulfill the requests of users for
the early shutdown scenario. The "outboard" design of the program
(relative to upsmon) was intended to reduce the load on the average
system. Most people don't have the requirement of shutting down after n
seconds on battery, since the usual OB+LB testing is sufficient.
This program was created separately so those people don't have to spend
CPU time and RAM on something that will never be used in their
environments.
The design of the timer handler is also geared towards minimizing impact.
It will come and go from the process list as necessary. When a new timer
is started, a process will be forked to actually watch the clock and
eventually start the CMDSCRIPT. When a timer triggers, it is removed from
the queue. Cancelling a timer will also remove it from the queue. When
no timers are present in the queue, the background process exits.
This means that you will only see upssched running when one of two things
is happening:
1. There's a timer of some sort currently running
2. upsmon just called it, and you managed to catch the brief instance
The final optimization handles the possibility of trying to cancel a timer
when there's none running. If there's no process already running, there
are no timers to cancel, and furthermore there is no need to start a
clock-watcher. As a result, it skips that step and exits sooner.