#!/usr/bin/perl

# check_dellom_snmp
#
# Nagios Plugin 
# Checks Dell OpenManage server health using SNMP
# Pretty crappy
#
# Version: 1.1 (8/11/2004)
# Author: Brad Henshaw (Brad.Henshaw@qcn.com.au || Brad.Henshaw@qbuild.qld.gov.au)
#
# Returns to OS the following values plus prints a textual description of OID statii:
# 0 OK
# 1 WARNING
# 2 CRITICAL
# 3 UNKNOWN
#
# usage: check_dellom_snmp <hostaddress> <community>

use strict;

my $version = 1.1;

# yes we should use SNMP.pm but I'm short on time.
my $snmpget = '/usr/bin/snmpget';

# local criticality values (used only in this script for comparisons)
# 0 OK
# 1 UNKNOWN
# 2 WARNING
# 3 CRITICAL
my %criticalities = (0,'OK', 1,'UNKNOWN', 2,'WARNING', 3,'CRITICAL');

# Nagios status code for OK, UNKNOWN, WARNING  and CRITICAL respectively
# (in other words, maps out criticality code to a nagios status code)
my @nagiosStatus = (0,3,1,2);

# each item in the array corresponds to a status type below (0 is invalid)
#DellStatusRedundancy        ::= INTEGER {
#    INVALID (0)			 -- my addition
#    other(1),               -- redundancy status is not one of the following:
#    unknown(2),             -- redundancy status is unknown (not known or monitored)
#    full(3),                -- object is fully redundant
#    degraded(4),            -- object's redundancy has been degraded
#    lost(5),                -- object's redundancy has been lost
#    notRedundant(6),        -- redundancy status does not apply or object is not redundant
#    redundancyOffline(7)    -- redundancy object taken offline
#}
# first array contains criticality values defined in %criticalities
my @statDellR = (1,2,1,0,3,3,3,3);
my @statDellRDesc = ('INVALID','OTHER','UNKNOWN','FULL','DEGRADED','LOST','NOTREDUNDANT',
					'REDUNDANCYOFFLINE');

# each item in the array corresponds to a status type below (0 is invalid)
#DellStatus                  ::= INTEGER {
#    INVALID (0)			 -- my addition
#    other(1),               -- status is not one of the following:
#    unknown(2),             -- status of object is unknown (not known or monitored)
#    ok(3),                  -- status of object is OK (normal)
#    nonCritical(4),         -- status of object is non-critical (warning)
#    critical(5),            -- status of object is critical (failure)
#    nonRecoverable(6)       -- status of object is non-recoverable (dead)
#}
# first array contains criticality values defined in %criticalities
my @statDell = (1,2,1,0,2,3,3);
my @statDellDesc = ('INVALID','OTHER','UNKNOWN','OK','NONCRITICAL','CRITICAL',
					'NONRECOVERABLE');
my %index = (	'VOLTAGE'	=> 0,
		'FANS'		=> 1,
		'TEMPERATURE'	=> 2,
		'MEMORY'	=> 3,
		'PS'		=> 4,
		'PU'		=> 5,
		'PR'		=> 6,
		'CHASSIS'	=> 7,
		'INTRUSION'	=> 8,
		'EL'		=> 9,
		'ALL'		=> 99 ); # Just to work with the help
	
my %oids = (	'.1.3.6.1.4.1.674.10892.1.200.10.1.12.1', 'Voltage',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.21.1', 'Fans',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.24.1', 'Temperature',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.27.1', 'Memory',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.9.1', 'Power Supply',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.42.1', 'Power Unit',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.6.1', 'Power Redundancy',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.4.1', 'Chassis',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.30.1', 'Intrusion',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.41.1', 'Event Log');

my @oidOrder = ('.1.3.6.1.4.1.674.10892.1.200.10.1.12.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.21.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.24.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.27.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.9.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.42.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.6.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.4.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.30.1',
				'.1.3.6.1.4.1.674.10892.1.200.10.1.41.1');

# define type of status value for each OID in %oids
# 0 == DellStatus, 1 == DellStatusRedundancy
my %oidStatType = ('.1.3.6.1.4.1.674.10892.1.200.10.1.12.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.21.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.24.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.27.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.9.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.42.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.6.1', 1,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.4.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.30.1', 0,
				'.1.3.6.1.4.1.674.10892.1.200.10.1.41.11', 0);
				
exit &main;

sub main {
	my $oidList="";
	my $oidDesc;
	my $snmpResults;
	my $statString="";
	my $server; my $community; my $param;
	my @statusLines;
	my $line;
	my %statusHash;
	my $oid; my $value;
	my $criticality;
	my $mostCritical=0;		# from %criticalities
	my $valuesReturned=0;
	my $possibleComma;
	my $ignore;
	
	($server, $community, $param) = &checkArgs;
	$snmpget = $snmpget . " -v 1 -On $server -c $community ";
	#Testa se snmp esta OK
        `$snmpget .1.3.6.1.2.1.1.1.0 >/dev/null 2>&1`;
        if( $? != 0 ) {
                print "CRITICAL - SNMP nao habilitado\n";
                exit(2);
        }
        `$snmpget .1.3.6.1.4.1.674.10892.1.200.10.1.1.1 >/dev/null 2>&1`;
        if( $? != 0 ) {
                print "CRITICAL - Impossivel encontrar OIDs OpenManager\n";
                exit(2);
        }

	if ($param eq 'ALL') {
		foreach $oid (@oidOrder) { $oidList = $oidList . $oid . ' '; }
	} else {
		$oidList = $oidOrder[$index{$param}] . ' ';
	}

	$snmpResults = `$snmpget $oidList`;

	# populate the status hash with the OIDs as keys; default to no value received/unknown (1)
	if ($param eq 'ALL') {
		foreach $oid (keys %oids) {
			$statusHash{$oid} = 0;
		}
	} else {
		$statusHash{$oidOrder[$index{$param}]} = 0;
	}
	
	# massage snmpget output and extract the results into the status hash
	$snmpResults =~ s/enterprises/\.1\.3\.6\.1\.4\.1/sg;
	$snmpResults =~ s/ //sg; # remove those pesky spaces for ease of parsing
	@statusLines = split(/\n/, $snmpResults); # break into lines and strip off \n

	#for(my $i=0; $i<=$#statusLines; $i++) {
	#	print "$statusLines[$i] \n";
	#}

	# this only adds into statusHash the OIDs we have defined above. Others which are
	# returned by snmpget (not sure why, but being paranoid) are silently ignored.
	foreach $line (@statusLines) {
		($oid, $ignore, $value) = split(/[:=]/, $line);
		#print "$oid    --->  $value\n";
		if (! ($statusHash{$oid} eq '')) {
			$statusHash{$oid} = $value;
			$valuesReturned++;
		}
	}

	# Did we get any valid responses at all? (i.e. did snmpget completely fail?)
	if ($valuesReturned == 0) {
		$mostCritical = 1;
		$statString = "No valid response received";
	} else {
		# determine most critical status code - do this after retrieving them all so
		# we can take into account any OIDs not returned by snmpget
		# also build up the final output string
		foreach $oid (@oidOrder) {

			next if (($param ne 'ALL') && ($oid ne $oidOrder[$index{$param}]));

			# value in this case is the value returned by snmpget, not the value we use
			# in this script for criticality
			$value = $statusHash{$oid};
			$criticality = &getCriticality($oid,$value);
	
			if ($criticality >= $mostCritical) {
				# update mostcritical value and place this item at the front of the
				# status string
				$mostCritical = $criticality;
				if ($statString eq '') {
					$possibleComma = '';
				} else {
					$possibleComma = ', ';
				}
				$statString = "$oids{$oid}: " . &getStatDesc($oid,$value)
								. $possibleComma . $statString;
			} else {
				if (!($statString eq '')) { $statString = $statString . ", "; }
				$statString = $statString . "$oids{$oid}: " . &getStatDesc($oid,$value);
			}
		}
	}
		
	print "$statString\n";
	
	return $nagiosStatus[$mostCritical];
}

# get a local criticality code for the given OID's value (where value is the numeric
# value returned by snmpget for this OID)
sub getCriticality {
	my ($oid,$value) = @_;
	my $criticality;

	#print $oidStatType{$oid}." -- ";

	if ($oidStatType{$oid} == 0) {
		$criticality = $statDell[$value];
	} else {
		$criticality = $statDellR[$value];
	}
	
	return $criticality;
}

# gets the status description for given OID and snmpget value
sub getStatDesc {
	my ($oid,$value) = @_;
	my $statusString;
	
	# 0 == DellStatus, 1 == DellStatusRedundancy
	if ($oidStatType{$oid} == 0) {
		$statusString = $statDellDesc[$value];
	} else {
		$statusString = $statDellRDesc[$value];
	}

	return $statusString;
}

# checks command-line arguments and returns hostname and community in an array
# terminates script with error message to stdout if invalid arguments
sub checkArgs {
	if (scalar @ARGV == 3 && defined($index{$ARGV[2]})) {
		return ($ARGV[0], $ARGV[1], $ARGV[2]);
	} else {
		print "Usage:\n\t$0 [hostname] [community] [parameter]\n\n";
		print "Parameters Available:\n";
		print "\tVOLTAGE = voltage status\n";
                print "\tFANS = fan status\n";
                print "\tTEMPERATURE = temperature status\n";
                print "\tMEMORY = memory status\n";
                print "\tPS = power supply\n";
                print "\tPU = power unity\n";
                print "\tPR = power redundancy\n";
                print "\tCHASSIS = chassis status\n";
                print "\tINTRUSION = intrusion\n";
                print "\tEL = Event Log\n";
                print "\tALL = All status informations\n\n";

		exit $nagiosStatus[1]; # INVALID/UNKNOWN
	}
}


