#!/bin/sh
#
# check_apcupsd 1.2
# Nagios plugin to monitor APC Smart-UPSes using apcupsd.
#
# Copyright (c) 2008 Martin Toft <mt@martintoft.dk>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#
# Example configuration
#
# commands.cfg:
#
# define command {
#         command_name check_apcupsd
#         command_line $USER1$/check_apcupsd -w $ARG2$ -c $ARG3$ $ARG1$
#         }
# 
# define command {
#         command_name check_apcupsd_no_notify
#         command_line $USER1$/check_apcupsd $ARG1$
#         }
#
# ups1.cfg:
#
# define service {
#         use generic-service
#         host_name ups1
#         service_description CHARGE
#         check_command check_apcupsd!bcharge!95!50
#         }
# 
# define service {
#         use generic-service
#         host_name ups1
#         service_description TEMP
#         check_command check_apcupsd!itemp!35!40
#         }
# 
# define service {
#         use generic-service
#         host_name ups1
#         service_description LOAD
#         check_command check_apcupsd!loadpct!70!85
#         }
# 
# define service {
#         use generic-service
#         host_name ups1
#         service_description TIMELEFT
#         check_command check_apcupsd_no_notify!timeleft
#         }

APCACCESS=/sbin/apcaccess

usage()
{
	echo "usage: check_apcupsd [-c critical_value] [-h hostname] [-p port]"
	echo -n "                     [-w warning_value] "
	echo "<bcharge|itemp|loadpct|timeleft>"
	echo
	echo "hostname and port defaults to localhost and 3551, respectively."
	echo
	echo "checks:"
	echo "    bcharge  = battery charge, measured in percent."
	echo "    itemp    = internal temperature, measured in degree Celcius."
	echo "    loadpct  = load percent, measured in percent (do'h!)."
	echo "    timeleft = time left with current battery charge and load,"
	echo "               measured in minutes."
	exit 3
}

HOSTNAME=localhost
PORT=3551

while getopts c:h:p:w: OPTNAME; do
	case "$OPTNAME" in
	h)
		HOSTNAME="$OPTARG"
		;;
	p)
		PORT="$OPTARG"
		;;
	w)
		WARNVAL="$OPTARG"
		;;
	c)
		CRITVAL="$OPTARG"
		;;
	*)
		usage
		;;
	esac
done

ARG="$@"
while [ $OPTIND -gt 1 ]; do
	ARG=`echo "$ARG" | sed 's/^[^ ][^ ]* *//'`
	OPTIND=$(($OPTIND-1))
done

if [ "$ARG" != "bcharge" -a "$ARG" != "itemp" -a "$ARG" != "loadpct" \
	-a "$ARG" != "timeleft" ]; then
	usage
fi

if [ "`echo $PORT | grep '^[0-9][0-9]*$'`" = "" ]; then
	echo "Error: port must be a positive integer!"
	exit 3
fi

if [ "$WARNVAL" != "" -a "`echo $WARNVAL | grep '^[0-9][0-9]*$'`" = "" ]; then
	echo "Error: warning_value must be a positive integer!"
	exit 3
fi

if [ "$CRITVAL" != "" -a "`echo $CRITVAL | grep '^[0-9][0-9]*$'`" = "" ]; then
	echo "Error: critical_value must be a positive integer!"
	exit 3
fi

if [ "$WARNVAL" != "" -a "$CRITVAL" != "" ]; then
	if [ "$ARG" = "bcharge" -o "$ARG" = "timeleft" ]; then
		if [ $WARNVAL -le $CRITVAL ]; then
			echo "Error: warning_value must be greater than critical_value!"
			exit 3
		fi
	else
		if [ $WARNVAL -ge $CRITVAL ]; then
			echo "Error: warning_value must be less than critical_value!"
			exit 3
		fi
	fi
fi

if [ ! -x "$APCACCESS" ]; then
	echo "Error: $APCACCESS must exist and be executable!"
	exit 3
fi

$APCACCESS status $HOSTNAME:$PORT > /dev/null
if [ $? -ne 0 ]; then
	# The error message from apcaccess will do fine.
	exit 3
fi

VALUE=`$APCACCESS status $HOSTNAME:$PORT | grep -i ^$ARG | \
	sed 's/.*:  *\([0-9.][0-9.]*\)[^0-9.].*/\1/'`
if [ "$VALUE" != "0" ]; then
	VALUE=`echo $VALUE | sed 's/^0*//'`
fi
ROUNDED=`echo $VALUE | sed 's/\..*//'`

case "$ARG" in
bcharge)
	if [ "$CRITVAL" != "" ]; then
		if [ $ROUNDED -lt $CRITVAL ]; then
			echo "CRITICAL - Battery Charge: ${VALUE}%"
			exit 2
		fi
	fi
	if [ "$WARNVAL" != "" ]; then
		if [ $ROUNDED -lt $WARNVAL ]; then
			echo "WARNING - Battery Charge: ${VALUE}%"
			exit 1
		fi
	fi
	echo "OK - Battery Charge: ${VALUE}%"
	;;
itemp)
	if [ "$CRITVAL" != "" ]; then
		if [ $ROUNDED -ge $CRITVAL ]; then
			echo "CRITICAL - Internal Temperature: $VALUE C"
			exit 2
		fi
	fi
	if [ "$WARNVAL" != "" ]; then
		if [ $ROUNDED -ge $WARNVAL ]; then
			echo "WARNING - Internal Temperature: $VALUE C"
			exit 1
		fi
	fi
	echo "OK - Internal Temperature: $VALUE C"
	;;
loadpct)
	if [ "$CRITVAL" != "" ]; then
		if [ $ROUNDED -ge $CRITVAL ]; then
			echo "CRITICAL - Load: ${VALUE}%"
			exit 2
		fi
	fi
	if [ "$WARNVAL" != "" ]; then
		if [ $ROUNDED -ge $WARNVAL ]; then
			echo "WARNING - Load: ${VALUE}%"
			exit 1
		fi
	fi
	echo "OK - Load: ${VALUE}%"
	;;
timeleft)
	if [ "$CRITVAL" != "" ]; then
		if [ $ROUNDED -lt $CRITVAL ]; then
			echo "CRITICAL - Time Left: $VALUE Minutes | UPS=$VALUE;$CRITVAL;$WARNVAL"
			exit 2
		fi
	fi
	if [ "$WARNVAL" != "" ]; then
		if [ $ROUNDED -lt $WARNVAL ]; then
			echo "WARNING - Time Left: $VALUE Minutes | UPS=$VALUE;$CRITVAL;$WARNVAL"
			exit 1
		fi
	fi
	echo "OK - Time Left: $VALUE Minutes | UPS=$VALUE;$CRITVAL;$WARNVAL"
	;;
esac

exit 0
