#!/usr/bin/perl
#
# check_ucs
#
# Nagios plugin for monitoring Cisco UCS over SNMP
#
# Copyright (C) 2012-2014 Petr Havlicek (petr.havlicek@vsb.cz)
#
# 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
# 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 .
#
# History:
############
# Version 2.1.0 - 4th April 2014
# - Add support for SNMP version 3
# - Some cosmetic improvements
# Version 2.0.3 - 16th May 2013
# - Add support for greater OID
# - Uknown status with 0 object detected
# Version 2.0.2 23rd January 2013
# - Minor bug fixes
# Version 2.0.1 - 22nd January 2013
# - Added some user input checks
# - Object name comapring case insensitive
# Version 2.0 - 4th January 2013
# - Complete re-design of internal functionality
# - Now first step is getting sub-tree
# - Second step is getting descriptions for all OID in sub-tree
# - Third is filter sub tree by specific description
# - Last step is getting results state for specific OIDs
# Version 1.3 - 16th November 2012
# - Add support for checking faults
# Version 1.2 - 21st August 2012
# - Based on OID prefix for specific device => No manual OID specification
# - Using manual prefix definitation
# - Remove PSU Temperature test
# - Bugfixes
# Version: 1.1.1 - 7th August 2012
# - Monitoring fan modules insteed individuals fans
# Version: 1.1 - 18th June 2012
# - Add support for prinitg description of monitored objects
# - Minor bugfixes
use Getopt::Std;
use Net::SNMP qw(oid_base_match);
use strict;
use vars qw($PROGNAME $VERSION);
$PROGNAME = "check_ucs";
$VERSION = "2.1.0";
# End program after printing version or help
$Getopt::Std::STANDARD_HELP_VERSION = "TRUE";
# SNMP OIDs for Tests
use constant {
CT => ".1.3.6.1.4.1.9.9.719.1.15.7.1.33",
CI => ".1.3.6.1.4.1.9.9.719.1.15.30.1.25",
F => ".1.3.6.1.4.1.9.9.719.1.15.13.1.7",
PO => ".1.3.6.1.4.1.9.9.719.1.15.56.1.7",
FS => ".1.3.6.1.4.1.9.9.719.1.1.1.1.20",
};
# Constants for NAGIOS status code
use constant {
NAGIOS_OK => 0,
NAGIOS_WARNING => 1,
NAGIOS_CRITICAL => 2,
NAGIOS_UNKNOWN => 3,
};
# Args list:
# -a authProtocol
# -A authKey
# -C
# -H
# -N Name of monitoring object
# -T Select test
# -u SecurityName
# -x privProtocol
# -X privKey
our ( $opt_a, $opt_A, $opt_C, $opt_H, $opt_N, $opt_T, $opt_u, $opt_x, $opt_X );
getopts('a:A:C:H:N:T:u:x:X:');
# User input validation
&VERSION_MESSAGE and &HELP_MESSAGE and exit
if !$opt_a
and !$opt_A
and !$opt_C
and !$opt_H
and !$opt_N
and !$opt_T
and !$opt_u
and !$opt_x
and !$opt_X;
my $output;
$output .= "Missing host address (-H)!\n"
if !$opt_H;
$output .= "Missing test type (-T)!\n"
if !( $opt_T =~ m/ct|ci|f|po|fs/i );
$output .= "Missing object name (-N)!\n"
if !$opt_N && !( $opt_T =~ m/FS/i );
$output .= "Missing SNMPv2 community (-C) or SNMPv3 username (-u)!\n"
if !$opt_C && !$opt_u;
$output .= "Bad SNMPv3 authProtocol (-a )!\n"
if !( $opt_a =~ m/^$|MD5|SHA/i );
$output .= "Bad SNMPv3 privProtocoll (-x )!\n"
if !( $opt_x =~ m/^$|DES|AES/i );
$output .= "Mode noAuthPriv not supported!\n"
if !$opt_A && $opt_X;
print $output;
&HELP_MESSAGE and exit if $output;
my $host = lc $opt_H;
my $object_name = lc $opt_N;
my $type = lc $opt_T;
my $snmp_ver = 2;
my $community = $opt_C;
our ( $username, $auth_pass, $auth_proto, $priv_pass, $priv_proto );
if ($opt_u) {
$snmp_ver = 3;
$username = $opt_u;
$priv_pass = $opt_X;
$auth_pass = $opt_A;
$auth_proto = "MD5";
$auth_proto = $opt_a if defined($opt_a);
$priv_proto = "DES";
$priv_proto = $opt_x if defined($opt_x);
}
# Select correct object prefix
if ( $type eq "fs" ) { $object_name = " "; }
# Test definitation
my $test = "";
my $oid_prefix = "";
if ( $type eq "ct" ) {
$test = "Temperature";
$oid_prefix = CT;
}
elsif ( $type eq "ci" ) {
$test = "IOCard";
$oid_prefix = CI;
}
elsif ( $type eq "f" ) {
$test = "Fan";
$oid_prefix = F;
}
elsif ( $type eq "po" ) {
$test = "PSU";
$oid_prefix = PO;
}
elsif ( $type eq "fs" ) {
$test = "Faults";
$oid_prefix = FS;
}
my $oid = $oid_prefix;
# Get informations via SNMP
our ( $session, $error );
# SNMP v2c
if ( defined($community) ) {
( $session, $error ) = Net::SNMP->session(
-hostname => $host,
-version => $snmp_ver,
-community => $community,
);
}
# SNMP v3 AuthPriv
elsif ( defined($priv_pass) ) {
( $session, $error ) = Net::SNMP->session(
-hostname => $host,
-version => $snmp_ver,
-username => $username,
-authpassword => $auth_pass,
-authprotocol => $auth_proto,
-privpassword => $priv_pass,
-privprotocol => $priv_proto,
);
}
# SNMP v3 AuthNoPriv
elsif ( defined($auth_pass) ) {
( $session, $error ) = Net::SNMP->session(
-hostname => $host,
-version => $snmp_ver,
-username => $username,
-authpassword => $auth_pass,
-authprotocol => $auth_proto,
);
}
if ( !defined $session ) {
printf "Connection Error: %s.\n", $error;
exit NAGIOS_UNKNOWN;
}
# Get OID for whole subtree
my @oids_all;
my $response;
while ( defined( $session->get_next_request($oid) ) ) {
$response = ( $session->var_bind_names )[0];
if ( !oid_base_match( $oid_prefix, $response ) ) { last; }
push @oids_all, $response;
$oid = $response;
}
# Get descriptions
my $get;
my @descs;
foreach (@oids_all) {
$oid = $_;
if ( $type eq "fs" ) { $oid =~ s/\d+(\.\d{5,})$/11\1/; }
else { $oid =~ s/\d+(\.\d{5,})$/2\1/; }
$get = $session->get_request("$oid");
if ( !defined $get ) {
printf "SNMP Error: %s.\n at OID: $_\n", $session->error();
$session->close();
exit NAGIOS_UNKNOWN;
}
push( @descs, $get->{$oid} );
}
# Filter relevant information
my @descriptions;
my @oids;
for ( my $i = 0 ; $i < @descs ; $i++ ) {
if ( @descs[$i] =~ /$object_name/i ) {
push( @descriptions, @descs[$i] );
push( @oids, @oids_all[$i] );
}
}
# Get results for selected host
my @results;
for ( my $i = 0 ; $i < @descriptions ; $i++ ) {
$oid = @oids[$i];
$get = $session->get_request("$oid");
if ( !defined $get ) {
printf "SNMP Error: %s.\n at OID: $_\n", $session->error();
$session->close();
exit NAGIOS_UNKNOWN;
}
push( @results, $get->{$oid} );
}
$session->close;
if ( int(@results) eq 0 ) {
print "No OID match! Check your -H and -N or -T\n";
exit NAGIOS_UNKNOWN;
}
# Validation results
my $exit_state = NAGIOS_OK;
my $output = "Problem with $test at";
if ( $type eq "fs" ) { $output = "Faults found!\n"; }
for ( my $i = 0 ; $i < @results ; $i++ ) {
if ( $type eq "fs" ) {
if ( $results[$i] > 4 ) {
$exit_state = NAGIOS_CRITICAL;
$output .= " " . $descriptions[$i] . "\n";
}
next;
}
if ( $results[$i] < 1 ) {
if ( ( $type eq "po" ) || ( $exit_state == NAGIOS_CRITICAL ) ) {
$exit_state = NAGIOS_CRITICAL;
}
else { $exit_state = NAGIOS_WARNING; }
$output .= " " . $descriptions[$i];
}
elsif ( $results[$i] > 1 ) {
$exit_state = NAGIOS_CRITICAL;
$output .= " " . $descriptions[$i];
}
}
if ( $exit_state eq NAGIOS_OK ) {
if ( ( @results eq 0 ) && ( $type ne "fs" ) ) {
$exit_state = NAGIOS_UNKNOWN;
print "No object found\n";
}
else { print int(@results) . " objects OK\n"; }
}
else { print "$output.\n"; }
exit $exit_state;
sub VERSION_MESSAGE {
print "$PROGNAME version $VERSION.\n"
. " by Petr Havlicek (petr.havlicek\@vsb.cz) 2012-2014\n\n"
. "Nagios plugin for monitoring Cisco UCS over SNMP.\n";
}
sub HELP_MESSAGE {
print "\nUSAGE: -H -T -N [-C ]
[-u ] [-a ] [-A ]
[-x ] [-X ]\n";
print "\n";
print "Parameters:\n";
print " -H Target hostname\n";
print " -T Selected test\n";
print " -N Monitoring object name\n";
print " -C SNMPv2 community string\n";
print " -u SNMPv3 SecurityName\n";
print " -a SNMPv3 authProtocol (Default: MD5)\n";
print " -A SNMPv3 authPassword\n";
print " -x SNMPv3 privProtocol (Default: DES)\n";
print " -X SNMPv3 privKey\n";
print "\n";
print "Test types:\n";
print "\tct - Chassis Temperature\n";
print "\tci - Chassis IOCard Status\n";
print "\tf - Fans Status\n";
print "\tpo - PSUs Operate Status\n";
print "\tfs - Faults Summary (Dont need -N)\n";
print "\n";
print "Fabric Interconnects support only these test: f, po\n";
print "Object name examples: switch, switch-A, chassis-1, chassis-10\n";
print "\n";
}