#!/usr/bin/perl

# rgrabner, 2008-03-03
# check sw raids major re-write: script extented to support two different modes:
# - report failures to syslog and send email if e.g. called from cron (method=syslog)
# - behave like a Nagios plugin if e.g. call from snmpd or directly (method=nagios)
#


use strict;
use Getopt::Long;
use Sys::Hostname;
use Sys::Syslog qw(:DEFAULT setlogsock);

# set default method
my $method = "syslog";

my $file = "/proc/mdstat";
my $device = "all";

my $hostname = hostname;
$hostname =~ s/\.amd\.com//;

my $site = lc `/tool/pandora/bin/sitename`;
chomp $site;

my %bad_devices;
my %good_devices;
my @messages;
my $retval = -1;
my $result;
my $resstring;

my (%active_devs, %failed_devs, %spare_devs);



sub usage()
{
	printf("
Check status of Linux SW RAID
Usage: mdstat-parser.pl [option]

  --method=[syslog|nagios]   Reporting method (default is syslog)
  
    syslog method: script will report to syslog and send email
    nagios method: script is meant to be run as Nagios plugin or via snmpd exec

");
  return 1;
}


sub send_mail {
    my $badraiddevs = shift;
    open(MAILER, "| /usr/sbin/sendmail mpd.$site.sys.mon\@mpdtxmail.amd.com");
    print MAILER "Subject: RAID PROBLEM on $hostname [$badraiddevs]\n";
    print MAILER "\n\n";
    print MAILER "You might want to check /proc/mdstat for $badraiddevs on $hostname.\n";
    print MAILER "\nThis concerns me:\n\n";
    print MAILER join("\n", @_);
    print MAILER "\n";
    close MAILER;
}

sub sys_log {
    my $badraiddevs = shift;
    setlogsock("unix");
    openlog("check_sw_raid", "cons", "kern");
    syslog("warning", "SOFTWARE RAID PROBLEM [$badraiddevs].  Check mpd.$site.sys.mon mailing list for details.");
    closelog();
}




# Get command line options
GetOptions ('method=s' => \$method,
	    'help' => sub { &usage() } );

if (( $method ne "syslog" ) and ( $method ne "nagios" )) {
  $retval = usage();
  exit($retval);
}



open FILE, "< $file" or die "Can't open $file : $!";
while (<FILE>) {
   chomp;
   next if ! /^(md\d+)+\s*:/;
   next if $device ne "all" and $device ne $1;
   $retval=0;
   my $line1=$_;
   my $raiddev = $1;
   my @array = split(/ /);
   # check if we can find which device has failed (if any)
   for $_ (@array) {
      next if ! /(\w+)\[\d+\](\(.\))*/;
      if ($2 eq "(F)") {
         $failed_devs{$raiddev} .= "$1,";
      }
      elsif ($2 eq "(S)") {
         $spare_devs{$raiddev} .= "$1,";
      }
      else {
         $active_devs{$raiddev} .= "$1,";
      }
   }
   #if (! defined($active_devs{$raiddev})) { $active_devs{$raiddev} = "none"; }
   #   else { $active_devs{$raiddev} =~ s/,$//; }
   #if (! defined($spare_devs{$raiddev}))  { $spare_devs{$raiddev}  = "none"; }
   #   else { $spare_devs{$raiddev} =~ s/,$//; }
   if (! defined($failed_devs{$raiddev})) { $failed_devs{$raiddev} = "none"; }
      else { $failed_devs{$raiddev} =~ s/,$//; }

   $_ = <FILE>;
   # Underscores mean a disk is missing from the array (probably failed).
   if ($_=~/_/) {
      $bad_devices{$raiddev}++;
      push(@messages, $line1);
      push(@messages, $_);
      if ( ! ($failed_devs{$raiddev} = "none")) {
         push(@messages, "Failed device seems to be: $failed_devs{$raiddev}");
      }
      $retval=2;
   } else {
       $good_devices{$raiddev}++;
   }
}
close FILE;

my $badraiddevs = join(", ", (sort keys %bad_devices));
my $goodraiddevs = join(", ", (sort keys %good_devices));

if ((scalar @messages > 0) and ($method eq "syslog")) {
   if (scalar keys %bad_devices > 0) {
      send_mail($badraiddevs, @messages);
      #sys_log($badraiddevs);
      print("Sent mail because RAID error for $badraiddevs.\n");
      print("\n");
      print join("\n", @messages);
      print("\n");
      $retval=0;
   }
} elsif ($method eq "nagios") {
   if (scalar keys %bad_devices > 0) {
      $resstring = "degraded raid-devices: $badraiddevs";
   }
   if (scalar keys %good_devices > 0) {
      if ($resstring ne "") {$resstring=$resstring . "; ";}
      $resstring = $resstring . "good raid-devices: $goodraiddevs";
   }

   if ($retval == 0) { $result = "OK"; }
      elsif ($retval == 1) { $result = "WARNING"; }
      elsif ($retval == 2) { $result = "CRITICAL"; }
      elsif ($retval == 4) { $result = "DEPENDENT"; }
      else { $result = "UNKNOWN"; $resstring = "no md devices available?!" }
      print "$result - $resstring\n";
} else {
   # return silently if no raid devices were found and method=syslog
   $retval=0;
}

exit($retval);








