#!/usr/bin/perl
eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
	if 0; # not running under some shell
#
#		check_apcupsd.sh: Nagios reporting for apcupsd
#		Copyright (C) 2008 Ithaka Harbors, Inc.
#
#		This program is free software; you can redistribute it and/or modify
#		it under the terms of the GNU General Public License as published by
#		the Free Software Foundation; either version 2 of the License, or
#		any later version.
#
#		This program is distributed in the hope that it will be useful,
#		but WITHOUT ANY WARRANTY; without even the implied warranty of
#		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#		GNU General Public License for more details.
#
#		You should have received a copy of the GNU General Public License
#		along with this program; if not, write to the Free Software
#		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

=head1 NAME

check_apcupsd - Nagios Uninterruptible Power Supply Status Check

=head1 SYNOPSIS

B<check_acpupsd>
[B<-h>, B<--help>]
[B<-V>, B<--version>]

=head1 DESCRIPTION

Run apcaccess to get the current status of the UPS.

=head1 REQUIREMENTS

=over 4

=item B<apcupsd>

The system must run apcupsd.

=item B<Nagios::Plugin>

This provides the return codes that Nagios wants.

=back

=head1 COMMAND LINE OPTIONS

=over 4

=item B<-s> or B<--stats>

A semicolon separated list of values from apcaccess to return, with optional
warn and critical levels. The value must match the case sensitive output from
apcaccess (BCHARGE, not bcharge to check the batter charge). The default is
BCHARGE,@50:95,@0:50;TIMELEFT,@5:10,@0:5;ITEMP,35,40;LOADPCT,70,85 (critical
battery charge from 0 to 50%, warn from 50 to 95%; critical time left from 0 to
5 minutes, warn from 5 to 10; critical temperature above 40 Celsius, warn from
35 to 40; critical load above 85%, warn above 70).

=item B<-v> or B<--verbose>

Outputs debugging information on STDERR.

=item B<-h> or B<--help>

Prints usage information and exits.

=item B<-v> or B<--version>

Prints version information and exits.

=back

=head1 AUTHOR

Alan Brenner - alan.brenner@ithaka.org; I've updated this from the version
at http://www.nagiosexchange.org/cgi-bin/page.cgi?g=Detailed%2F2656.html;d=1 by
switch to perl and making the script able to monitor multiple apcupsd values
at once.

=head1 BUGS

Undoubtedly there are some in here. I (Alan Brenner) have endevored to keep this
simple.

=head1 SEE ALSO

B<plw(1)>


=head1 COPYRIGHT

	Copyright (C) 2008 Ithaka Harbors, Inc.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

=cut

use strict;
use Data::Dumper;
use Nagios::Plugin;
use Nagios::Plugin::Threshold;

our($np,			# Nagios::Plugin object
	$debug,			# verbose or not
	@stats,			# statistics to return
	%stats,			# hash of @stats, with warn and critical as a list
	$line,			# line of output from apcaccess
	$ii,			# for loop index
	@values,		# values to check for return code
	$thresh,		# threshold object
	%abbrevs,		# sprintf abbreviations for return code values
	@status,		# return code line values
	$apc			# check_apcupsd.pl return code
);

%abbrevs = ('BCHARGE' => '%.1f%%', 'ITEMP' => '%.1fdeg',
			'TIMELEFT' => '%.1fmin', 'LOADPCT' => '%.1f%% load');

$np = Nagios::Plugin->new(version => 'Ithaka 1.0',
	usage => "Usage: %s [ -v|--verbose ] [ -t <timeout> ] [ -s <STAT> ]");
$np->add_arg(spec => 'stats|s=s',
	help => '-s, --stats=STAT[,w,c][:STAT[,w,c]....] A semicolon separated list'
		. ' of values from apcaccess to return, with optional warn and critical'
		. ' levels. Default is: BCHARGE,@50:95,@0:50;TIMELEFT,@5:10,@0:5;'
		. 'ITEMP,35,40;LOADPCT,70,85.');

# Parse @ARGV and process standard arguments (e.g. usage, help, version)
$np->getopts;
# Timeout, if necessary
alarm $np->opts->timeout;
$debug = $np->opts->verbose;
unless (@stats = split(/;/, $np->opts->stats)) {
	@stats = ('BCHARGE,@50:95,@0:50', 'TIMELEFT,@5:10,@0:5',
			  'ITEMP,35,40', 'LOADPCT,70,85');
}
foreach $ii (@stats) {
	@values = split(/,/, $ii);
	if (scalar(@values) == 3) {
		$stats{$values[0]} = [$values[1], $values[2]];
	} else {
		$stats{$values[0]} = [undef, undef];
	}
}
if ($debug) {
	my $ii = Data::Dumper->new([\%stats], ['stats']);
	$ii->Indent(1);
	warn $ii->Dump();
}

$apc = OK;
open APC, "/sbin/apcaccess status|" or
	$np->nagios_die("Cannot run apcaccess: $!");
while ($line = <APC>) {
	chomp $line;
	warn "'$line'\n" if $debug;
	@stats = split(/\s*:\s*/, $line, 2);
	if (exists $stats{$stats[0]}) {
		@values = split(/\s+/, $stats[1]);
		if (defined ${stats{$stats[0]}}[0]) {
			$thresh = Nagios::Plugin::Threshold->set_thresholds(
				warning => ${stats{$stats[0]}}[0],
				critical => ${stats{$stats[0]}}[1]);
		} else {
			$thresh = undef;
		}
		$np->add_perfdata(label => $stats[0],
						  value => $values[0],
						  threshold => $thresh);
		# save statistics for display
		if (exists $abbrevs{$stats[0]}) {
			push @status, sprintf $abbrevs{$stats[0]}, $values[0];
		} else {
			push @status, $stats[1];
		}
		# return the highest check value
		if ($thresh) {
			next if $apc == CRITICAL;
			$ii = $thresh->get_status($values[0]);
			warn "$values[0] -> $ii\n";
			if ($ii == CRITICAL) {
				$apc = CRITICAL;
			} elsif ($ii == WARNING and $apc == OK) {
				$apc = WARNING;
			}
		}
	}
}
close APC;

$ii = join(', ', @status);
$np->nagios_exit($apc, "UPS needs attention: $ii") if ($apc != OK);
$np->nagios_exit($apc, $ii);

