#!/usr/bin/perl # vim:ts=4 # # Check a foundry switch for state of a virtual server # Steve S 2006 # http://www.steveshipway.org/forum # # Usage - # check_foundry [-B] -H switchname [-C community] -v vServerName [-p vPort] # # Version 0.2 use strict; use Net::SNMP; use Getopt::Std; my($CRITACTIVE) = 500; my($WARNACTIVE) = 400; my($FOUNDRY) = '1.3.6.1.4.1.1991'; my($TIMEOUT) = 4; my($DEBUG) = 0; my($COMMUNITY) = 'public'; my($SWITCH) = ''; my($VSERVER) = ''; my($VPORT) = ''; my(%vports) = (); my(%rports) = (); my(%bind) = (); my(%global) = (); my($MSG,$STATUS) = ("",3); use vars qw/$opt_c $opt_w $opt_h $opt_d $opt_H $opt_C $opt_v $opt_B $opt_p $opt_M $opt_T/; my($snmp,$snmperr,$resp); my($maxr,$okr,$state); ########################################################################### sub dohelp() { print "To perform Nagios checks:\n"; print "check_foundry -H switchname [-C community] -v vServerName [-p vPort]\n"; print "To list vServers (info only)\n"; print "check_foundry -H switchname [-C community]\n"; print "To list rServer bindings (info only)\n"; print "check_foundry -B -H switchname [-C community] [-v vServerName [-p vPort]]\n"; print "For MRTG output (total active sessions)\n"; print "check_foundry -M -H switchname [-C community]\n"; print "For MRTG output (active sessions, rServer count)\n"; print "check_foundry -M -H switchname [-C community] -v vServerName [-p vPort]\n"; print "Add -d for debug mode.\n"; print "Use -w and -c to set thresholds for number of Active sessions ($WARNACTIVE, $CRITACTIVE)\n"; exit 0; } sub dooutput() { if($opt_M) { print "U\nU\n\nError: $MSG ($STATUS)\n"; exit 0; } $MSG = "Status: $STATUS" if(!$MSG); $STATUS = 3 if($STATUS<0 or $STATUS>3); print "$MSG\n"; exit $STATUS; } ########################################################################### sub readfoundry() { my($k,$oid,$seq); print "Starting SNMP\n" if($DEBUG); ($snmp,$snmperr) = Net::SNMP->session( -hostname=>$SWITCH, -community=>$COMMUNITY, -timeout=>$TIMEOUT, -retries=>2 ); if($snmperr) { print "($snmperr)\n" if($DEBUG); $MSG = "Error: $snmperr"; $STATUS = 3; dooutput; # exit exit(0); } # gather general stats $resp = $snmp->get_request( -varbindlist=>[ "$FOUNDRY.1.1.4.1.1.0", "$FOUNDRY.1.1.4.1.13.0" ] ); if(!$resp) { $MSG = "Error: Cannot read general OIDs. Is community string correct?"; $STATUS = 3; dooutput; # exit } $global{active} = $resp->{"$FOUNDRY.1.1.4.1.1.0"} -$resp->{"$FOUNDRY.1.1.4.1.13.0"}; # Optimise if(!$VSERVER and $opt_M) { $snmp->close; return; } # Gather vport stats print "Getting vport table\n" if($DEBUG); $resp = $snmp->get_table( -baseoid=>"$FOUNDRY.1.1.4.26"); if(!$resp) { $MSG = "Error: Cannot read VPort Statistics table"; $STATUS = 3; dooutput; # exit } foreach $oid ( keys %{$resp} ) { $oid =~ /\.(\d+)\.(\d+\.\d+\.\d+\.\d+\.\d+)$/; # print "$oid\n" if($DEBUG); if($1 == 3) { $seq = $2; $k = $resp->{$oid}.":".$resp->{"$FOUNDRY.1.1.4.26.1.1.2.$seq"}; # print "Adding vport:$k\n" if($DEBUG); $vports{$k} = { seq=>$seq, vserver=>$resp->{$oid}, vport=>$resp->{"$FOUNDRY.1.1.4.26.1.1.2.$seq"}, vip=>$resp->{"$FOUNDRY.1.1.4.26.1.1.1.$seq"}, active=>$resp->{"$FOUNDRY.1.1.4.26.1.1.4.$seq"}, total=>$resp->{"$FOUNDRY.1.1.4.26.1.1.5.$seq"} }; $VPORT = $resp->{"$FOUNDRY.1.1.4.26.1.1.2.$seq"} if($resp->{$oid} eq $VSERVER and !$VPORT); } } # Gather Rport stats print "Getting rport table\n" if($DEBUG); $resp = $snmp->get_table( -baseoid=>"$FOUNDRY.1.1.4.24"); if(!$resp) { $MSG = "Error: Cannot read RPort Statistics table"; $STATUS = 3; dooutput; # exit } foreach $oid ( keys %{$resp} ) { $oid =~ /\.(\d+)\.(\d+\.\d+\.\d+\.\d+\.\d+)$/; if($1 == 3) { $seq = $2; $k = $resp->{$oid}.":".$resp->{"$FOUNDRY.1.1.4.24.1.1.2.$seq"}; $rports{$k} = { seq=>$seq, vserver=>$resp->{$oid}, vport=>$resp->{"$FOUNDRY.1.1.4.24.1.1.2.$seq"}, vip=>$resp->{"$FOUNDRY.1.1.4.24.1.1.1.$seq"}, active=>$resp->{"$FOUNDRY.1.1.4.24.1.1.7.$seq"}, total=>$resp->{"$FOUNDRY.1.1.4.24.1.1.8.$seq"}, state=>$resp->{"$FOUNDRY.1.1.4.24.1.1.5.$seq"} }; } } # Gather bind information print "Getting bind table\n" if($DEBUG); $resp = $snmp->get_table( -baseoid=>"$FOUNDRY.1.1.4.6"); if(!$resp) { $MSG = "Error: Cannot read bind table"; $STATUS = 3; dooutput; # exit } foreach $oid ( keys %{$resp} ) { $oid =~ /\.(\d+)\.(\d+)$/; # print "$oid\n" if($DEBUG); if($1 == 2) { $seq = $2; $k = $resp->{$oid}.":".$resp->{"$FOUNDRY.1.1.4.6.1.1.3.$seq"}; $bind{$k} = () if(!defined $bind{$k}); push @{$bind{$k}}, ($resp->{"$FOUNDRY.1.1.4.6.1.1.4.$seq"}.":" .$resp->{"$FOUNDRY.1.1.4.6.1.1.5.$seq"}); } } $snmp->close(); } sub listvservers() { print "Listing all vservers...\n" if($DEBUG); print "VServer Name IP Address Port Svrs Active\n"; foreach ( keys %vports ) { printf "%-15s %-16s %5d %3d (%5d)\n", $vports{$_}{vserver},$vports{$_}{vip},$vports{$_}{vport}, ($#{$bind{$_}}+1), $vports{$_}{active}; } } sub listbindings() { if(!$VSERVER) { foreach ( keys %bind ) { print $_.": ".(join ',',@{$bind{$_}})."\n"; } } else { print "Bindings for $VSERVER:$VPORT :\n"; print "".(join ', ',@{$bind{"$VSERVER:$VPORT"}})."\n"; } } ########################################################################### getopts('dhH:C:v:p:MT:B'); dohelp if($opt_h); $DEBUG = 1 if($opt_d); $COMMUNITY = $opt_C if($opt_C); $SWITCH = $opt_H if($opt_H); $VSERVER = $opt_v if($opt_v); $VPORT = $opt_p if($opt_p); $TIMEOUT = $opt_T if($opt_T); if(!$SWITCH) { $STATUS = 3; $MSG = "Must specify foundry switch name with -H."; dooutput; exit 3; } if(!$COMMUNITY) { $STATUS = 3; $MSG = "Must specify SNMP community string with -C."; dooutput; exit 3; } readfoundry; if(!$VSERVER) { if($opt_M) { print $global{active}."\n" .$global{active}."\n\n" .$global{active}." active sessions.\n"; exit 0; } elsif($opt_B) { listbindings; } else { listvservers; } exit(0); } if( $VSERVER =~ /(\S+):(\d+)/ ) { ($VSERVER,$VPORT) = ($1,$2); } if( $VSERVER =~ /\d+\.\d+\.\d+\.\d+/ ) { foreach ( keys %vports ) { if( $vports{$_}{vip} eq $VSERVER ) { $VSERVER = $vports{$_}{vserver}; $VPORT = $vports{$_}{vport} if(!$VPORT); last; } } } # Now, identify the vserver... if(!defined $vports{"$VSERVER:$VPORT"}) { $MSG = "That Server/port is not recognised ($VSERVER:$VPORT)"; $STATUS = 3; dooutput; exit 3; } # Bindings listbindings if($DEBUG or $opt_B); exit 0 if($opt_B); if($opt_M) { # count active rservers $okr = 0; foreach ( @{$bind{"$VSERVER:$VPORT"}} ) { if($rports{$_}{state} == 6) { $okr +=1; } # active } # output print $vports{"$VSERVER:$VPORT"}{active}."\n"; print "$okr\n"; # print "".(1+$#{$bind{"$VSERVER:$VPORT"}})."\n"; print "\n"; print "Active: ".$vports{"$VSERVER:$VPORT"}{active} ." RServers: $okr/".(1+$#{$bind{"$VSERVER:$VPORT"}})."\n"; exit 0; } # Now, we need to work out which RServers we have and their health. $STATUS = 0; if( $vports{"$VSERVER:$VPORT"}{active} > $CRITACTIVE ) { $STATUS = 2; $MSG = "CRIT: ".$vports{"$VSERVER:$VPORT"}{active}." active sessions to $VSERVER:$VPORT"; } elsif( $vports{"$VSERVER:$VPORT"}{active} > $WARNACTIVE ) { $STATUS = 1; $MSG = "WARN: ".$vports{"$VSERVER:$VPORT"}{active}." active sessions to $VSERVER:$VPORT"; } else { $MSG = $vports{"$VSERVER:$VPORT"}{active}." active sessions to $VSERVER:$VPORT"; } $maxr = $#{$bind{"$VSERVER:$VPORT"}} + 1; $okr = 0; foreach ( @{$bind{"$VSERVER:$VPORT"}} ) { # loop through the rservers $state = $rports{$_}{state}; if($state == 6) { $okr +=1; next; } # active if($state == 1) { $MSG .= "
rServer $_ is only ENABLED"; $STATUS= 2; } elsif($state == 2) { $MSG .= "
rServer $_ is FAILED"; $STATUS= 2; } elsif($state == 3) { $MSG .= "
rServer $_ is TESTING"; $STATUS= 1 if($STATUS<2); } elsif($state == 4) { $MSG .= "
rServer $_ is SUSPECT"; $STATUS= 1 if($STATUS<2); } elsif($state == 5) { $MSG .= "
rServer $_ is SHUTDOWN"; } elsif($state == 0) { $MSG .= "
rServer $_ is DISABLED"; } } if($maxr == $okr ) { $MSG .= "
All $maxr RealServers are active."; } else { $MSG .= "
Only $okr/$maxr RealServers are active."; } dooutput; exit(3);