#!/usr/bin/perl -w


# check_promise_chassis.pl   --  Nagios Plugin
#
# By Barry O'Donovan - http://www.barryodonovan.com/ - barry <at> opensolutions <dot> ie
#
# Designed specifically for the VTrak M200i but should be easily customisable to other
# models.
#
# Usage: ./check_promise_chassis.pl <community> <host>
#
# Copyright (c) 2007 Barry O'Donovan - http://www.barryodonovan.com/
# Copyright (c) 2007 Open Source Solutions Ltd - http://www.opensolutions.ie/
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of 
# this software and associated documentation files (the "Software"), to deal in 
# the Software without restriction, including without limitation the rights to 
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
# of the Software, and to permit persons to whom the Software is furnished to do 
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all 
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


use strict;
use Net::SNMP;

my $status;
my $TIMEOUT = 20;

my %ERRORS = ('UNKNOWN' , '-1',
              'OK' , '0',
              'WARNING', '1',
              'CRITICAL', '2');

my $state = "OK";
my $answer = "";
my $snmpkey;
my $key;
my $community = "public";
my $port = 161;

my $snmpDiskStatusTable = '1.3.6.1.4.1.7933.1.10.2.1.1.1.8';
my $snmpBatteryStatus = '.1.3.6.1.4.1.7933.2.1.7.1.1.14.1.1';
my $snmpPSUStatusTable = '.1.3.6.1.4.1.7933.2.1.4.1.1.2.1';
my $snmpCoolingDeviceStatusTable = '.1.3.6.1.4.1.7933.2.1.3.1.1.3.1';
my $snmpTemperatureStatusTable = '.1.3.6.1.4.1.7933.2.1.5.1.1.3';
my $snmpDrivesOffline = '.1.3.6.1.4.1.7933.1.10.1.2.1.1.22.1';
my $snmpDrivesWithPFA = '.1.3.6.1.4.1.7933.1.10.1.2.1.1.23.1';
my $snmpDrivesRebuilding = '.1.3.6.1.4.1.7933.1.10.1.2.1.1.24.1';
my $snmpDrivesMissing = '.1.3.6.1.4.1.7933.1.10.1.2.1.1.25.1';

my $hostname;
my $session;
my $error;
my $response = undef;
my $usage;

my $itn;
my @psu_stats = undef;
my @disk_stats = undef;
my @cooldev_stats = undef;
my @temp_stats = undef;


sub setstate 
{
    my $newstate = shift( @_ );

    if( $ERRORS{$newstate} > $ERRORS{$state} ) 
    {
        $state = $newstate;
        return();
    }
    
    if( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 
    {
        $state = $newstate;
        return();
    }
}

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
     print ("ERROR: No snmp response from $hostname\n");
     exit $ERRORS{"UNKNOWN"};
};
alarm($TIMEOUT);

$community = shift;
$hostname  = shift;

( $session, $error ) = Net::SNMP->session(
 -hostname  => $hostname,
 -community => $community,
 -port      => $port
);

if( !defined( $session ) ) 
{
    $state='UNKNOWN';
    $answer=$error;
    print ("$state: $answer");
    exit $ERRORS{$state};
}
####################################################################################
# Query the Disk States
####################################################################################

if( !defined( $response = $session->get_table( $snmpDiskStatusTable ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Disk State OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ( "$state: $answer,$snmpkey" );
    exit $ERRORS{$state};
}

$itn = 0;

foreach $snmpkey ( keys %{$response} ) 
{
    $disk_stats[$itn] = $response->{$snmpkey};
    
    if( !( $disk_stats[$itn] =~ "OK" ) )
    {
        &setstate('CRITICAL');
        $answer .= "Disk " . ( $itn + 1 ) . " in state " . $disk_stats[$itn] . "<br />";
    }
    $itn++;
}

####################################################################################
# Query the Battery States
####################################################################################

if( !defined( $response = $session->get_request( $snmpBatteryStatus ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Battery OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ("$state: $answer");
    exit $ERRORS{$state};
}

if( $response->{$snmpBatteryStatus} && !( $response->{$snmpBatteryStatus} =~ "FullyCharged" ) )
{
    &setstate('WARNING');
    $answer .= "Battery status is: " . $response->{$snmpBatteryStatus} . "<br />";
}

####################################################################################
# Query the PSU States
####################################################################################

if( !defined( $response = $session->get_table( $snmpPSUStatusTable ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "PSU OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ( "$state: $answer,$snmpkey" );
    exit $ERRORS{$state};
}

$itn = 0;

foreach $snmpkey ( keys %{$response} ) 
{
    $psu_stats[$itn] = $response->{$snmpkey};
    
    if( !( $psu_stats[$itn] =~ "Powered On and Functional" ) )
    {
        &setstate('CRITICAL');
        $answer .= "PSU #" . ( $itn + 1 ) . " in state " . $psu_stats[$itn] . "<br />";
    }
    $itn++;
}



####################################################################################
# Query the Cooling Device States
####################################################################################

if( !defined( $response = $session->get_table( $snmpCoolingDeviceStatusTable ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Cooling Device OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ( "$state: $answer,$snmpkey" );
    exit $ERRORS{$state};
}

$itn = 0;

foreach $snmpkey ( keys %{$response} ) 
{
    $cooldev_stats[$itn] = $response->{$snmpkey};
    
    if( !( $cooldev_stats[$itn] =~ "Functional" ) )
    {
        &setstate('CRITICAL');
        $answer .= "Cooling device #" . ( $itn + 1 ) . " in state " . $cooldev_stats[$itn] . "<br />";
    }
    $itn++;
}



####################################################################################
# Query the Temperature States
####################################################################################

if( !defined( $response = $session->get_table( $snmpTemperatureStatusTable ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Temperature States OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ( "$state: $answer,$snmpkey" );
    exit $ERRORS{$state};
}

$itn = 0;

foreach $snmpkey ( keys %{$response} ) 
{
    $temp_stats[$itn] = $response->{$snmpkey};
    
    if( !( $temp_stats[$itn] =~ "normal" ) )
    {
        &setstate('CRITICAL');
        $answer .= "Temperature sensor #" . ( $itn + 1 ) . " in state " . $temp_stats[$itn] . "<br />";
    }
    $itn++;
}


####################################################################################
# Query Some Specific Drive States
####################################################################################

if( !defined( $response = $session->get_request( $snmpDrivesOffline ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Drives Offline OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ("$state: $answer");
    exit $ERRORS{$state};
}

if( $response->{$snmpDrivesOffline} > 0 )
{
    &setstate('CRITICAL');
    $answer .= "There are " . $response->{$snmpDrivesOffline} . " drives offline<br />";
}


if( !defined( $response = $session->get_request( $snmpDrivesWithPFA ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Drives with PFA OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ("$state: $answer");
    exit $ERRORS{$state};
}

if( $response->{$snmpDrivesWithPFA} > 0 )
{
    &setstate('WARNING');
    $answer .= "There are " . $response->{$snmpDrivesWithPFA} . " drives with PFA status<br />";
}


if( !defined( $response = $session->get_request( $snmpDrivesRebuilding ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Drives rebuilding OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ("$state: $answer");
    exit $ERRORS{$state};
}

if( $response->{$snmpDrivesRebuilding} > 0 )
{
    &setstate('WARNING');
    $answer .= "There are " . $response->{$snmpDrivesRebuilding} . " drives rebuilding<br />";
}


if( !defined( $response = $session->get_request( $snmpDrivesMissing ) ) ) 
{
    if( $session->error_status == 2 ) 
    {
        $answer = "Drives missing OID not supported.";
    } 
    else 
    { 
        $answer=$session->error; 
    }
    $session->close;
    $state = 'CRITICAL';
    print ("$state: $answer");
    exit $ERRORS{$state};
}

if( $response->{$snmpDrivesMissing} > 0 )
{
    &setstate('CRITICAL');
    $answer .= "There are " . $response->{$snmpDrivesMissing} . " drives missing<br />";
}


####################################################################################
####################################################################################

$session->close;

if($state eq 'OK') 
{
    print "Chassis OK\n";
} 
else 
{
    print "$answer\n"; 
}

exit $ERRORS{$state};

