mikey@Sun

Network UPS Tools on Solaris

Saturday Nov 10, 2007

I have become the lucky owner of a Trust 1200VA management UPS. The bad news is that, the manufacturer provides software for Microsoft systems only. However, I found an opensource ups monitor called Network UPS Tools, that is said to work under unix a-like systems. And yes, I managed to make it work on Solaris 10, this short howto tells you how.


The first thing we need is a user account that will be used to run nut daemons. I say, the user 'ups', and the group 'ups' (also), with the home directory in /var/ups, that will be used as the state directory (this is mentioned later).

# groupadd -g 999 ups
# useradd -u 999 -g ups -d /var/ups -s /bin/false -m ups
# chown ups:ups /var/ups
# chmod 750 /var/ups


At this point you need NUT sources, that are available for download at http://www.networkupstools.org/source.html. You have to download, extract, and compile them:

# /usr/sfw/bin/wget http://www.networkupstools.org/source/2.2/nut-2.2.0.tar.gz
# gunzip -c nut-2.2.0.tar.gz | tar -xf -
# cd nut-2.2.0
# ./configure --prefix=/opt/nut --with-statepath=/var/ups --with-user=ups --with-group=ups
# make && make install


Let's stop here for a second, as I need to explain couple of things, with regards to the configure command. The prefix is where nut is going to be installed, the statedir is the same as the home directory of previously created user, the user and the group are self-explanatory.


I presume everything went fine, there were not errors - just like in the ideal world. Ok, its time configure it a little bit. So be prepared to edit couple of files in the text editor of your choice, but please do also read the comments, as some of the options (e.g. the password) have to be changed.

/opt/nut/etc/ups.conf:

[trust]
  # full list of deivers at http://www.networkupstools.org/compat/stable.html)
  driver = megatec
  port = /dev/ttya


/opt/nut/etc/upsd.conf:

# bind to localhost only
LISTEN 127.0.0.1
# define ACLs
ACL all 0.0.0.0/0  
ACL localhost 127.0.0.1/32
# Accept connections from localhost...
ACCEPT localhost
# ... and reject anything else
REJECT all
               

/opt/nut/etc/upsd.users

# define monitor user
[monuser]
password = YOUR_PASSWORD
allowfrom = localhost
upsmon master


/opt/nut/etc/upssched.conf

CMDSCRIPT /opt/nut/bin/upssched-cmd

/opt/nut/etc/upsmon.conf

RUN_AS_USER root # root is required for shotdown
MONITOR trust@localhost 1 monuser YOUR_PASSWORD_AGAIN master
MINSUPPLIES 1
SHUTDOWNCMD "/usr/sbin/poweroff"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
NOTIFYCMD /opt/nut/bin/notify # will create this later
POWERDOWNFLAG /etc/killpower
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5


Done, now simply change permissions to only created config files, so that only ups user is able to read them as your password is stored there.

# chgrp ups ups.conf upsd.conf upsmon.conf upssched.conf
# chmod 640 ups.conf upsd.conf upsmon.conf upssched.conf


I have previously mentioned the notify script that, would mail you whenever the UPS status changes (e.g. low battery).

#!/bin/bash
echo "$*" | mail -s "UPS state changed" foo@bar.com


Don't forget to make it exacutable

# chmod 755 /opt/nut/bin/notify

We are almost home, the only thing left here is the SMF, so that the nut daemons would start auto-magically on system boot. You need the method and manifest files to make this work.

# mkdir -p /opt/nut/lib/svc/method
# vi nut

#!/usr/bin/sh

. /lib/svc/share/smf_include.sh

NUT_DIR=/opt/nut
STATE_DIR=/var/ups
PID_UPS=${STATE_DIR}/upsd.pid
PID_MON=/var/run/upsmon.pid

ups_stop () {
    if [ -f ${PID_MON} ]; then
        /usr/bin/kill `cat ${PID_MON}` > /dev/null
        /usr/bin/rm -f ${PID_MON}
    fi
    if [ -f ${PID_UPS} ]; then
        /usr/bin/kill `cat ${PID_UPS}` > /dev/null
        /usr/bin/rm -f ${PID_UPS}
    fi
    ${NUT_DIR}/bin/upsdrvctl stop > /dev/null 2>&1
}

ups_start () {
    $NUT_DIR/bin/upsdrvctl start >/dev/null 2>&1
    $NUT_DIR/sbin/upsd >/dev/null 2>&1
    $NUT_DIR/sbin/upsmon >/dev/null 2>&1
}

##
# Start of script
#
case "$1" in
        start)
            ups_start
            ;;
        stop)
            ups_stop
            ;;
        restart)
            ups_stop
            while pgrep upsd > /dev/null
            do
                sleep 1
            done
            ups_start
            ;;
        *)
            echo ""
            echo "Usage: `basename $0` { start | stop | restart }"
            echo ""
            exit 64
            ;;
esac

# vi /var/svc/manifest/network/nut.xml

<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">

<service_bundle type='manifest' name='nut'>
<service name='application/nut' type='service' version='1'>
   
    <instance name='default' enabled='false'>

        <dependency name='network'
           grouping='require_all'
           restart_on='error'
           type='service'>
           <service_fmri value='svc:/milestone/network:default'/>
        </dependency>

        <dependency name='filesystem-local'
           grouping='require_all'
           restart_on='none'
           type='service'>
           <service_fmri
            value='svc:/system/filesystem/local:default'/>
        </dependency>

        <exec_method
           type='method'
           name='start'
           exec='/opt/nut/lib/svc/method/nut start'
           timeout_seconds='60'>
           <method_context />
        </exec_method>

        <exec_method
           type='method'
           name='stop'
           exec='/opt/nut/lib/svc/method/nut stop'
           timeout_seconds='60'>
           <method_context />
        </exec_method>

       <exec_method
           type='method'
           name='refresh'
           exec='/opt/nut/lib/svc/method/nut restart'
           timeout_seconds='60'>
           <method_context />
        </exec_method>

    </instance>

    <stability value='Evolving' />
    <template>
        <common_name>
            <loctext xml:lang='C'>
                Network UPS Tools
            </loctext>
        </common_name>
    </template>

</service>
</service_bundle>

You can download them directly from:
http://blogs.sun.com/mikey/resource/method-nut and http://blogs.sun.com/mikey/resource/manifest-nut

That's everything, time to enable the service and test the configuration:

# svccfg import nut.xml
# svcadm enable svc:/application/nut:default
# /opt/nut/bin/upsc trust@localhost


battery.charge: 95.0
battery.voltage: 13.50
battery.voltage.nominal: 12.0
driver.name: megatec
driver.parameter.pollinterval: 2
driver.parameter.port: /dev/ttya
driver.version:
driver.version.internal: 1.5.4
input.frequency: 49.9
input.voltage: 247.0
input.voltage.fault: 247.0
input.voltage.maximum: 252.3
input.voltage.minimum: 243.0
output.voltage: 247.0
output.voltage.nominal: 230.0
ups.beeper.status: enabled
ups.delay.shutdown: 0
ups.delay.start: 2
ups.load: 11.0
ups.mfr: unknown
ups.model: unknown
ups.serial: unknown
ups.status: OL
ups.temperature: 25.0

You should be able to see the output similar to this above, which is a kind of confirmation that everything works fine.

[5] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg
Comments:

Shouldn't have .conf file ended up in /etc/opt/nut/, and data files/home dir in /var/opt/nut/?

Posted by UX-admin on November 10, 2007 at 10:42 PM GMT #

How about to allow the ups daemon (i.e. ups user account) to shutdown by assigning the apropriate role? How to do that?

Posted by paul on November 24, 2007 at 01:56 AM GMT #

1. Check your shutdown command: 'poweroff' bypasses shutdown scripts IFAIK. I'd recommend 'shutdown -y -i 5 -g 90' to allow services to shutdown cleanly.
2. GCC isn't very consistent in it's options: for SPARC, it doesn't have -march or -arch like for many other targets. Autoconf does not honour that. It generates "-xarch=v9" (this is complete garbage) in the makefiles and I can not find this in the *.in files. I had to fix this manually to "-mcpu=v9", as well as the path to be /usr/local/ups (default); I prefer /opt for 3rd party SW that gets installed with 'pkgadd'. No SNMP, no CGI, besides that it works fine.

Posted by Paul on January 23, 2008 at 05:48 AM GMT #

@paul

a separate role wont be required. I misunderstood the documentation on this. What upsmon does is, it starts one process as root (the one to issue the SHUTDOWNCMD), and forks the second as user specified in RUN_AS_USER for ups monitoring purposes, so you can safely set RUN_AS_USER to ups. Thanks for pointing this out.

@Paul

not sure if the same Paul as the author of the previous comment, so yes, 'poweroff' is not ideal here, I agree -- thanks.

Posted by Michal Nowak on February 02, 2008 at 04:00 PM GMT #

Hi Mikey,

Let me explain, my need. I need this NUT tool to work on SUN M4000, Linux & windows as well. My system also has Oracle 10g database (its not cluster). But, we have zones running with different Oracle Listner name.

Incase, of manual shutdown we login to zones and shutdown the database. And, the zones and then the system. Can you provide your valuable tips for using this NUT tool to shutdown my Sun server safely.

Thanks,

Rajesh

Posted by RAJESH PRASAD on August 27, 2009 at 08:47 PM BST #

Post a Comment:
  • HTML Syntax: NOT allowed