#!/usr/bin/perl -w

###
# check_afacli
#
# This script runs the afacli utility to get status of a supported 
# Adaptec RAID controller (such as the Dell PERC3Di) and parse the 
# output for any potential error or warning states, which it then 
# passes on in a format that works with automated monitoring via 
# Nagios.
#
# The following items need to be customized based on your local 
# installation:
#    use lib "/usr/lib/nagios/plugins"; needs to be set to the 
#       path where Nagios' utils.pm can be found
#    $SUDO is the path to the sudo binary
#    $AFACLI is the full path to your afacli utility
#    $AFASCRIPT is the path to a textfile cotaining the set of 
#       commands to drive afacli
#    $AFALOG is the path to the logfile output generated by afacli 
#       which should be set in the above script with the 'logfile 
#       start <filename>' command
#
# Copyright 2004 Jonathan Delgado
#
# 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.
#
# GPL Licence : http://www.gnu.org/licenses/gpl.txt
###

use strict;

use lib "/usr/lib/nagios/plugins";
use utils qw(%ERRORS);

my $SUDO = '/usr/bin/sudo';
my $AFACLI = '/sbin/afacli';
my $AFASCRIPT = '/etc/nagios/afascript';
my $AFALOG = '/tmp/afacli.log';

# Delete any pre-existing logs
#( -e $AFALOG ) && unlink $AFALOG;

# Run afacli with the input script
system("TERM=dumb $SUDO $AFACLI < $AFASCRIPT > /dev/null");

#Be sure we have some output and error if we don't
unless ( -e $AFALOG ) 
{
	print STDOUT "UNKNOWN: Could not find output from afacli at $AFACLI\n";
	exit $ERRORS{'UNKNOWN'};
}

my $STATUS = 'OK';
my $COMMANDSTART = 0;
my $command = '';
my $results = '';
# Variables for container list
my ($container, $contype, $consize, $SCSIbidl, $partstate, $constate);

open(LOGFILE, "<$AFALOG");

while ( <LOGFILE> ) 
{
	if ( m/^AFA0/ ) 
	{
		$COMMANDSTART = 1;
		next;
	}
	if ( $COMMANDSTART ) 
	{
		m/^COMMAND:\s+(.+)$/;
		$command = $1;
		$COMMANDSTART = 0;
		next;
	}
	
	# Look for various things depending on what the current command is
	
	if ( $command =~ m/controller\s+details/ ) 
	{
	
		if ( m/\s+Battery State: (\w+)/ ) 
		{
			$results .= "Battery:$1 ";
			if ( $1 =~ m/Ok/i ) {
				# Do nothing
			} 
			elsif ( ( $1 =~ m/Reconditioning/i ) || ( $1 =~ m/Low/i ) || ( $1 =~ m/Charging/i ))
			{
				unless ( $STATUS eq 'CRITICAL' ) 
				{
					$STATUS = 'WARNING';
				}
			} 
			else 
			{
				$STATUS = 'CRITICAL';
			}
		}
	} 
	elsif ( $command =~ m/container\s+list/ ) 
	{

		# Grab listed containers
		if ( m/^\s*(\d+)\s+(Mirror|Stripe|Volume|RAID-5)\s+(\d+\.?\d*(KB|MB|GB)).+(\d:\d\d:\d)\s+((\d+\.?\d*(KB|MB|GB))\s*(!|:)\s*(\d+\.?\d*(KB|MB|GB)))/i ) 
		{
			$constate = 'OK';
			($container, $contype, $consize, $SCSIbidl, $partstate)  = ($1, $2, $3, $5, $9);
			$results .= "$container:$contype:$consize:";
			if ( $partstate eq '!' ) 
			{
				# There is a dead partition, bad news
				$constate = 'BAD';
			}
		} 
		elsif ( m/^.+(\d:\d\d:\d)\s+(\S+(!|:)\S+)/ ) 
		{
			($SCSIbidl, $partstate) = ($1, $3);
			if ( $partstate eq '!' ) 
			{
				# There is a dead partition, bad news
				$constate = 'BAD';
			}
		} 
		elsif ( m/Missing/i ) 
		{
			$constate = 'BAD';
		}
		elsif ( m/^\s*$/ ) 
		{
			# Got to end of current container
			unless ($container eq '-') 
			{
				$results .= "$constate ";
				$container = '-';
				if ( $constate eq 'BAD' ) 
				{
					$STATUS = 'CRITICAL';
				}
			}
		} 
	} 
	elsif ( $command =~ m/^close/ ) 
	{
		# This is really it for the log file, no point reading further
		last;
	}
	
	# We don't really do anything else
}

close LOGFILE;

print STDOUT "$STATUS: $results\n";
exit $ERRORS{$STATUS};
