#!/usr/bin/perl -w

# Project : Monitoring of Quantum Library with Nagios & Centreon
# Author : Romain Pichard
#
#
# This program can monitor Quantum Libraries PX506 
# and certainly PX502 and PX510.
# 
# The main aim is to check the UPTIME and the STATE of the library
# with SNMP. The other aim is to translate SNMP responses 
# (1, 2, 3,...) with words.
#
# URL of Quantum's MIB :
# http://www.quantum.com/ServiceandSupport/SoftwareandDocumentationDownloads/PX506/Index.aspx
# Download the SNMP Integration CD and search the file named : QUANTUM-SNMP.mib
#
#
# This program is inspired by Ken McKinlay's script 
# which named check_netapp.pl
#
# Parameter checks and SNMP v3 based on code by Christoph Kron 
# and S. Ghosh (check_ifstatus)
#
#
# 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 cheupi@gmail.com
#
# 2008.01.29 Version 1.0


use strict;
use lib "/usr/local/nagios/libexec";
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use Net::SNMP;
use Getopt::Long;
Getopt::Long::Configure('bundling');

my $PROGNAME = 'check_px5XX';
my $PROGREVISION = '1.0';

sub print_help ();
sub usage ();
sub process_arguments ();

my ($status,$timeout,$answer,$perfdata,$hostname);
my ($seclevel,$authproto,$secname,$authpass,$privpass,$snmp_version);
my ($auth,$priv,$session,$error,$response,$snmpoid,$variable);
my ($opt_h,$opt_V);
my %snmpresponse;

my $state = 'UNKNOWN';
my $community='public';
my $maxmsgsize = 1472; # Net::SNMP default is 1472
my $port = 161;

my $snmpUptime = '.1.3.6.1.2.1.1.3';
my $snmpState = '.1.3.6.1.4.1.2036.2.1.1.7';

my %StateLevel = (
	1 => 'Unavailable',
	2 => 'Available',
	3 => 'Online',
	4 => 'Offline',
	5 => 'Going online',
	6 => 'State not available',
);

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
	print "ERROR: No snmp response from $hostname (alarm timeout)\n";
	exit $ERRORS{'UNKNOWN'};
};

$status = process_arguments();
if ( $status != 0 ) {
	print_help();
	exit $ERRORS{'OK'};
}

alarm($timeout);

# Do the query
if ( ! defined ( $response = $session->get_table($snmpoid) ) ) {
	$answer=$session->error;
	$session->close;
	$state = 'CRITICAL';
	print "$state:$answer for $snmpoid with snmp version $snmp_version\n";
	exit $ERRORS{$state};
}
$session->close;
alarm(0);

foreach my $snmpkey (keys %{$response} ) {
	my ($oid,$key) = ( $snmpkey =~ /(.*)\.(\d+)$/ );
	$snmpresponse{$oid}{$key} = $response->{$snmpkey};
}

if ( $variable eq 'UPTIME' ) {
	$state = 'OK';
	$answer = sprintf("Uptime of Quantum Library: %s",$snmpresponse{$snmpUptime}{0});
	$perfdata = sprintf("uptime=%s",$snmpresponse{$snmpUptime}{0});
} elsif ( $variable eq 'STATE' ) {
	$state = 'OK';
	$state = 'WARNING' if ( ( $snmpresponse{$snmpState}{0} == 5 ) || ( $snmpresponse{$snmpState}{0} == 6 ) );
	$state = 'CRITICAL' if ( ( $snmpresponse{$snmpState}{0} == 1 ) || ( $snmpresponse{$snmpState}{0} == 4 ) );
	$answer = sprintf("State of Quantum Library: %s",$StateLevel{$snmpresponse{$snmpState}{0}});
	$perfdata = sprintf("statelevel=%d",$snmpresponse{$snmpState}{0});
} 

print "$answer|$perfdata\n";
exit $ERRORS{$state};

sub usage () {
	print "\nMissing arguments!\n\n";
	print "check_px5XX.pl -H <ip_address> -v <variable>\n";
	print "             [-C community] [-t timeout] [-p port-number]\n";
	print "             [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n";
	print "             [-A authpasswd] [-X privpasswd]\n\n";
	support();
	exit $ERRORS{'UNKNOWN'};
}

sub print_help () {
	print "check_px5XX.pl plugin for Nagios monitors the status\n";
	print "of a Quantum Library system\n\n";
	print "Usage:\n";
	print "  -H, --hostname\n\thostname to query (required)\n";
	print "  -C, --community\n\tSNMP read community (defaults to public)\n";
	print "  -t, --timeout\n\tseconds before the plugin tims out (default=$TIMEOUT)\n";
	print "  -p, --port\n\tSNMP port (default 161\n";
	print "  -P, --snmp_version\n\t1 for SNMP v1 (default), 2 for SNMP v2c\n\t\t3 for SNMP v3 (requires -U)\n";
	print "  -L, --seclevel\n\tchoice of \"noAuthNoPriv\", \"authNoPriv\", \"authpriv\"\n";
	print "  -U, --secname\n\tuser name for SNMPv3 context\n";
	print "  -a, --authproto\n\tauthentication protocol (MD5 or SHA1)\n";
	print "  -A, --authpass\n\tauthentication password\n";
	print "  -X, --privpass\n\tprivacy password in hex with 0x prefix generated by snmpkey\n";
	print "  -V, --version\n\tplugin version\n";
	print "  -v, --variable\n\tvariable to query, can be:\n";
	print "\t\tUPTIME - Uptime of Quantum Library\n";
	print "\t\tSTATE - State of Quantum Library\n";
	print "  -h, --help\n\tusage help\n\n";
	print_revision($PROGNAME,"\$Revision: 1.2 $PROGREVISION\$");
}

sub process_arguments () {
	$status = GetOptions (
		'V' => \$opt_V, 'version' => \$opt_V,
		'h' => \$opt_h, 'help' => \$opt_h,
		'P=i' => \$snmp_version, 'snmp_version=i' => \$snmp_version,
		'C=s' => \$community, 'community=s' => \$community,
		'L=s' => \$seclevel, 'seclevel=s' => \$seclevel,
		'a=s' => \$authproto, 'authproto=s' => \$authproto,
		'U=s' => \$secname, 'secname=s' => \$secname,
		'A=s' => \$authpass, 'authpass=s' => \$authpass,
		'X=s' => \$privpass, 'privpass=s' => \$privpass,
		'H=s' => \$hostname, 'hostname=s' => \$hostname,
		't=i' => \$timeout, 'timeout=i' => \$timeout,
		'v=s' => \$variable, 'variable=s' => \$variable,
	);

	if ( $status == 0 ) {
		print_help();
		exit $ERRORS{'OK'};
	}

	if ( $opt_V ) {
		print_revision($PROGNAME,"\$Revision: 1.2 $PROGREVISION\$");
		exit $ERRORS{'OK'};
	}

	if ( ! utils::is_hostname($hostname) ) {
		usage();
		exit $ERRORS{'UNKNOWN'};
	}

	unless ( defined $timeout ) {
		$timeout = $TIMEOUT;
	}

	if ( ! $snmp_version ) {
		$snmp_version = 1;
	}

	if ( $snmp_version =~ /3/ ) {
		if ( defined $seclevel && defined $secname ) {
			unless ( $seclevel eq ('noAuthNoPriv' || 'authNopriv' || 'authPriv' ) ) {
				usage();
				exit $ERRORS{'UNKNOWN'};
			}

			if ( $seclevel eq ('authNoPriv' || 'authPriv' ) ) {
				unless ( $authproto eq ('MD5' || 'SHA1') ) {
					usage();
					exit $ERRORS{'UNKNOWN'};
				}
				if ( ! defined $authpass ) {
					usage();
					exit $ERRORS{'UNKNOWN'};
				} else {
					if ( $authpass =~ /^0x/ ) {
						$auth = "-authkey => $authpass";
					} else {
						$auth = "-authpassword => $authpass";
					}
				}
			}

			if ( $seclevel eq 'authPriv' ) {
				if ( ! defined $privpass ) {
					usage();
					exit $ERRORS{'UNKNOWN'};
				} else {
					if ( $privpass -~ /^0x/ ) {
						$priv = "-privkey => $privpass";
					} else {
						$priv = "-privpassword => $privpass";
					}
				}
			}
		} else {
			usage();
			exit $ERRORS{'UNKNOWN'};
		}
	}

	# Create the SNMP session
	if ( $snmp_version =~ /[12]/ ) {
		($session,$error) = Net::SNMP->session(
					-hostname => $hostname,
					-community => $community,
					-port => $port,
					-version => $snmp_version,
		);
		if ( ! defined $session ) {
			$state = 'UNKNOWN';
			$answer = $error;
			print "$state:$answer";
			exit $ERRORS{$state};
		}
	} elsif ( $snmp_version  =~ /3/ ) {
		if ( $seclevel eq 'noAuthNoPriv' ) {
			($session,$error) = Net::SNMP->session(
						-hostname => $hostname,
						-community => $community,
						-port => $port,
						-version => $snmp_version,
						-username => $secname,
			);
		} elsif ( $seclevel eq 'authNoPriv' ) {
			($session,$error) = Net::SNMP->session(
						-hostname => $hostname,
						-community => $community,
						-port => $port,
						-version => $snmp_version,
						-username => $secname,
						-authprotocol => $authproto,
						$auth
			);
		} elsif ( $seclevel eq 'authPriv' ) {
			($session,$error) = Net::SNMP->session(
						-hostname => $hostname,
						-community => $community,
						-port => $port,
						-version => $snmp_version,
						-username => $secname,
						-authprotocol => $authproto,
						$auth,
						$priv
			);
		}
		if ( ! defined $session ) {
			$state = 'UNKNOWN';
			$answer = $error;
			print "$state:$answer";
			exit $ERRORS{$state};
		}
	} else {
		$state = 'UNKNOWN';
		print "$state: No support for SNMP v$snmp_version\n";
		exit $ERRORS{$state};
	}

	# Check the supported variables
	if ( ! defined $variable ) {
		print_help();
		exit $ERRORS{'UNKNOWN'};
	}  {
		if ( $variable eq 'UPTIME' ) {
			$snmpoid = $snmpUptime;
		} elsif ( $variable eq 'STATE' ) {
			$snmpoid = $snmpState;
		} else {
			print_help();
			exit $ERRORS{'UNKNOWN'};
		}
	}

	return $ERRORS{'OK'};
}

