#!/usr/bin/perl -w
# ---------------------------------------------------- #
# File : check_mylexraid
# Author : Damien SIAUD
# Date : 19/02/2008
# ---------------------------------------------------- #
# This script require Net::SNMP
#
# License Information:
# 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 3 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, see <http://www.gnu.org/licenses/>. 
#
# ---------------------------------------------------- # 
# This plugin check the status of Mylex/LSI 1030 controllers series
# The LSI snmp agent must be installed on the monitored server.
# Retreive it on http://www.lsi.com/support/storage/index.html
#
# ----------------------------------------------------- #



use lib "/usr/local/nagios/libexec";
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use vars qw($script_name $script_version);
use Getopt::Long;
use vars qw($o_host $o_community $o_port $o_help $o_version $o_timeout $o_debug $session $return_str);
use Net::SNMP qw(oid_lex_sort);
use vars qw($oid_prefix $controler_opstate $physdev_opstate $logicaldev_opstate %controlerstate %physicalstate %logicalstate %objects);

use strict;

# --------------------------- globals -------------------------- #

$script_name = "check_mylexraid";
$script_version = "0.1";

$o_host = undef;
$o_community = undef;
$o_port = 161;
$o_help= undef;
$o_version= undef;
$o_timeout= undef;
$o_debug= undef;

$session = undef;
$return_str = "";

# ---------------------------- snmp ---------------------------- #

$oid_prefix= "1.3.6.1.4.1.1608";

$controler_opstate= $oid_prefix . ".1.1.1.2.1.2";		# Controler operational state
%controlerstate= (
	1 	=> ['Functional', 0],
	2 	=> ['Non-Functional', 2],
	128	=> ['NotPresent', 0]
);

$physdev_opstate= $oid_prefix . ".1.1.1.4.1.5";			# physical devices operational state
%physicalstate= (
	0	=> ['Dead',2],
	2	=> ['Reduilding',1],
	3	=> ['Online',0],
	4	=> ['InstallationAbord',1],
	5	=> ['Present',0],
	6 	=> ['NotPresent',0],
	16 	=> ['Hotspare',0],
	130	=> ['RebuiltCancelled', 1]
);

$logicaldev_opstate= $oid_prefix . ".1.1.1.3.1.3";		# Logical devices operational state
%logicalstate= (
	3 	=> ['Online',0],
	4	=> ['Critical', 2],
	128	=> ['NotPresent',0],
	255	=> ['Offline',0],
);

my $nbc= 0; # controler counter
my $nbl= 0; # logical drives counter
my $nbp= 0; # physical drives counter

%objects= (
	'controler'	=> [\$controler_opstate,\$nbc,\%controlerstate],
	'logicaldrive'	=> [\$logicaldev_opstate,\$nbl,\%logicalstate],
	'physicaldrive' => [\$physdev_opstate,\$nbp,\%physicalstate],
);

# ---------------------------- main ----------------------------- #

check_options();

$o_timeout= $TIMEOUT if(!$o_timeout);
alarm($o_timeout);


($session, $return_str) = Net::SNMP->session(
	-hostname	=> $o_host,
	-community	=> $o_community,
	-port		=> $o_port,
	-timeout	=> $o_timeout
);


if (!defined($session)) {
	print "ERROR opening session: $return_str\n";
	exit $ERRORS{'UNKNOWN'};
}

my $warning= 0;
my $critical= 0;
my $err_str= "";

# now we check controler, logical drives and disks
for my $obj (keys %objects) {
	do_check($obj);
}

my $status= "OK";
if($warning) {
	$status= "WARNING";
}
if($critical) {
	$status= "CRITICAL";
}

print "Mylex $status - $nbc controlers, $nbl logical disks, $nbp physical disks found. $err_str\n";

$session->close;

exit $ERRORS{"$status"};

# --------------------------- functions ------------------------- #

# Get the alarm signal (just in case snmp timout screws up)
$SIG{'ALRM'} = sub {
     print ("Time-out error\n");
     exit $ERRORS{"UNKNOWN"};
};

sub do_check {
	my ($obj)= @_;
	
	my $oid= ${$objects{$obj}->[0]};
	my %state= %{$objects{$obj}->[2]};
	
	print "We are checking $obj with oid : $oid\n" if($o_debug);
	my $h_sess= (Net::SNMP->VERSION < 4)?$session->get_table($oid):$session->get_table(-baseoid => $oid);

	foreach my $i (oid_lex_sort(keys(%{$h_sess}))) {

		my $stateid= $h_sess->{$i}; # operational state id
		my $statusid= $state{$stateid}->[1]; # 0: ok, 1: warning, 2: critical
		my $statestr= $state{$stateid}->[0]; # Dead, Critical, Online ...
		my $counter= ${$objects{$obj}->[1]};

		print "----> operational state is $statestr (nagios critical level = $statusid) \n" if($o_debug);
		if($statusid) {
			if($statusid > 1) {
				$critical++;
			}
			else {
				$warning++;
			}
			$err_str .= "$obj $counter is $statestr. ";
		}
		${$objects{$obj}->[1]}++;
	}
}


sub usage {
	print "Usage: $0 -H <host> -C <community> [-p <port>] [-t <timeout>] [-T] [-V] [-h]\n";
}


sub version {
	print "$script_name v$script_version\n";
}


sub help {
	version();
	usage();

	print <<HELP;
	-h, --help
   		print this help message
	-H, --hostname=HOST
		name or IP address of host to check
	-C, --community=COMMUNITY NAME
		community name for the host's SNMP agent (implies v1 protocol)
	-P, --port=PORT
		SNMP port (Default 161)
	-t, --timeout=INTEGER
		timeout for SNMP
	-v, --verbose
		Print some extra debugging information (not advised for normal operation)
	-V, --version
		version number
HELP
}


sub check_options {
	Getopt::Long::Configure("bundling");
	GetOptions(
		'h'	=> \$o_help,		'help'		=> \$o_help,
		'H:s'	=> \$o_host,		'hostname:s'	=> \$o_host,
		'P:i'	=> \$o_port,		'port:i'	=> \$o_port,
		'C:s'	=> \$o_community,	'community:s'	=> \$o_community,
		't:i'	=> \$o_timeout,		'timeout:i'	=> \$o_timeout,
		'd'	=> \$o_debug,		'debug'		=> \$o_debug,
		'V'	=> \$o_version,		'version'	=> \$o_version
	);

	if(defined($o_help)) {
		help(); 
		exit $ERRORS{'UNKNOWN'};
	}

	if(defined($o_version)) {
		version();
		exit $ERRORS{'UNKNOWN'};
	}

	if(!defined($o_host) || !defined($o_community)) {
		usage();
		exit $ERRORS{'UNKNOWN'};
	}
}

