#!/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"; }