#! /usr/bin/perl -w ##################################################################### # What's this ? ##################################################################### # Checks the health of RAID disks # Requires aacraid driver and afacli program # More infos on http://public.www.planetmirror.com/pub/pub/domsch/ # Script designed for Nagios/NRPE # # Usage : # You can set warning level and cirtical level with -w and -c # This level corresponds to the number of disks in failure # Option -h displays a small usage message # # Copyright (C) 2004 Clement OUDOT # # 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 # # More contributions on http://www.linagora.org ##################################################################### # Modules ##################################################################### use strict ; use Getopt::Std ; ##################################################################### # Configuration ##################################################################### # Path to afacli program my $afacli = "/usr/sbin/afacli" ; # Name of Array Device my $array_name = "afa0" ; my $array_device = "/dev/".$array_name ; # Name of Instructions file for afacli my $infile = "/tmp/afacli.in" ; # Name of Log file of afacli my $outfile = "/tmp/afacli.out" ; # Nagios codes my %code = ( 'Ok' => 0, 'Warning' => 1, 'Critical' => 2, 'Unknown' => 3) ; # Set TERM env (required by afacli program) $ENV{TERM} = "xterm" ; ##################################################################### # Command line parameters ##################################################################### # Init Options Hash Table my %opts ; getopt('wch',\%opts) ; &usage if exists $opts{"h"} ; $opts{"w"} = 1 unless (exists($opts{"w"})) ; $opts{"c"} = 1 unless (exists($opts{"c"})) ; my $warning_level = $opts{"w"} ; my $critical_level = $opts{"c"} ; ##################################################################### # Usage function ##################################################################### sub usage { print "Usage : $0 -w -c \n" ; exit $code{'Unknown'} ; } ##################################################################### # Tests ##################################################################### # Is afacli executable ? unless (-x $afacli) { print "Can't execute $afacli\n" ; exit $code{'Unknown'} ; } # Does Array Device exists ? unless (-e $array_device ) { print "SCSI Device $array_name Unknown\n" ; exit $code{'Unknown'} ; } # Do we have enough rights to read/write the device ? # Note : Although we just need to read the device, afacli requires # read/write rights on the device unless ( (-r $array_device ) && (-w $array_device ) ) { print "Not enough rights on device $array_name\n" ; exit $code{'Unknown'} ; } ##################################################################### # Creation of Instructions File ##################################################################### # Opening of infile my $infile_test = open (INFILE, ">$infile") ; unless ($infile_test) { print "Can't open $infile for writing\n"; exit $code{'Unknown'} ; } # Adding instructions print INFILE "logfile start \"$outfile\"\n" ; print INFILE "open /readonly=TRUE $array_name\n" ; print INFILE "disk list\n" ; print INFILE "disk show space\n" ; print INFILE "close\n" ; print INFILE "logfile end\n" ; print INFILE "exit\n" ; # Close the infile close INFILE ; ##################################################################### # Execution of afacli ##################################################################### `$afacli < $infile` ; ##################################################################### # Log File Analyse ##################################################################### # Opening of outfile my $outfile_test = open (OUTFILE, "$outfile") ; unless ($outfile_test) { print "Can't open $outfile for reading\n" ; exit $code{'Unknown'}; } # Init hash table my %disks ; # Set flags my ( $flag_disk_list , $flag_disk_show_space ) = ( 0 , 0 ) ; # Parsing outfile while () { $flag_disk_list = 1 if (/COMMAND: disk list/) ; $flag_disk_show_space = 1 if (/COMMAND: disk show space/) ; if ( $flag_disk_show_space ) { # Result of disk show space command if (/\d:\d\d:\d/) { # This line is a disk line ! my @line = split ; my ($disk_nb) = ( $line[0] =~ /\d:(\d\d):\d/ ) ; my $disk_status = $line[1] ; # Add this disk to the hash table push @{$disks{$disk_nb}} , $disk_status ; } } elsif ( $flag_disk_list ) { # Result of disk list command if (/^\d:\d\d:\d\s*Disk/) { # This line is a disk line ! my @line = split ; my ($disk_nb) = ( $line[0] =~ /\d:(\d\d):\d/ ) ; my $disk_status = $line[4] ; # Add this disk to the hash table push @{$disks{$disk_nb}} , $disk_status ; } } } # Close the outfile close OUTFILE ; ##################################################################### # File deletion ##################################################################### unlink $infile, $outfile ; ##################################################################### # Exit with Nagios Code ##################################################################### # Find disks in error and print a message # # [disk_nb: Ok] my $nb_disks_error = 0 ; my %status ; foreach my $nb (sort keys %disks) { my $reftable = $disks{$nb} ; $status{$nb} = 0 ; foreach (@$reftable) { # Good Status are : Initialized, Free, Container $status{$nb}++ unless (/Initialized|Free|Container/i) ; } if ( $status{$nb} ) { $nb_disks_error++ ; print "<$nb: " ; foreach (@$reftable) { print "$_ " unless (/Initialized|Free|Container/i) ; } print "> "; } else { print "[$nb: Ok] " ; } } print "\n" ; exit $code{'Critical'} if ($nb_disks_error >= $critical_level) ; exit $code{'Warning'} if ($nb_disks_error >= $warning_level) ; exit $code{'Ok'} ;