Plugin:check hp


 * 1) ! /usr/bin/perl -w
 * 2) check_hp - nagios plugin
 * 3) Copyright (C) 2008-2014 Guenther Mair,
 * 4) Derived from check_ifoperstatus by Christoph Kron.
 * 5) This program is free software; you can redistribute it and/or
 * 6) modify it under the terms of the GNU General Public License
 * 7) as published by the Free Software Foundation; either version 2
 * 8) of the License, or (at your option) any later version.
 * 9) This program is distributed in the hope that it will be useful,
 * 10) but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 11) MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * 12) GNU General Public License for more details.
 * 13) You should have received a copy of the GNU General Public License
 * 14) along with this program; if not, write to the Free Software
 * 15) Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 16) Report bugs to:  guenther.mair@hoslo.ch
 * 17) $Id: check_hp 62 2014-08-02 16:05:01Z gunny $
 * 1) You should have received a copy of the GNU General Public License
 * 2) along with this program; if not, write to the Free Software
 * 3) Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 4) Report bugs to:  guenther.mair@hoslo.ch
 * 5) $Id: check_hp 62 2014-08-02 16:05:01Z gunny $
 * 1) Report bugs to:  guenther.mair@hoslo.ch
 * 2) $Id: check_hp 62 2014-08-02 16:05:01Z gunny $
 * 1) $Id: check_hp 62 2014-08-02 16:05:01Z gunny $

my $nagioslibexec;

BEGIN { my @lib_folders = qw(/usr/local/nagios/libexec /usr/lib/nagios/plugins/); foreach my $lib (@lib_folders) { if (-d $lib) { $nagioslibexec = $lib; last; } } }

use POSIX; use strict;

use lib $nagioslibexec; use utils qw($TIMEOUT %ERRORS &print_revision &support);

use Net::SNMP; use Getopt::Long; &Getopt::Long::config('bundling');


 * 1) function prototypes

sub print_help ; sub usage ; sub process_arguments ; sub in_array ($@);


 * 1) module-specific variables

my $PROGNAME = "check_hp"; my $REVISION = '$Rev: 62 $'; my $debug; my $exclude = ''; my $warnings = ''; my $required = ''; my @all_exclude; my @all_warnings; my @all_required; my $countComponents = 0; my $state = 'OK'; my $answer = ""; my $tmp = ""; my $result;


 * 1) variables for argument handling

my $opt_h; my $opt_V; my $status;


 * 1) snmp specific variables

my $timeout; my $hostname; my $session; my $error; my $response; my $key; my $lastc; my $name; my $community = "public"; my $snmp_version = 1; my $maxmsgsize = 1472; # Net::SNMP default is 1472 my ($seclevel, $authproto, $secname, $authpass, $privpass, $auth, $priv); my $context = ""; my $port = 161; my @snmpoids;


 * 1) Compaq/HP system states

my %cpqGenericStates = ( '1','other',  '2','ok',  '3','degraded',  '4','failed');

my %cpqDaLogDrvStates = ( '1','other',  '2','ok',  '3','failed',  '4','unconfigured',  '5','recovering',  '6','readyForRebuild',  '7','rebuilding',  '8','wrongDrive',  '9','badConnect',  '10','overheating',  '11','shutdown',  '12','expanding',  '13','notAvailable',  '14','queuedForExpansion');

my %cpqDaPhyDrvStates = ( '1','other',  '2','ok',  '3','failed',  '4','predictiveFailure');

my %cpqDaPhyDrvSmartStates = ( '1','other',  '2','ok',  '3','replaceDrive');

my %cpqDaTapeDrvStates = ( '1', 'unknown',  '2', 'ok',  '3', 'degraded',  '4', 'failed',  '5', 'offline',  '6', 'missingWasOk',  '7', 'missingWasOffline');

my %cpqSeCpuStates = ( '1','unknown',  '2','ok',  '3','degraded',  '4','failed',  '5','disabled');

my %cpqHeResilientMemStates = ( '1', 'other',  '2', 'ok',  '3', 'degraded');

my %cpqFcaHostStates = ( '1', 'unknown',  '2', 'ok',  '3', 'failed',  '4', 'shutdown',  '5', 'loopDegraded',  '6', 'loopFailed',  '7', 'notConnected');

my %cpqNicIfLogMapStates = ( '1', 'unknown',  '2', 'ok',  '3', 'primaryFailed',  '4', 'standbyFailed',  '5', 'groupFailed',  '6', 'redundancyReduced',  '7', 'redundancyLost');

my %cpqNicIfPhysAdapterStates = ( '1', 'unknown',  '2', 'ok',  '3', 'generalFailure',  '4', 'linkFailure');


 * 1) Compaq/HP system OIDs (ascending numeric order), names and state-types

my %cpqComponents = (  cpqSeCpuStatus => {     OID  => '1.3.6.1.4.1.232.1.2.2.1.1.6',     name => 'CPU status',     type => 'cpqSeCpuStates',   },   cpqDaCntlrCondition => {     OID  => '1.3.6.1.4.1.232.3.2.2.1.1.6',     name => 'controller status',     type => 'cpqGenericStates',   },   cpqDaAccelCondition => {     OID  => '1.3.6.1.4.1.232.3.2.2.2.1.9',     name => 'array accelerator status',     type => 'cpqGenericStates',   },   cpqDaLogDrvStatus => {     OID  => '1.3.6.1.4.1.232.3.2.3.1.1.4',     name => 'logical drive status',     type => 'cpqDaLogDrvStates',   },   cpqDaLogDrvCondition => {     OID  => '1.3.6.1.4.1.232.3.2.3.1.1.11',     name => 'logical drive and associated physical state',     type => 'cpqGenericStates',   },   cpqDaPhyDrvStatus => {     OID  => '1.3.6.1.4.1.232.3.2.5.1.1.6',     name => 'physical drive status',     type => 'cpqDaPhyDrvStates',   },   cpqDaPhyDrvCondition => { OID => '1.3.6.1.4.1.232.3.2.5.1.1.37', name => 'physical drive condition', type => 'cpqGenericStates', },  cpqDaPhyDrvSmartStatus => { OID => '1.3.6.1.4.1.232.3.2.5.1.1.57', name => 'physical drive S.M.A.R.T status', type => 'cpqDaPhyDrvSmartStates', },  cpqDaTapeDrvStatus => { OID => '1.3.6.1.4.1.232.3.2.9.1.1.8', name => 'tape drive status', type => 'cpqDaTapeDrvStates', },  cpqHeEventLogCondition => { OID => '1.3.6.1.4.1.232.6.2.11.2.0', name => 'overall IML entries', type => 'cpqGenericStates', },  cpqHeThermalSystemFanStatus => { OID => '1.3.6.1.4.1.232.6.2.6.4', name => 'status of the processor fan(s)', type => 'cpqGenericStates', },  cpqHeThermalCpuFanStatus => { OID => '1.3.6.1.4.1.232.6.2.6.5', name => 'status of the fan(s)', type => 'cpqGenericStates', },  cpqHeFltTolFanCondition => { OID => '1.3.6.1.4.1.232.6.2.6.7.1.9', name => 'condition of the fan', type => 'cpqGenericStates', },  cpqHeTemperatureCondition => { OID => '1.3.6.1.4.1.232.6.2.6.8.1.6', name => 'temperature sensor condition', type => 'cpqGenericStates', },  cpqHeFltTolPwrSupplyCondition => { OID => '1.3.6.1.4.1.232.6.2.9.1', name => 'overall condition of power supply subsystem', type => 'cpqGenericStates', },  cpqHeFltTolPowerSupplyCondition => { OID => '1.3.6.1.4.1.232.6.2.9.3.1.4', name => 'condition of the power supply', type => 'cpqGenericStates', },  cpqRackCommonEnclosureFanCondition => { OID => '1.3.6.1.4.1.232.22.2.3.1.3.1.11', name => 'condition of the rack fan', type => 'cpqGenericStates', },  cpqRackPowerSupplyCondition => { OID => '1.3.6.1.4.1.232.22.2.5.1.1.1.17', name => 'condition of the power supply', type => 'cpqGenericStates', },  cpqHeResilientMemCondition => { OID => '1.3.6.1.4.1.232.6.2.14.4', name => 'condition of the memory protection subsystem', type => 'cpqHeResilientMemStates', },  cpqNicIfLogMapStatus => { OID => '1.3.6.1.4.1.232.18.2.2.1.1.11', name => 'status of the NIC logical group', type => 'cpqNicIfLogMapStates', },  cpqFcaHostCntlrStatus => { OID => '1.3.6.1.4.1.232.16.2.7.1.1.4', name => 'fibre channel host controller status', type => 'cpqFcaHostStates', },  cpqNicIfPhysAdapterStatus => { OID => '1.3.6.1.4.1.232.18.2.3.1.1.14', name => 'physical adapter status', type => 'cpqNicIfPhysAdapterStates', });


 * 1) validate arguments

process_arguments;


 * 1) just in case of problems, let's avoid blocking the calling process for too long

$SIG{'ALRM'} = sub { print ("ERROR: No snmp response from $hostname (alarm)\n"); exit $ERRORS{"UNKNOWN"}; };

alarm($timeout);


 * 1) main function

print "Compaq/HP Agent Check:"; print "\n" if (defined $debug); for my $component (keys %cpqComponents) { if (in_array($component, @all_exclude)) { print " excluding '".$component."' from check\n" if (defined $debug); next; }

$result = fetch_status($cpqComponents{$component}{OID}, $cpqComponents{$component}{name}, $cpqComponents{$component}{type}, $component); if ((in_array($component, @all_required)) && ($result < 0)) { print " ". $cpqComponents{$component}{name}. " (NOT FOUND)"; print " required '".$component."' not found\n" if (defined $debug); $state = 'CRITICAL'; } } if ($countComponents == 0) { $state = "UNKNOWN"; print " no cpq/hp component found\n"; } elsif ( ! defined $debug && $state eq 'OK') { print " overall system state OK\n"; } else { print "\n"; } exit $ERRORS{$state};


 * 1) subroutines

sub fetch_status { my $value;
 * 1) $_[0] component OID
 * 2) $_[1] component name
 * 3) $_[2] component type
 * 1) $_[2] component type

if ($_[1] eq "cpqHeEventLogCondition") { if ( ! defined ($response = $session->get_request($_[0]))) { printf(" %-35s %s - %s (OID not found, ignoring)\n", $_[3], $_[1], $_[0]) if (defined $debug); # tree not found, ignore! return -1; } } elsif ( ! defined ($response = $session->get_table($_[0]))) { printf(" %-35s %s - %s (OID-tree not found, ignoring)\n", $_[3], $_[1], $_[0]) if (defined $debug); # tree not found, ignore! return -1; }

while (($key, $value) = each %{$response}) { my $component_unit = $_[3]. '.' . substr($key, length($_[0])+1); my $component_value = $_[3]. '=' . $value; if ($value > 2) { # 1 = other/unknow => assume OK      # 2 = ok            => OK      # 3 = failure/worse => CRITICAL/WARNING if (in_array($component_unit, @all_exclude)) { next; } elsif ((in_array($key, @all_warnings) || in_array($component_value, @all_warnings)) && $state ne 'CRITICAL') { printf("critical state reduced to warning because of setting %s\n", $component_value) if (in_array($component_value, @all_warnings) && defined $debug); $state = 'WARNING'; } else { $state = 'CRITICAL'; }   }    if (defined $debug || $value > 2) { printf(" %-35s = %s ", $component_unit, $value) if (defined $debug); print " ". $_[1] . " (";     if (defined $key && (length($key) > (length($_[0])+2))) {        print substr($key, length($_[0])+1) . ":";      }      # eval to something like '$cpqGenericStates{$value}'      $tmp = eval("\$". $_[2] . "{" . $value. "}");     print $tmp if ($tmp ne "");      print ")\n"; }   $countComponents++; print "\n" if (defined $debug); } return 0; }

sub in_array($@) { my $needle = shift(@_); my %items = map {$_ => 1} @_; return (exists($items{$needle})) ? 1 : 0; }

sub usage { printf "\nMissing arguments!\n"; printf "\n"; printf "Usage: \n"; printf "check_hp -H  [-C ] [-d] [-x excludecomponent1,excludecomponent2,...]\n"; printf "Copyright (C) 2008-2013 Guenther Mair\n"; printf "\nUse 'check_hp --help' for details.\n"; printf "\n\n"; exit $ERRORS{"UNKNOWN"}; }

sub print_help { printf "check_hp plugin for Nagios/Icinga\n"; printf "\nModule specific parameters:\n"; printf "  -d (--debug)      debug / verbose mode (print checked details)\n"; printf "  -x (--exclude)    exclude components from check (separate by commas)\n"; printf "  -w (--warnings)   use warnings instead of criticals for these components (separate by commas)\n"; printf "                    specific values to be selected may be specified as in '-w cpqNicIfLogMapStatus=6'\n"; printf "  -r (--required)   report critical if any of these components is not found (separate by commas)\n"; printf "\nCurrently the module supports the following components:\n ". join(",\n ", keys %cpqComponents). "\n"; printf "\nSNMP parameters:\n"; printf "  -H (--hostname)   Hostname to query (required)\n"; printf "  -C (--community)  SNMP read community (defaults to public,\n";  printf "                     used with SNMP v1 and v2c\n";  printf "   -v (--snmp_version)  1 for SNMP v1 (default)\n";  printf "                        2 for SNMP v2c\n";  printf "                        SNMP v2c will use get_bulk for less overhead\n";  printf "   -L (--seclevel)   choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n";  printf "   -U (--secname)    username for SNMPv3 context\n";  printf "   -A (--authpass)   authentication password (cleartext ascii or localized key\n"; printf "                    in hex with 0x prefix generated by using \"snmpkey\" utility\n"; printf "                    auth password and authEngineID\n"; printf "  -a (--authproto)  Authentication protocol (MD5 or SHA1)\n"; printf "  -X (--privpass)   privacy password (cleartext ascii or localized key\n";  printf "                     in hex with 0x prefix generated by using \"snmpkey\" utility\n";  printf "                     privacy password and authEngineID\n";  printf "   -p (--port)       SNMP port (default 161)\n";  printf "   -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n";  printf "   -t (--timeout)    seconds before the plugin times out (default=$TIMEOUT)\n";  printf "   -V (--version)    Plugin version\n";  printf "   -h (--help)       usage help \n\n";  print_revision($PROGNAME, '$Revision: 62 $'); }

sub process_arguments { $status = GetOptions(   "V"   => \$opt_V,        "version"        => \$opt_V,    "h"   => \$opt_h,        "help"           => \$opt_h,    "d"   => \$debug,        "debug"          => \$debug,    "x=s" => \$exclude,      "exclude=s"      => \$exclude,    "w=s" => \$warnings,     "warnings=s"     => \$warnings,    "r=s" => \$required,     "required=s"     => \$required,    "v=i" => \$snmp_version, "snmp_version=i" => \$snmp_version,    "C=s" => \$community,    "community=s"    => \$community,    "L=s" => \$seclevel,     "seclevel=s"     => \$seclevel,    "a=s" => \$authproto,    "authproto=s"    => \$authproto,    "U=s" => \$secname,      "secname=s"      => \$secname,    "A=s" => \$authpass,     "authpass=s"     => \$authpass,    "X=s" => \$privpass,     "privpass=s"     => \$privpass,    "p=i" => \$port,         "port=i"         => \$port,    "H=s" => \$hostname,     "hostname=s"     => \$hostname, "M=i" => \$maxmsgsize,  "maxmsgsize=i"   => \$maxmsgsize, "t=i" => \$timeout,     "timeout=i"      => \$timeout, );

@all_exclude = split(/,/, $exclude); @all_warnings = split(/,/, $warnings); @all_required = split(/,/, $required);

if ($status == 0) { print_help; exit $ERRORS{'OK'}; }

if ($opt_V) { print_revision($PROGNAME,'$Revision: 62 $'); exit $ERRORS{'OK'}; }

if ($opt_h) { print_help; exit $ERRORS{'OK'}; }

if (!utils::is_hostname($hostname)) { usage; exit $ERRORS{"UNKNOWN"}; }

$timeout = $TIMEOUT unless (defined $timeout);

if ($snmp_version =~ /3/) { # Must define a security level even though default is noAuthNoPriv # v3 requires a security username if (defined $seclevel && defined $secname) {

# Must define a security level even though defualt is noAuthNoPriv unless ( grep /^$seclevel$/, qw(noAuthNoPriv authNoPriv authPriv) ) { usage; exit $ERRORS{"UNKNOWN"}; }

# Authentication wanted if ( $seclevel eq 'authNoPriv' || $seclevel eq 'authPriv' ) { unless ( $authproto eq 'MD5' || $authproto eq 'SHA1' ) { usage; exit $ERRORS{"UNKNOWN"}; }

if ( ! defined $authpass) { usage; exit $ERRORS{"UNKNOWN"}; } else { if ($authpass =~ /^0x/) { $auth = "-authkey => $authpass" ; } else { $auth = "-authpassword => $authpass"; }       }      }

# Privacy (DES encryption) wanted if ($seclevel eq 'authPriv') { if ( ! defined $privpass) { usage; exit $ERRORS{"UNKNOWN"}; } else { if ($privpass =~ /^0x/) { $priv = "-privkey => $privpass"; } else { $priv = "-privpassword => $privpass"; }       }      }    } else { usage; exit $ERRORS{'UNKNOWN'}; ; } } # end snmpv3

# start snmpv1 / snmpv2 if ($snmp_version =~ /[12]/) { ($session, $error) = Net::SNMP->session(     -hostname   => $hostname,      -community  => $community,      -port       => $port,      -version    => $snmp_version,      -maxmsgsize => $maxmsgsize    );

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

} elsif ($snmp_version =~ /3/) {

if ($seclevel eq 'noAuthNoPriv') { ($session, $error) = Net::SNMP->session(       -hostname => $hostname,        -port     => $port,        -version  => $snmp_version,        -username => $secname      ); } elsif ($seclevel eq 'authNoPriv') { ($session, $error) = Net::SNMP->session(       -hostname     => $hostname,        -port         => $port,        -version      => $snmp_version,        -username     => $secname,        $auth,        -authprotocol => $authproto      ); } elsif ($seclevel eq 'authPriv') { ($session, $error) = Net::SNMP->session(       -hostname     => $hostname,        -port         => $port,        -version      => $snmp_version,        -username     => $secname,        $auth,        -authprotocol => $authproto,        $priv      ); }

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

} else { $state='UNKNOWN'; print ("$state: No support for SNMP v$snmp_version yet\n"); exit $ERRORS{$state}; } }
 * 1) End validation