#! /usr/bin/perl -w

#
#	Ce check Nagios permet de vérifier le status du RAID d'un serveur utilisant une carte PERC.
#
#	Arguments: check_clara_raid_status_PERC ip_addr_of_raid_machine disk_id,disk_id,disk_id,[disk_id,...]
#
#	Les disques ID sont de la forme : x.yy avec x = channel et yy = id du disk sur le channel
#
#	Yann GROSSEL 2005.07.15
#

# STATE_OK=0
# STATE_WARNING=1
# STATE_CRITICAL=2
# STATE_UNKNOWN=3
# STATE_DEPENDENT=4

use strict;

use SNMP;
use Data::Dumper;

# Configuration

my $key		= 'password';
my $oid		= '.1.3.6.1.4.1.5000.10.101.1';

# Variables

my $r;

#

sub usage()
{
	print "Usage: $0 ip_addr_of_raid_machine disk_id,disk_id,disk_id,[disk_id,...]\n";
	exit(3);
}

# Debut

&usage if $#ARGV != 1;

my $server = shift;

# Polling du serveur RAID.

SNMP::initMib();

my $sess = new SNMP::Session(DestHost => $server, Community => $key, UseSprintValue => 1);

if (not defined($sess)) { print "Impossible d'ouvrir une session SNMP avec $server !\n"; exit(3); }

$r = $sess->get($oid);

if (not defined($r) or $r eq 'NULL' ) { print "Erreur lors du poll SNMP de $server !\n"; exit(3); }

$r =~ s/^"\s*//;
$r =~ s/\s*"\s*$//;

unless ($r =~ m/^(\S+)\s+(.*)$/)
{
	print "$r" if -t 1;
	print "Reponse SNMP de $server : format inattendu !\n";
	exit 3;
}

my $r_status = $1;	# Status global du raid
my $d_status = $2;	# Status de chaque disk

if ($r_status ne 'OPTIMAL')
{
	print "Raid status = '$r_status'\n";

	if ($r_status =~ m/^(REBLD|REBUILD|REBUILDING)$/i) { exit 1; }	# Warning
	else { exit 2;	} # Critical
}

# Le status global est OPTIMAL, on checke les disks.

my @ds = split(m/\s+/, $d_status);
my %disks;

foreach my $d (@ds)
{
	unless ($d =~ m/^(\d+)\.(\d+)=(\S+)$/)
	{
		print "Reponse SNMP de $server : format inattendu !\n";
		exit 3;
	}

	$disks{"$1.$2"} = $3;
}

# On checke.

my $ids = shift;

my $final = 0;

foreach my $d (split m/,/, $ids)
{
	my $hot_spare = 0;

	if ($d =~ m/^H/)
	{
		# Hot spare
		$d = substr($d, 1);
		$hot_spare = 1;
	}

	if (not defined($disks{$d}))
	{
		print "Disk '$d' unknown on server\n";
		exit 3;	# Unknown
	}

	if ($disks{$d} eq 'ONLINE')
	{
		if ($hot_spare)
		{
			print "Hotspare Disk '$d' is 'ONLINE' !\n";
			$final = 1;	# Warning
			delete $disks{$d};
			next;
		}
		else
		{
			# Le disque fonctionne correctement.
			delete $disks{$d};
			next;
		}
	}

	if ($disks{$d} eq 'HOTSPARE')
	{
		if ($hot_spare)
		{
			# Le disque est un HOTSPARE, c'est normal.
			delete $disks{$d};
			next;
		}
		else
		{
			# Un disque est devenu hotspare ?!
			print "Disk '$d' is unexpectedly 'HOTSPARE' ?\n";
			$final = 3;	# Unknown
			delete $disks{$d};
			next;
		}
	}

	print "Disk '$d' is '" . $disks{$d} . "'\n";

	if ($disks{$d} =~ m/^(REBLD|REBUILD|REBUILDING)$/i) { exit 1; }	# Warning
	else { exit 2;	} # Critical
}

if ($final != 0) { exit $final; }

if (scalar(keys %disks) > 0)
{
	# Le serveur indique des disks qu'on attendait pas.
	my $u = join(' ', keys %disks);
	print "Server gives unexpected disks: $u\n";
	exit 3;	# Unknown
}

# Ok.

print "raid status is $r_status\n";

exit 0;

