#!/usr/bin/perl
#
# check_cisco_envmon - nagios plugin 
#
# Copyright (C) 2006 Larry Low
#
# 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 (at your option) 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.
#
# Report bugs to:  llow0@yahoo.com
#
# Primary MIB reference - CISCO-ENVMON-MIB
#
# Version 0.4
#  - added snmpv3 support
# Version 0.3
#  - fix Typo of UNKNOWN
#  - fix $snmp was not checked for being defined - fixed (thanks Sylvian Collilieux)
# Version 0.2
#  - added conformed with ePN
#
use strict;
use warnings;
use lib '/usr/lib/nagios/plugins';
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use vars qw($PROGNAME);

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
	print ("ERROR: Plugin took too long to complete (alarm)\n");
	exit $ERRORS{"UNKNOWN"};
};
alarm($TIMEOUT);

$PROGNAME = "check_cisco_envmon.pl";
sub print_help ();
sub print_usage ();

my ($opt_h,$opt_V,$opt_sps);
my $community = "public";
my $snmp_version = 2;
my ($hostname);

use Getopt::Long;
&Getopt::Long::config('bundling');
GetOptions(
	"V"   => \$opt_V,	"version"    => \$opt_V,
	"h"   => \$opt_h,	"help"       => \$opt_h,
	"C=s" => \$community,	"community=s"=> \$community,
	"H=s" => \$hostname,	"hostname=s" => \$hostname,
	"v=i" => \$snmp_version,"snmp_version=i" => \$snmp_version,
	"s"   => \$opt_sps,	"sps"        => \$opt_sps
);

# -h & --help print help
if ($opt_h) { print_help(); exit $ERRORS{'OK'}; }
# -V & --version print version
if ($opt_V) { print_revision($PROGNAME,'$Revision: 0.4 $ '); exit $ERRORS{'OK'}; }
# Invalid hostname print usage
if (!utils::is_hostname($hostname)) { print_usage(); exit $ERRORS{'UNKNOWN'}; }

# Setup SNMP object
use Net::SNMP qw(INTEGER OCTET_STRING IPADDRESS OBJECT_IDENTIFIER NULL);
my ($snmp, $snmperror);
if ($snmp_version == 2) {
	($snmp, $snmperror) = Net::SNMP->session(
		-hostname => $hostname,
		-version => 'snmpv2c',
		-community => $community
	);
} elsif ($snmp_version == 3) {
	my ($v3_username,$v3_password,$v3_protocol,$v3_priv_passphrase,$v3_priv_protocol) = split(":",$community);
	my @auth = ();
	if (defined($v3_password)) { push(@auth,($v3_password =~ /^0x/) ? 'authkey' : 'authpassword',$v3_password); }
	if (defined($v3_protocol)) { push(@auth,'authprotocol',$v3_protocol); }
	if (defined($v3_priv_passphrase)) { push(@auth,($v3_priv_passphrase =~ /^0x/) ? 'privkey' : 'privpassword',$v3_priv_passphrase); }
	if (defined($v3_priv_protocol)) { push(@auth,'privprotocol',$v3_priv_protocol); }

	($snmp, $snmperror) = Net::SNMP->session(
		-hostname => $hostname,
		-version => 'snmpv3',
		-username => $v3_username,
		@auth
	);
} else {
	($snmp, $snmperror) = Net::SNMP->session(
		-hostname => $hostname,
		-version => 'snmpv1',
		-community => $community
	);
}

if (!defined($snmp)) {
	print ("UNKNOWN: SNMP error: $snmperror\n");
	exit $ERRORS{'UNKNOWN'};
}


my $state = 'UNKNOWN';
my $output = '';
# Begin plugin check code
{
	my $ciscoEnvMonObjects = "1.3.6.1.4.1.9.9.13.1";

	#voltage
	my $ciscoEnvMonVoltageStatusDescr = "1.3.6.1.4.1.9.9.13.1.2.1.2";
	my $ciscoEnvMonVoltageStatusValue = "1.3.6.1.4.1.9.9.13.1.2.1.3";
	my $ciscoEnvMonVoltageState = "1.3.6.1.4.1.9.9.13.1.2.1.7";

	#temperature
	my $ciscoEnvMonTemperatureStatusDescr = "1.3.6.1.4.1.9.9.13.1.3.1.2";
	my $ciscoEnvMonTemperatureStatusValue = "1.3.6.1.4.1.9.9.13.1.3.1.3";
	my $ciscoEnvMonTemperatureState = "1.3.6.1.4.1.9.9.13.1.3.1.6";

	#fans
	my $ciscoEnvMonFanStatusDescr = "1.3.6.1.4.1.9.9.13.1.4.1.2";
	my $ciscoEnvMonFanState = "1.3.6.1.4.1.9.9.13.1.4.1.3";

	#supply
	my $ciscoEnvMonSupplyStatusDescr = "1.3.6.1.4.1.9.9.13.1.5.1.2";
	my $ciscoEnvMonSupplyState = "1.3.6.1.4.1.9.9.13.1.5.1.3";

	my %CiscoEnvMonStates = (
		1 => "normal(1)",
		2 => "warning(2)",
		3 => "critical(3)",
		4 => "shutdown(4)",
		5 => "notPresent(5)",
		6 => "notFunctioning(6)"
	);

	my @snmpoids;
	my $result = $snmp->get_table(
		-baseoid => $ciscoEnvMonObjects
	);
	if (!defined($result)) {
		my $answer = $snmp->error;
		$snmp->close;
		print ("UNKNOWN: SNMP error: $answer\n");
		exit $ERRORS{'UNKNOWN'};
	}

	my $pwrok = 0;
	$state = 'OK';
	foreach my $oid (keys(%{$result})) {
		if ($oid =~ /$ciscoEnvMonVoltageState/) {
			my $key = $';
			my $tempdescr = "Voltage '".$result->{"$ciscoEnvMonVoltageStatusDescr$key"}."'";
			if (defined($result->{"$ciscoEnvMonVoltageStatusValue$key"})) {
				$tempdescr .= " value is '".$result->{"$ciscoEnvMonVoltageStatusValue$key"}."'";
			}
			$tempdescr .= " state '".$CiscoEnvMonStates{$result->{"$ciscoEnvMonVoltageState$key"}}."' ";
			
			if (($result->{$oid} == 1) || ($result->{$oid} == 5)) {
				# do nothing
			} elsif ($result->{$oid} == 2) {
				$output .= $tempdescr;
				if ($state eq 'OK') {
					$state = 'WARNING';
				}
			} else {
				$output .= $tempdescr;
				$state = 'CRITICAL';
			}
		} elsif ($oid =~ /$ciscoEnvMonTemperatureState/) {
			my $key = $';
			my $tempdescr = "Temp '".$result->{"$ciscoEnvMonTemperatureStatusDescr$key"}."'";
			if (defined($result->{"$ciscoEnvMonTemperatureStatusValue$key"})) {
				$tempdescr .= " value is '".$result->{"$ciscoEnvMonTemperatureStatusValue$key"}."'";
			}
			$tempdescr .= " state '".$CiscoEnvMonStates{$result->{"$ciscoEnvMonTemperatureState$key"}}."' ";
			
			if (($result->{$oid} == 1) || ($result->{$oid} == 5)) {
				# do nothing
			} elsif ($result->{$oid} == 2) {
				$output .= $tempdescr;
				if ($state eq 'OK') {
					$state = 'WARNING';
				}
			} else {
				$output .= $tempdescr;
				$state = 'CRITICAL';
			}
		} elsif ($oid =~ /$ciscoEnvMonFanState/) {
			my $key = $';
			my $tempdescr = "Fan '".$result->{"$ciscoEnvMonFanStatusDescr$key"}."' state '".$CiscoEnvMonStates{$result->{"$ciscoEnvMonFanState$key"}}."' ";
			
			if (($result->{$oid} == 1) || ($result->{$oid} == 5)) {
				# do nothing
			} elsif ($result->{$oid} == 2) {
				$output .= $tempdescr;
				if ($state eq 'OK') {
					$state = 'WARNING';
				}
			} else {
				$output .= $tempdescr;
				$state = 'CRITICAL';
			}
		} elsif ($oid =~ /$ciscoEnvMonSupplyState/) {
			my $key = $';
			my $tempdescr = "Supply '".$result->{"$ciscoEnvMonSupplyStatusDescr$key"}."' state '".$CiscoEnvMonStates{$result->{"$ciscoEnvMonSupplyState$key"}}."' ";

			if (defined($opt_sps) && ($result->{"$ciscoEnvMonSupplyStatusDescr$key"} eq "Redundant Pwr Supply")) {
				$pwrok = 1;
			}
			
			if (($result->{$oid} == 1) || ($result->{$oid} == 5)) {
				# do nothing
				if (defined($opt_sps)) {				
					$pwrok = 1;
				}
			} elsif ($result->{$oid} == 2) {
				$output .= $tempdescr;
				if ($state eq 'OK') {
					if (!$pwrok) {
						$state = 'WARNING';
					}
				}
				if (defined($opt_sps)) {
					$output .= "(ignored) ";
				}

			} else {			
				$output .= $tempdescr;
				if (!$pwrok) {
					$state = 'CRITICAL';
				}
				if (defined($opt_sps)) {
					$output .= "(ignored) ";
				}
			}
		}
	}
	if ((length($output) == 0) && ($state eq 'OK')) {
		$output = "Environment checks return all normal.";
	}
}
print "$state - $output\n";
exit $ERRORS{$state};

sub print_help() {
	print_revision($PROGNAME,'$Revision: 0.4 $ ');
	print "Copyright (c) 2006 Larry Low\n";
	print "This program is licensed under the terms of the\n";
	print "GNU General Public License\n(check source code for details)\n";
	print "\n";
	printf "Check environmental status of Cisco via SNMP.\n";
	print "\n";
	print_usage();
	print "\n";
	print " -H (--hostname)     Hostname to query - (required)\n";
	print " -C (--community)    SNMP read community or v3 auth (defaults to public)\n";
	print "                     (v3 specified as username:authpassword:... )\n";
	print "                       username = SNMPv3 security name\n";
	print "                       authpassword = SNMPv3 authentication pass phrase (or hexidecimal key)\n";
	print "                       authprotocol = SNMPv3 authentication protocol (md5 (default) or sha)\n";
	print "                       privpassword = SNMPv3 privacy pass phrase (or hexidecmal key)\n";
	print "                       privprotocol = SNMPv3 privacy protocol (des (default) or aes)\n";
	print " -v (--snmp_version) 1 for SNMP v1\n";
	print "                     2 for SNMP v2c (default)\n";
	print "                     3 for SNMP v3\n";
	print " -s (--sps)          Single power supply used\n";
	print " -V (--version)      Plugin version\n";
	print " -h (--help)         usage help\n";
	print "\n";
	support();
}

sub print_usage() {
	print "Usage: \n";
	print "  $PROGNAME -H <HOSTNAME> [-C <community>]\n";
	print "  $PROGNAME [-h | --help]\n";
	print "  $PROGNAME [-V | --version]\n";
}
