#!/usr/bin/perl -T
#############################################################################
#                                                                           #
# This script was initially developed by Anstat Pty Ltd for internal use    #
# and has kindly been made available to the Open Source community for       #
# redistribution and further development under the terms of the             #
# GNU General Public License: http://www.gnu.org/licenses/gpl.html          #
#                                                                           #
#############################################################################
#                                                                           #
# This script is supplied 'as-is', in the hope that it will be useful, but  #
# neither Anstat Pty Ltd nor the authors make any warranties or guarantees  #
# as to its correct operation, including its intended function.             #
#                                                                           #
# Or in other words:                                                        #
#       Test it yourself, and make sure it works for YOU.                   #
#                                                                           #
#############################################################################
# Author: George Hansper               e-mail:  Name.Surname@anstat.com.au  #
#############################################################################

$ENV{PATH}="/sbin:/usr/sbin:/bin:/usr/bin";

use strict vars;

my $rcsid = '$Id: check_dell_aacraid.pl,v 1.1 2005/12/19 22:48:43 georgeh Exp georgeh $';
my $rcslog = '
  $Log: check_dell_aacraid.pl,v $
  Revision 1.1  2005/12/19 22:48:43  georgeh
  Initial revision

';

if ( @ARGV > 0 ) {
	if( $ARGV[0] eq "-V" ) {
		print STDERR "$rcsid\n";
	} else {
		print STDERR "Nagios plugin for checking the status of a Dell RAID array using 'afacli'\n";
		print STDERR "Requires Dell Open Manage (Array Manager) to be installed.\n";
		print STDERR "The afacli command must be run as the 'root' user, so this script\n";
		print STDERR "must also be run as the 'root' user\n";
		print STDERR "\n";
		print STDERR "Usage:\n";
		print STDERR "\t$0 [-V]\n";
		print STDERR "\t\t-V ... print version information\n";
		print STDERR "\n";
		print STDERR "NRPE usage:\n";
		print STDERR "\tcommand[check_dell_aacraid]=/usr/bin/sudo /usr/lib/nagios/plugins/check_dell_aacraid.pl\n";
		print STDERR "\n";
		print STDERR "NRPE usage requires /etc/sudoers to contain:\n";
		print STDERR "\tnagios  ALL=NOPASSWD: /usr/lib/nagios/plugins/check_dell_aacraid.pl\n";
		print STDERR "\n";
		
	}
}

my (@tag,@value,%value);
my ($status,$disk,$rebuild_percent,$is_hotspare,$disk_empty,$disk_online,$disk_faulty,$disk_unconf);
my ($array,%array_resyncing,%array_failed,%failed);
my ($i,$ok,$failed,$resyncing,$exit);
my ($detail,@details);
my ($slot,%slot);
my ($battery_state);

open(AFACLI,"afacli open /readonly afa0 : enclosure show slot : task list : controller details : close|")
	|| do { print "afacli: " . $! ."\n"; exit 2};

$ok="OK";
# Skip everything up to the header line
while ( <AFACLI> ) {
	if( $_ =~ /Enclosure/ ) {
		last;
	}
}

$failed=0;
$resyncing=0;
while ( <AFACLI> ) {
	s/^\s+//;
	chomp;
	if ( /^[- ]+$/ ) {
		next;
	} elsif ( /Slot/ ) {
		@tag = (split/\s+/, "$_" );
		#print "1=$tag[1], 2=$tag[2]\n";
		next;
	} elsif ( /^\s*$/ ) {
		last;
	} else {
		@value = (split/\s+/, "$_", @tag );
	}
	for ( $i=0 ; $i < @tag ; $i++ ) {
		$value{$tag[$i]} = $value[$i];
	}
	$array = $value{ID};
	$disk  = $value{Slot};
	#printf STDERR "Array=%s, Disk=%s\n",$array,$disk;
	# Status info:
	# Disk OK and Array OK:
	#	OK ACTIVATE
	# (may be running on hotspare - slot marked "OK HOTSPARE ACTIVATE")
	# Disk OK and Rebuilding
	#	OK REBUILD FAILED CRITICAL ACTIVATE
	# Disk Failed (unplugged)
	#	OK FAILED CRITICAL UNCONFIG EMPTY I/R READY NOTACTIVATE
	#	OK EMPTY I/R READY NOTACTIVATE
	# Hotspare ready but not in use
	#	OK UNCONFIG HOTSPARE ACTIVATE
	# Hotspare Disk rebuilding
	#	OK REBUILD FAILED CRITICAL HOTSPARE ACTIVATE
	# Hotspare Disk online (ie after a failure)
	#	OK HOTSPARE ACTIVATE
	# 
	# Disk failed and no hotspare available - other disks in the array show...
	#	OK FAILED CRITICAL ACTIVATE
	#	OK FAILED CRITICAL HOTSPARE ACTIVATE
	# $slot{"Slot$value{Slot}"} = $value{Status};
	#
	# From the Dell documentation:
	# Status  	 Meaning
	# -------	---------
	# OK 		The device that resides in this slot is operational. In the example, the device that resides in device slot 0 on enclosure management device 0 is operational.
	# ERROR 	The device that resides in this slot has error conditions.
	# FAULTY 	The device that resides in this slot has some hardware or data fault.
	# REBUILD 	The device that resides in this slot is being rebuilt.
	# FAILED 	The device that resides in this slot is in a device array. One member of this device array has an error.
	# CRITICAL 	The device that resides in this slot is in a device array that was previously fault-tolerant and is now non-fault-tolerant.
	# SCRUB 	The device that resides in this slot is in a device array that is undergoing a parity check operation.
	# WARNING 	The device that resides in this slot is likely to fail in the near future.
	# UNCONFIG 	The device that resides in this slot is not currently configured as a member of a device array or as a hot spare.
	# HOTSPARE 	The device that resides in this slot is configured as a hot spare.
	# REBUILDSTOP 	The device that resides in this slot was rebuilding, but the rebuild operation terminated abnormally or unsuccessfully.
	# EMPTY 	No physical device resides in this slot.
	# I/R READY 	The slot is ready for the physical insertion or removal of a device.
	# NOTACTIVATE 	The slot is not activated. The device that resides in the slot cannot be accessed on the SCSI bus.
	# ACTIVATE 	The slot is activated. The device that resides in the slot can be accessed on the SCSI bus.


	@details = (split /\s+/, "$value{Status}");
	$status = "undef";
	$is_hotspare = "";
	$disk_empty = 0;
	$disk_online = 0;
	$disk_faulty = 0;
	$disk_unconf = 0;
	foreach $detail ( @details ) {
		if( $detail =~ /^NOTACTIVATE$/i ) {
			$disk_online = 0;
		} elsif($detail =~ /^ACTIVATE$/i ) {
			$disk_online = 1;
		} elsif($detail =~ /^FAULTY$/i ) {
			$disk_faulty = 1;
			$failed=1;
		} elsif($detail =~ /^REBUILD$/i ) {
			$array_resyncing{$array} = "Array$array";
			$resyncing=1;
		} elsif($detail =~ /^FAILED$/i ) {
			$array_failed{$array} = "Array$array";
			$failed=1;
		} elsif($detail =~ /^CRITICAL$/i ) {
			$array_failed{$array} = "Array$array";
			$failed=1;
		} elsif($detail =~ /^UNCONFIG$/i ) {
			$disk_unconf = 1;
		} elsif($detail =~ /^HOTSPARE$/i ) {
			$is_hotspare = "(hotspare)";
		} elsif($detail =~ /^EMPTY$/i ) {
			$disk_empty = 1;
		}
	}
	if ( $disk_faulty ) {
		$status = "Failed";
		$failed{"Slot$array$disk"} = "Offline";
	} elsif ( $disk_empty ) {
		$status = "Empty";
	} elsif ( $disk_unconf && $is_hotspare ne "" ) {
		$status = "Hotspare";
		$is_hotspare = "";
	} elsif ( $disk_unconf  ) {
		$status = "Unconf";
	} elsif ( $disk_online == 0 ) {
		$status = "Failed";
		$failed{"Slot$array$disk"} = "Offline";
	} elsif ( $disk_online == 1 && $array_resyncing{$array} ne "" ) {
		$status = "Resync";
	} elsif ( $disk_online == 1 ) {
		$status = "OK";
	}
	$slot{"Slot$array$disk"} = $status . $is_hotspare;
}
while ( <AFACLI> ) {
	if ( /Rebuild/i ) {
		split;
		$rebuild_percent=$_[2];
	}
	if ( /Battery *State/i ) {
		chomp;
		split /: */;
		$battery_state=$_[1];
	}
}

close(AFACLI);

if ( $failed != 0 && $resyncing == 0 ) {
	print "FAILED: ";
	print join ", ", (sort (values %array_failed ));
	print " " . join ", ", (sort (keys %failed ));
	print " -";
	$exit = 2;
} elsif ( $resyncing != 0 ) {
	print "RESYNC: ";
	print join ", ", (sort (values %array_resyncing ));
	print " $rebuild_percent";
	print " -";
	$exit = 1;
} elsif ( $battery_state !~ /^OK/i ) {
	print "BATTERY: $battery_state -";
	$exit = 1;
} else {
	print "OK -";
	$exit = 0;
}

# Sort the list in alphabetical mountpoint order...
#foreach $slot ( sort { $slot{$a} cmp $slot{$b};} (keys %slot) ) {
foreach $slot ( sort (keys %slot) ) {
	print " $slot=$slot{$slot};";
}
 
print " Battery=$battery_state;";
print "\n";
exit $exit;
