#!/usr/bin/perl
#
# check_hpacucli
#
# Copyright © 2012 Philip Garner, Technophobia Limited.
#
#    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 3 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, see <http://www.gnu.org/licenses/>.
#
# Orginaly written by John Carroll for use with BCNU.
# Cannibalised by Phil Garner for Nagios.
#
# This plugin was written for and at the expense of Technophobia Limited
# and is being made available with there authorisation.
#
# Authors: Phil Garner - phil.garner@technophobia.com
#          John Carroll - john.carroll@technophobia.com
#
# v0.1 06/03/2012
# v0.2 11/06/2012 change file opp test on hpacucli
# v0.3 12/11/2012 add -w
# v0.4 23/11/2013 Fix for 5.14+ depreciations
#
# NOTES: Requires Perl Module Nagios::Plugin & hpacucli to be installed
#        Nagios user will need sudo access - suggest adding line below to
#        sudoers:
#	     nagios  ALL=(ALL) NOPASSWD: /usr/sbin/hpacucli
#
#	     In sudoers if requiretty is on (off state is default)
#	     you will also need to add the line below
#	     Defaults:nagios !requiretty
#

use strict;
use warnings;
use Nagios::Plugin;

# These may need changing depending on the configuration of your system
my $hpacucli = '/usr/sbin/hpacucli';
my $sudo     = '/usr/bin/sudo';

my $np = Nagios::Plugin->new(
    shortname => 'check_hpacucli',
    version   => '0.3',
    usage     => "Usage: %s <ARGS>\n\t\t--help for help\n",
    license   => "License - GPL v3 see code for more details",
    url       => "http://www.technophobia.com",
    blurb     => "Blurb:
\tNagios plugin that checks HP RAID controller status with hpacucli, 
\trequires CPAN module Nagios::Plugin & hpacucli to be installed.  
\tTo work it will need a sudoers line see NOTES in code for details.",
);

# Define Extra Args
$np->add_arg(
    spec     => 'informative|i',
    help     => 'Adds information on each check even if OK',
    required => 0,
);

$np->add_arg(
    spec => 'warnonly|w=s',
    help => 'comma seperated list of things to warn on and not crit (default)',
    required => 0,
);

my ( $slot, $fh, $fh2, @warn_only );

$np->getopts;

my $warn_only_list = $np->opts->warnonly;

if ( defined $warn_only_list ) {
    @warn_only = split( /,/, $warn_only_list );
}

# Check sudo is installed and executable
if ( !-x $sudo ) {
    $np->nagios_exit( UNKNOWN, "No executable sudo at $sudo" );
}

# Check hpacucli is installed
if ( !-e $hpacucli ) {
    $np->nagios_exit( UNKNOWN, "No hpacucli at $hpacucli" );
}

# Get controller status
open( $fh, "$sudo $hpacucli controller all show status|" )
  or $np->nagios_exit( CRITICAL, "Failed to run hpacucli" );

# Spin through output
foreach my $line (<$fh>) {

    if ( $line =~ m/Another instance of hpacucli is running! Stop it first\./i )
    {
        $np->nagios_exit( CRITICAL,
            "Another instance of hpacucli is running!" );
    }

    elsif ( $line =~ m/Slot (\d+)/i ) {
        my $slot = $1;

        # Now get further details on each controller

        foreach my $PARAM (qw(array physicaldrive logicaldrive)) {

            open( $fh2,
                "$sudo $hpacucli controller slot=$slot $PARAM all show status|"
              )
              or $np->add_message( CRITICAL,
                "Failed to get info for $PARAM slot $slot" );

            foreach my $line2 (<$fh2>) {
                if ( $line2 =~ /^\s*$PARAM.*:\s*(\w+[\w\s]*)$/i ) {
                    my $result = $1;
                    chomp $result;
                    if ( $result ne "OK" ) {
                        chomp $line2;
                        if ( defined $warn_only_list ) {
                            foreach my $warn (@warn_only) {
                                if ( $warn eq $line2 ) {
                                    $np->add_message( WARNING, "$line2" );
                                }
                                else {
                                    $np->add_message( CRITICAL, "$line2" );
                                }
                            }
                        }
                        else {
                            $np->add_message( CRITICAL, "$line2" );
                        }
                    }
                    elsif ( $np->opts->informative ) {
                        chomp $line2;
                        $np->add_message( OK, "$line2" );
                    }
                }
            }

            close($fh2)
              or $np->add_message( CRITICAL,
                "Failed to get info for $PARAM slot $slot" );
        }
    }
    else {

        # Check the overall controller status is OK
        if ( $line =~ /Status\:\s*([\w\s]+)$/ ) {
            my $result = $1;
            chomp $result;
            if ( $result ne "OK" ) {
                chomp $line;
                if ( defined $warn_only_list ) {
                    foreach my $warn (@warn_only) {
                        if ( $warn eq $line ) {
                            $np->add_message( WARNING, "$line" );
                        }
                        else {
                            $np->add_message( CRITICAL, "$line" );
                        }
                    }
                }
                else {
                    $np->add_message( CRITICAL, "$line" );
                }
            }
            elsif ( $np->opts->informative ) {
                chomp $line;
                $np->add_message( OK, "$line" );
            }
        }

    }
}
close($fh)
  or $np->nagios_exit( CRITICAL,
    "Failed to run $sudo $hpacucli controller all show status" );

# Output Info and Exit
$np->nagios_exit( $np->check_messages() );
