#! /usr/bin/perl -wT #---------------------------------------------------------------------- # # Author: Martin Fuerstenau, martin.fuerstenau_at_genesix.de # Date: 08.08.2006 # # Purpose: # Checking the status of network interface bonding on Linux. # # Changes: # # - None # # How it works: # # First you have to enhance your SNMP by the output of a shell script. I call # this snmp_bond and it is placed in /opt/bin: # # #!/bin/bash # #set -x # # # # Author: Martin Fuerstenau, martin.fuerstenau_at_genesix.de # # Date : 02082006 # # Purpose: Pipes the data from /proc/net/bonding to snmp for NAGIOS # # BONDING_STAT_DIR=/proc/net/bonding/ # # for BONDING_INTERFACE in $(ls $BONDING_STAT_DIR) # do # ACTIVE="" # INTERFACE="" # RETURN=$BONDING_INTERFACE # # while read LINE; do # case "$LINE" in # "Bonding Mode: "*) # MODE="${LINE##Bonding Mode: }" # RETURN="$RETURN $MODE" ;; # "Currently Active Slave: "*) # ACTIVE="${LINE##Currently Active Slave: }" # RETURN="$RETURN $ACTIVE" ;; # "Slave Interface: "*) # INTERFACE="${LINE##Slave Interface: }" # RETURN="$RETURN $INTERFACE" ;; # "MII Status: "*) # INTERFACE_STATUS="${LINE##MII Status: }" # RETURN="$RETURN $INTERFACE_STATUS" ;; # esac # # done < $BONDING_STAT_DIR/$BONDING_INTERFACE # echo $RETURN # done # # Next you have to add the following line to your snmpd.conf and restart # your snmpd: # # exec .1.3.6.1.4.1.2021.170 bonding /opt/bin/snmp_bond # # If you do know a snmpwalk you will see the status of your bonding # interfaces via snmp. Now you can set up a Nagios check for bonding with this # perl module. # # Synopsis: # # check_teaming_broadcom -H [-C ] [-v ] # #---------------------------------------------------------------------- use strict; use Getopt::Long; use vars qw($VERSION $HELP $hostname $host @OIDS $PROGNAME %INTERFACE_ERROR); use vars qw($community @result $snmpversion $warning $critical $WHATSUP $error); use lib "/usr/lib/nagios/ops_plugins" ; use utils qw(%ERRORS &print_revision &support &usage); # Get the right package from CPAN and install it use SNMP::Util; use SNMP::Util_env; &SNMP::initMib(); $PROGNAME = "check_bonding_linux"; $ENV{'PATH'}=''; $ENV{'BASH_ENV'}=''; $ENV{'ENV'}=''; Getopt::Long::Configure('bundling'); GetOptions ("V" => \$VERSION, "version" => \$VERSION, "h" => \$HELP, "help" => \$HELP, "v=s" => \$snmpversion, "snmpversion=s" => \$snmpversion, "H=s" => \$hostname, "hostname=s" => \$hostname, "C=s" => \$community, "community=s" => \$community); if ($VERSION) { print_revision($PROGNAME,'$Revision: 1.0 $'); exit $ERRORS{'OK'}; } if ($HELP) { print_help(); exit $ERRORS{'OK'}; } if (!$hostname) { print_usage(); usage("Host name/address not specified\n\n"); } if ($hostname =~ /([-.A-Za-z0-9]+)/) { $host = $1; } if (!$host) { print_usage(); usage("Invalid host: $hostname\n\n"); } if (!$community) { $community = "public"; } if (!$snmpversion) { $snmpversion = "1"; } if (!($snmpversion eq "1" || $snmpversion eq "2c")) { print "Error! Only SNMP V1 or 2c supported!\n"; print "Wrong version submitted.\n"; exit 2; } $WHATSUP=bonding(); if ($WHATSUP == 0 ) { exit $ERRORS{'OK'}; } if ($WHATSUP == 1 ) { exit $ERRORS{'WARNING'}; } if ($WHATSUP == 2 ) { exit $ERRORS{'CRITICAL'}; } # --------------- Begin subroutines ---------------------------------------- # We initialize the snmp connection sub bonding { my $NumOIDs = 0; my $OIDROWCNT = 0; my $ROWCNT = 0; my $WARN_ME = 0; my $OID_LOOP_CNT; my $NIC_LOOPCNT; my $NIC_CNT; my $OFFSET; my $OID2GET; my $result; my $snmp = new SNMP::Util(-device => $hostname, -community => $community, -snmpversion => $snmpversion, -timeout => 5, -retry => 0, -poll => 'off', -verbose => 'on', -errmode => 'return', -delimiter => ' ', ); if (!$snmp) { print "Warning! "; print "Server $hostname not reachable!"; $WARN_ME = 1; } # Well - we get the f...ing data, but only is there is somethinf in $snmp if ($snmp) { @OIDS = $snmp->walk(-format => 'o', -oids =>['.1.3.6.1.4.1.2021.170.101'], -print => 'off'); if ($snmp->error) { print "Critical! "; $error = $snmp->errmsg; print "snmp error = $error"; $WARN_ME = 2; } else { # How much elements ( in this case network interfaces) we have in the array? $NumOIDs = @OIDS; # If it is zero make a warning give up if ($NumOIDs == 0) { print "Warning! No data received from host!"; $WARN_ME = 1; } else { for ( $OID_LOOP_CNT=0;$OID_LOOP_CNT<$NumOIDs;$OID_LOOP_CNT++) { # Now we extract the OIDS out of the array and kick out the trailing dot. $OID2GET = $OIDS[$OID_LOOP_CNT]; $OID2GET =~ s/\.$//; # Now we redirect STDERR to /dev/null to suppress some error messages # These messages a caused by the fact tthat there is no describing MIB # for the OIDs used. The perl module tries to buffer the MIBs in a hash # and this causes an error message # Unfortunalety the missing MIB is the reason for the delivery form of the # result. # # - One string instead of an array # - Hex instead of ASCII # # Therefore we have to do some conversation work # From here... --------------------------------------------------------------- open (STDERR, ">>/dev/null"); $result = $snmp->get('e',$OID2GET); @result = split / /, $result; $result=""; # Ok. We take back the redirection. close (STDERR); open(STDERR, ">&STDOUT"); # Now we take all the elemments in the array. With each # array loop me make a shift and place the next element in $hex. # A prefix 0x is added so chr can convert the hex value now in $hex # to ASCII. # # As the next step all these values are chained in a scalar ($result). # This scalar is converted to an array like before. this is not the # standard way to fill an array, but it is faster. while(@result) { my $hex=shift(@result); $hex = "0x$hex"; my $ascii = chr(hex($hex)); $result=$result.$ascii; } @result = split / /, $result; # to here .. --------------------------------------------------------------- # can be replaced by: # # @result=` /usr/bin/snmpget -c $community -v $snmpversion $hostname $OID2GET `; # # This will work and the result is the same. But system calls should for security # normally only be done if there is no other possibility. print "Interface: $result[$ROWCNT]
"; print "Mode : $result[$ROWCNT + 1] $result[$ROWCNT + 2]
"; print "Active: $result[$ROWCNT + 3]
"; if ( $result[$ROWCNT + 4] ne "up" ) { print "Critical! $result[$ROWCNT + 3] no link signal.
"; $WARN_ME = 2; } # Ok - now we process the rest of the bunch. # First lets look how much NICs we have per bonding. That means # take the number of elements of @result minus the 5 used above # and divide the rest by two because one value is the interface name # and the second value is the interface status $NIC_CNT=@result; $NIC_CNT=($NIC_CNT - 5 ) / 2; $OFFSET=5; for ( $NIC_LOOPCNT=0;$NIC_LOOPCNT<$NIC_CNT;$NIC_LOOPCNT++) { if ($result[$ROWCNT + $OFFSET + 1] eq "up" ) { print "$result[$ROWCNT + $OFFSET] link signal ok.
"; } else { print "Critical! $result[$ROWCNT + $OFFSET] no link signal
"; $WARN_ME = 2; } $OFFSET=$OFFSET + 2; } } } } } return $WARN_ME; } sub print_usage { print "\nUsage: $PROGNAME -H [-C community] [-v SNMP Version]\n\n"; print "or\n"; print "\nUsage: $PROGNAME -V for version.\n\n"; print "or\n"; print "\nUsage: $PROGNAME -h for help.\n\n"; } sub print_help { print_revision($PROGNAME,'$Revision: 1.0 $'); print "Copyright (c) 2006 Martin Fuerstenau - martin.fuerstenauatgenesix.de\n"; print "This plugin checks the status of network bonding on linux via SNMP.\n"; print_usage(); print " -H, --hostname=HOST Name or IP address of host to check\n"; print " -C, --community=community SNMPv1 community (default public)\n\n"; print " -v, --snmpversion=snmpversion Version of the SNMP protocol. At present version 1 or 2c\n\n"; print " -h, --help Short help message\n\n"; print " -V, --version Prints version of the plugin\n\n"; print "This plugin uses the 'snmpget' command included with the NET-SNMP package.\n"; print "If you don't have the package installed, you will need to download it from\n"; print "http://net-snmp.sourceforge.net before you can use this plugin.\n\n"; print "This plugin also make use of a enhanced version the perl module SNMP::Util .\n"; print "You will find it enclosed with this plugin. Be shure it is installed.\n\n"; support(); print "\n"; }