#!/usr/bin/perl -w
#
# Nagios plugin to check SUN STK RAID status.
# Copy to Nagios libexec directory (requires utils.pm from Nagios plugins).
#
# $Id: check_arcconf.pl,v 1.00 2010/06/09 kaunt Exp $
#
# Copyright (C) 2008-2010  Thomas Kaun / Telefonica o2 Germany GmbH & Co OHG
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#

##################################################################################
### loading modules
##################################################################################

use strict;
use lib "/usr/local/nagios/libexec";
use utils qw(%ERRORS);

##################################################################################
### declarations
##################################################################################

my @obj; my @ac; my @parm; my @idx; my @ldlist; my @pdlist; my @tmp;
my %raid;
my $instance; my $status;
my $verbose = "no";
my $a = 0; my $warning = 0; my $critical = 0;
my $cid = 1; my $batc = 30; my $batw = 80; 

my $command = "/usr/local/bin/sudo /opt/StorMan/arcconf getconfig $cid al";
my $arg = ''; my $stat = ""; my $perf = "";

$obj[0] = 'Controller';

##################################################################################
### parsing arguments
##################################################################################

foreach $arg (@ARGV) {
  if ($arg eq "-i") {
    $cid = $ARGV[$a+1];
  }
  if ($arg eq "-w") {
    $batw = $ARGV[$a+1];
  }
  if ($arg eq "-c") {
    $batc = $ARGV[$a+1];
  }
  if ($arg eq "-h") {
    print "\nusage: ./check_arcconf.pl -i <controller id> [-c <capacity remaining critical>] [-w <capacity remaining warning>]\n";
    print "\nOptions: -i <controller id>\n";
    print "         -c critical level battery capacity (def. 30)\n";
    print "         -w warning level battery capacity (def. 80)\n";
    print "         -h print this help\n";
    print "\n";
    exit $ERRORS{'UNKNOWN'};
  }
  $a++;
}

$instance = $cid;

##################################################################################
### collect data and store it in a hash
##################################################################################

open (ARCCONF, "$command |");
@ac = <ARCCONF>;
close ARCCONF;

foreach $_ (@ac) {
  chomp;
  if ($_ =~ /^\S.* information/) {
    @obj = split(/ /, $_);
    next;
  }
  if ($_ =~ /Logical device name/) {
    s/ //g;
    @parm = split(/:/, $_);
    $instance = $parm[1];
    push (@ldlist, $instance);
    next;
  }
  if ($_ =~ /Device #/) {
    @parm = split(/#/, $_);
    $instance = $parm[1];
    push (@pdlist, $instance);
    next;
  }
  if ($_ =~ /: /) {
    s/ {2,100}//g;
    s/: /:/;
    s/ /_/g;
    @parm = split(/:/, $_);
    $raid{"$obj[0].$instance.$parm[0]"} = $parm[1]; 
  }
}

##################################################################################
### check arcconf output
##################################################################################

# controller check

if (!($raid{"Controller.".$cid.".Controller_Status"} =~ /Optimal/)) {
  $warning++;
  $stat = ($stat."Controller ".$raid{"Controller.".$cid.".Controller_Status"}.", ");
}
if (!($raid{"Controller.".$cid.".Temperature"} =~ /Normal/)) {
  $warning++;
  $stat = ($stat."Controller ".$raid{"Controller.".$cid.".Temperature"}.", ");
}
if (!($raid{"Controller.".$cid.".Defunct_disk_drive_count"} == 0)) {
  $critical++;
  $stat = ($stat."Controller disks failed: ".$raid{"Controller.".$cid.".Defunct_disk_drive_count"}.", ");
}
if (!($raid{"Controller.".$cid.".Logical_devices/Failed/Degraded"} =~ /\/0\/0/)) {
  $warning++;
  $stat = ($stat."Controller devices/Failed/Degraded ".$raid{"Controller.".$cid.".Logical_devices/Failed/Degraded"}.", ");
}
if (!($raid{"Controller.".$cid.".Status"} =~ /Optimal/)) {
  $warning++;
  $stat = ($stat."Controller Battery ".$raid{"Controller.".$cid.".Status"}.", ");
}
if (!($raid{"Controller.".$cid.".Over_temperature"} =~ /No/)) {
  $critical++;
  $stat = ($stat."Controller Battery over temperature, ");
}
@tmp = split(/_/, $raid{"Controller.".$cid.".Capacity_remaining"});
if ($tmp[0] <= $batc) {
  $critical++;
  $stat = ($stat."Controller Battery ".$raid{"Controller.".$cid.".Capacity_remaining"}.", ");
 }
elsif ($tmp[0] <= $batw) {
  $warning++;
  $stat = ($stat."Controller Battery ".$raid{"Controller.".$cid.".Capacity_remaining"}.", ");
}

# logical devices check

foreach $instance (@ldlist) {
  if (!($raid{"Logical.".$instance.".Status_of_logical_device"} =~ /Optimal/)) {
    $critical++;
    $stat = ($stat."Logical device \"$instance\" ".$raid{"Logical.".$instance.".Status_of_logical_device"}.", ");
  }
  if (!($raid{"Logical.".$instance.".Failed_stripes"} =~ /No/)) {
    $warning++;
    $stat = ($stat."Logical device \"$instance\" stripes failed, ");
  }
}

# physical devices check

foreach $instance (@pdlist) {
  if ($raid{"Physical.".$instance.".State"}) {
    if (!($raid{"Physical.".$instance.".State"}) =~ /Online/) {
      $warning++;
      $stat = ($stat."Physical device \"$instance\" ".$raid{"Physical.".$instance.".State"}.": ".$raid{"Physical.".$instance.".Reported_Location"}.": ".$raid{"Physical.".$instance.".Model"}.": ".$raid{"Physical.".$instance.".Size"}.", ");
    }
    if (!($raid{"Physical.".$instance.".Supported"}) =~ /Yes/) {
      $warning++;
      $stat = ($stat."Physical device \"$instance\" ".$raid{"Physical.".$instance.".Reported_Location"}.": ".$raid{"Physical.".$instance.".Model"}.": ".$raid{"Physical.".$instance.".Size"}." not supported, ");
    }
  }
  elsif (!($raid{"Physical.".$instance.".Temperature"} =~ /Normal/)) {
    $warning++;
    $stat = ($stat."Physical device \"$instance\" ".$raid{"Physical.".$instance.".Model"}.": ".$raid{"Physical.".$instance.".Enclosure_ID"}." Temperature: ".$raid{"Physical.".$instance.".Temperature"}.", ");
  }
}

##################################################################################
### generating return code and messages
##################################################################################

if ($critical > 0) {
	print "$critical CRITICAL's, $warning WARNING's ! $stat|$perf\n";
	exit $ERRORS{'CRITICAL'};
}
elsif ($warning > 0) {
	print "$warning WARNING's ! $stat|$perf\n";
	exit $ERRORS{'WARNING'};
}
print "Sun StorageTek Raid o.k.|$perf\n";
exit $ERRORS{'OK'};
