xorl %eax, %eax

How-to: pfsense NUT UPS Monitoring with Email Notification

leave a comment »

While recently working on setting up a router based on pfsense, I came across this issue. To begin with, I was using the stable release (currently 1.2.3-RELEASE) of pfsense so everything discussed here applies to this version.

To install NUT, the only thing you have to do is to move to “System -> Packages” and select the “NUT” package.



Finally, hit install that will download and install the requested package.



Next, you can go to “Services -> NUT -> NUT Settings” and initialize it with information based on your UPS.



Normally, after setting everything up you will be able to view the “NUT Status” tab that will be similar to the following.



Now, the problem is that you only have this crappy monitoring page. I wanted to have email notifications for some specific events since I might not be able to visit the web interface all the time.
Here is the solution…

Login using SSH to the pfsense box and select option 8 to spawn a new shell.



By default the provided shell is tcsh.

# ps -p $$
  PID  TT  STAT      TIME COMMAND
 3449  p0  S      0:00.01 /bin/tcsh
#

So, you might find it more convenient to enable tab completion and listing of the symbolic links using the following command.

# set autolist listlinks

Now, you could be thinking that we only have to edit the configuration file like a common NUT installation but unfortunately, this is not the case.

The way pfsense is implemented, it uses PHP include files to initialize the configuration of each service. With that being said, have a look in /usr/local/pkg/nut.inc file. As you can see, even if you edit the configuration file (upsmon.conf), it will be restored to its initial configuration at each service restart. To avoid this edit the PHP include file to remove any references to upsmon.conf. In my case, here is the diff file.

--- nut.inc.orig	2011-06-05 14:42:31.148479200 +0300
+++ nut.inc	2011-06-05 14:43:30.152277600 +0300
@@ -159,7 +159,7 @@
 		nut_action('stop');
 
 		@unlink(NUT_RCFILE);
-		@unlink(NUT_DIR.'/upsmon.conf');
 		@unlink(NUT_DIR.'/ups.conf');
 		@unlink(NUT_DIR.'/upsd.conf');
 		@unlink(NUT_DIR.'/upsd.users');
@@ -178,12 +178,6 @@
 			return false;
 
 		/* upsmon.conf */
-		$upsmon_conf = <<<EOD
-MONITOR {$remotename}@{$remoteaddr} 1 {$remoteuser} {$remotepass} slave
-MINSUPPLIES 1
-SHUTDOWNCMD "/sbin/shutdown {$shutdownflag} +0"
-POWERDOWNFLAG /etc/killpower
-EOD;
 	
 		$stop = <<<EOD
 if [ `pgrep upsmon | wc -l` != 0 ]; then
@@ -198,7 +192,6 @@ EOD;
 
 		/* write out configuration */
 		conf_mount_rw();
-		nut_write_config(NUT_DIR.'/upsmon.conf', $upsmon_conf, 0640, 'uucp');
 		write_rcfile(array(
 			'file' => 'nut.sh',
 	    	'start' => $start,
@@ -276,12 +269,13 @@ EOD;
 		}
 
 		/* upsmon.conf */
-		$upsmon_conf = <<<EOD

-MONITOR {$name}@localhost 1 monuser mypass master
-MINSUPPLIES 1
-SHUTDOWNCMD "/sbin/shutdown {$shutdownflag} +0"
-POWERDOWNFLAG /etc/killpower
-EOD;
 
 		$stop = <<<EOD
 	if [ `pgrep upsmon | wc -l` != 0 ]; then
@@ -331,7 +325,7 @@ EOD;
 		nut_write_config(NUT_DIR.'/ups.conf', $ups_conf);
 		nut_write_config(NUT_DIR.'/upsd.conf', $upsd_conf, 0640, 'uucp');
 		nut_write_config(NUT_DIR.'/upsd.users', $upsd_users, 0640, 'uucp');
-		nut_write_config(NUT_DIR.'/upsmon.conf', $upsmon_conf, 0640, 'uucp');
 		write_rcfile(array(
 			'file' => 'nut.sh',
     		'start' => $start,
@@ -383,7 +377,7 @@ EOD;
 
 			conf_mount_rw();
 			unlink(NUT_RCFILE);
-			unlink(NUT_DIR.'/upsmon.conf');
 			/* might not always exist */
 			@unlink(NUT_DIR.'/ups.conf');
 			@unlink(NUT_DIR.'/upsd.conf');

Remember, before editing the configuration file you must enable write access to it using the provided script and then re-enable the read-only protection.

# /etc/rc.conf_mount_rw
# vi /usr/local/etc/nut/upsmon.conf
# /etc/rc.conf_mount_ro

The configuration is fairly simple, especially if you had any prior experience with NUT. Here is mine…

MONITOR SOMEUPS@localhost 1 monuser mypass master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POWERDOWNFLAG /etc/killpower

NOTIFYFLAG ONBATT EXEC+SYSLOG
NOTIFYFLAG ONLINE EXEC+SYSLOG
NOTIFYFLAG REPLBATT EXEC+SYSLOG
NOTIFYFLAG SHUTDOWN EXEC+SYSLOG
NOTIFYFLAG LOWBATT SYSLOG

NOTIFYCMD "/usr/local/etc/nut/notification.sh"

As you can see, I have added five notification flags and four of them will trigger the execution of the notification command which is a simple shell script, while all of them will be logged using the system’s logging service.

But the problem isn’t over yet. Once again, pfsense does not have any package or build-in utility to send emails. Furthermore, its default shell is tcsh and I do not have sufficient experience to write a such a script with it. Hopefully, after a couple of minutes of poking around I discovered that it also has a /bin/sh as well as /usr/bin/telnet so the script was quite predictable…

#!/bin/sh

SUBJECT=""
CONTENT=""
MAILSRV="XXX.XXX.XXX.XXX"

if [ $NOTIFYTYPE = "ONBATT" ]; then
        SUBJECT="SUBJECT: UPS: Switched to Battery Mode."
        CONTENT="Due to main power loss the system is switching to battery mode."
fi

if [ $NOTIFYTYPE = "ONLINE" ]; then
        SUBJECT="SUBJECT: UPS: Back to Power Line"
        CONTENT="The system has returned to power line mode."
fi

if [ $NOTIFYTYPE = "SHUTDOWN" ]; then
        SUBJECT="SUBJECT: UPS: Execution of Forced Shutdown"
        CONTENT="Due to main power line and battery power loss, the system will be forced to shutdown."
fi

if [ $NOTIFYTYPE = "REPLBATT" ]; then
        SUBJECT="SUBJECT: UPS: Battery Replacement Notification"
        CONTENT="System notification for UPS battery replacement."
fi


if [ -z $SUBJECT ]; then
        if [ -z $CONTENT ]; then
                exit 0
        fi
else
	(
        	sleep 0.5
	        echo "EHLO pfsense"
	        sleep 0.5
	        echo "MAIL FROM: ups@somewhere"
	        sleep 0.5
	        echo "RCPT TO: my@email.account"
	        sleep 0.5
	        echo "DATA"
	        sleep 0.5
	        echo $SUBJECT
	        sleep 0.5
	        echo "TO: my@email.account"
	        sleep 0.5
	        echo " "
	        echo $CONTENT
	        sleep 0.5
	        echo "."
	        sleep 0.5
	        echo "QUIT"
	) | telnet $MAILSRV 25
fi

Guess what?
It’s not over yet… After a couple of hours of runtime you’ll almost certainly notice that the NUT daemon loses its connection with the UPS and you have to manually restart it. After some web search I found that this is a known issue (check this out).

Here the solution is simply to add a cron-job that will restart the service every 15 minutes or so…

# crontab -e

And add something like this (for restarting every 15 minutes)…

*/15 * * * * /usr/local/etc/rc.d/nut.sh restart

And check that it was successfully written…

# crontab -l
*/15 * * * * /usr/local/etc/rc.d/nut.sh restart
#

We’re finally all set. NUT UPS monitoring with email notification on pfsense. To conclude, I wrote this post because I wasn’t able to find any of the above information so I think it might help some people doing the same task in the future.

About these ads

Written by xorl

June 5, 2011 at 17:55

Posted in administration, pfsense

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 58 other followers