#!/opt/vdops/bin/perl # This script replicates the output of "show standby brief" # V Who When What # --------------------------------------------------------------------------- # 1.1.0 skendric 2010-04-02 Upgrade to perl 5.10.1 # 1.0.2 skendric 2009-03-04 Add more interfaces types # 1.0.1 skendric 2009-02-25 Add -i command-line option (specify interface) # 1.0.0 skendric 2008-11-30 First Version # # Author: Stuart Kendrick, sbk {put at sign here} skendric {put dot here} com # # Source: http://www.skendric.com/device # # This software is available under the GNU GENERAL PUBLIC LICENSE, see # http://www.fsf.org/licenses/gpl.html # # # This script takes the following approach: # -Parses the hosts table for a list of targets (or accepts a command- # line list) # -Walks the output of various CISCO-HSRP-MIB variables # -Produces a report which emulates the output of the CLI # "show standby brief" # # # # Requirements: # -The following MIB modules stashed in /opt/vdops/share/snmp/mibs, # or wherever it is that you store MIB modules: # CISCO-PRODUCTS-MIB.my # # -PERL modules: the FHCRC::Netops collection # # # Assumptions: # # # Tested on: # -perl-5.10.1 # -net-snmp-5.5 # # # Instructions: # -Customize the script for your site: find the 'user-configurable # variables' section and modify as appropriate # -Type "show-standby" to see the command-line options # -Try it out # # # # Caveats: # # # Known Bugs: # # # To do: # -Add support for SNMPv3 # # Begin script # Load modules use strict; use warnings; use feature 'say'; use feature 'switch'; use Carp qw(carp cluck croak confess); use Data::Dumper; use English qw( -no_match_vars ); use Getopt::Std; use FHCRC::Netops::CiscoTools 1.3.1; use FHCRC::Netops::HostTools 1.0.3; use FHCRC::Netops::IFTools 1.2.0; use FHCRC::Netops::NetopsTools 2.0.7; use FHCRC::Netops::NetopsData 1.3.0; use FHCRC::Netops::PingTools 1.1.5; use FHCRC::Netops::SNMPTools 1.3.9; use FHCRC::Netops::Utilities 1.3.9; # Declare global variables my %hsrp_info; # Hash of hashes, keyed by target my $just_me; # If defined, only display output for # interfaces matching this string # Define global variables $debug = 0; # 10 = Logging # 9 = Database SELECT operations # 8 = Per IP/MAC/Port processing # 7 = Database INSERT/UPDATE/DELETE # 6 = Dump SNMP var # 5 = Dump snmp_packets # 4 = Grody: print big var # 3 = Verbose: print mid var # 2 = Simple: print small var # 1 = Basic: subroutine trace # 0 = Disable debugging $program_name = 'show-standby'; $usage = 'Usage: show-standby -s {yes|no} [-i {interface}] [-d {integer}] [-r] [-a | -e {expr} | -f {filename} | target1 target2 target3 ...]'; $version = '1.0.2'; # Binaries $grab_hosts = '/bin/cat /etc/hosts'; # Pause parameters $long = 30; $mid = 10; $short = 5; # Ping Stuff $ping_count = 3; $ping_timeout = 1; # Report stuff $institution = 'Widgets International'; $report_file = '/home/netops/rpts/show-standby.txt'; $report_queries = 'bsmith@widgets.com'; $report_subject = 'HSRP Group Status'; # SNMP Stuff # Optimize performance by sorting your community strings and SNMP version # list, most frequently used to the left, least frequently used to the right @mib_dir = qw(/opt/vdops/share/snmp/mibs); @mib_file = qw/ALL/; @snmp_read_list = qw/public/; @snmp_version_list = qw/2 1/; $snmp_port = 161; $snmp_retries = 3; $snmp_timeout = 1000000; # Syslog stuff $syslog_facility = 'local5'; $syslog_host = 'localhost'; $syslog_port = 514; $syslog_priority = 'info'; $syslog_socket = 'unix'; # Other possibilites include 'udp' and # 'stream'; depending on the flavor of Unix, # I've employed each of these # Target details @skip_name = qw/swamp/; @suffixes = qw/-rtr/; # Grab arguments getopts('ad:e:f:i:rs:', \%option); $just_me = $option{i} if defined $option{i}; @target = @ARGV; # Set mode if ($option{r}) { $mode = 'report' } elsif (-t STDIN) { $mode = 'interactive' } else { $mode = 'batch' } ### Begin Main Program ############################################### { check_args(); # Check arguments compile_mibs(); # Compile MIB files build_target(); # Populate @target target_check(); # Look for errors in @target basic_info(); # Gather information do_the_work(); # Do the work print_report(); # Print report } ##### End Main Program ############################################### ######################################################################## # Sort interface names ######################################################################## sub by_interface { my ($a_type, $a_slot, $a_port, $a_vlan, $b_slot, $b_port, $b_type, $b_vlan); if ($a =~ /\//) { ($a_type, $a_slot, $a_port) = ($a =~ /^(\w\w)(\d+)\/(\d+)/); ($b_type, $b_slot, $b_port) = ($b =~ /^(\w\w)(\d+)\/(\d+)/); } else { ($a_type, $a_vlan) = ($a =~ /^(\w\w)(\d+)/); ($b_type, $b_vlan) = ($b =~ /^(\w\w)(\d+)/); } if (defined $a_slot and defined $a_port) { if (($a_type cmp $b_type) != 0) { $a_type cmp $b_type } elsif (($a_slot <=> $b_slot) != 0) { $a_slot <=> $b_slot } elsif (($a_port <=> $b_port) != 0) { $a_port <=> $b_port } } else { if (($a_type cmp $b_type) != 0) { $a_type cmp $b_type } elsif (($a_vlan <=> $b_vlan) != 0) { $a_vlan <=> $b_vlan } } } ######################################################################## # Do the work: acquire image name ######################################################################## sub do_the_work { # Debug trace trace_location('begin') if $debug; # Notify operator print_it('Acquiring HSRP info...'); # Loop through targets TARGET: for my $target (@target) { my ($hsrp_auth, $hsrp_priority, $hsrp_preempt, $hsrp_preempt_delay, $hsrp_virtual_addr, $hsrp_active_addr, $hsrp_standby_addr, $hsrp_state, %hsrp_grp, %if_descr); # Acquire HSRP info # HSRP Auth $hsrp_auth = walk_oid($target, 'cHsrpGrpAuth'); # HSRP Priority $hsrp_priority = walk_oid($target, 'cHsrpGrpPriority'); # HSRP Preempt $hsrp_preempt = walk_oid($target, 'cHsrpGrpPreempt'); for my $iid (keys %$hsrp_preempt) { given ($hsrp_preempt->{$iid}) { when ('false') { $hsrp_preempt->{$iid} = 'N' } when ('true') { $hsrp_preempt->{$iid} = 'P' } default { $hsrp_preempt->{$iid} = 'P' } } } # HSRP Preempt Delay $hsrp_preempt_delay = walk_oid($target, 'cHsrpGrpPreemptDelay'); # HSRP Virtual Address $hsrp_virtual_addr = walk_oid($target, 'cHsrpGrpVirtualIpAddr'); for my $iid (keys %$hsrp_virtual_addr) { my $addr = $hsrp_virtual_addr->{$iid}; $hsrp_virtual_addr->{$iid} = 'unknown' if $addr eq '0.0.0.0'; } # HSRP Active Address $hsrp_active_addr = walk_oid($target, 'cHsrpGrpActiveRouter'); for my $iid (keys %$hsrp_active_addr) { my $addr = $hsrp_active_addr->{$iid}; $hsrp_active_addr->{$iid} = 'unknown' if $addr eq '0.0.0.0'; } # HSRP Standby Address $hsrp_standby_addr = walk_oid($target, 'cHsrpGrpStandbyRouter'); for my $iid (keys %$hsrp_standby_addr) { my $addr = $hsrp_standby_addr->{$iid}; $hsrp_standby_addr->{$iid} = 'unknown' if $addr eq '0.0.0.0'; } # HSRP Standby State say 'Walking cHsrpGrpStandbyState' if $debug > 3; $hsrp_state = walk_oid($target, 'cHsrpGrpStandbyState'); # Name the interfaces for my $iid (keys %$hsrp_auth) { my ($hsrp_grp, $leaf, $if_descr); ($leaf, $hsrp_grp) = ($iid =~ /(\d+)\.(\d+)/); $hsrp_grp{$iid} = $hsrp_grp; say "Getting ifDescr.$leaf" if $debug > 3; $if_descr = snmpGet( {host => $target, oid => "$ifDescr_oid.$leaf"} ); ($if_descr = $if_descr) =~ s/unrouted//; ($if_descr = $if_descr) =~ s/vlan/Vl/i; ($if_descr = $if_descr) =~ s/FastEthernet/Fa/; ($if_descr = $if_descr) =~ s/GigabitEthernet/Gi/; ($if_descr = $if_descr) =~ s/TenGigabitEthernet/Te/; ($if_descr = $if_descr) =~ s/Ethernet/Et/; ($if_descr = $if_descr) =~ s/Serial/Se/; ($if_descr = $if_descr) =~ s/\s//g; $if_descr{$iid} = $if_descr; } # Stuff into a massive data structure $hsrp_info{$target}->{'hsrp_auth'} = $hsrp_auth; $hsrp_info{$target}->{'hsrp_priority'} = $hsrp_priority; $hsrp_info{$target}->{'hsrp_preempt'} = $hsrp_preempt; $hsrp_info{$target}->{'hsrp_preempt_delay'} = $hsrp_preempt_delay; $hsrp_info{$target}->{'hsrp_virtual_addr'} = $hsrp_virtual_addr; $hsrp_info{$target}->{'hsrp_active_addr'} = $hsrp_active_addr; $hsrp_info{$target}->{'hsrp_standby_addr'} = $hsrp_standby_addr; $hsrp_info{$target}->{'hsrp_state'} = $hsrp_state; $hsrp_info{$target}->{'hsrp_grp'} = \%hsrp_grp; $hsrp_info{$target}->{'if_descr'} = \%if_descr; # Entertain operator print $BANG if $mode eq 'interactive'; } # Make things look pretty say "\n" if $mode eq 'interactive'; # Debug trace trace_location('end') if $debug; return 1; } ######################################################################## # Tell the operator what I discovered ######################################################################## sub print_report { my $handle; my %if_descr_values; my $total = @target; my $now = get_now(); # Debug trace trace_location('begin') if $debug; # If we are running in test mode, skip this routine unless ($dome) { print_it("Running in test mode, cannot print a meaningful report\n"); return 1; } # Direct output to screen or to file if ($mode eq 'interactive') { $handle = *STDOUT; } else { open $handle, '>', $report_file or die "Cannot open $report_file: $!\n"; } # Walk targets for my $target (@target) { my @if_descr_sorted; my $hsrp_priority = $hsrp_info{$target}->{'hsrp_priority'}; my $hsrp_preempt = $hsrp_info{$target}->{'hsrp_preempt'}; my $hsrp_preempt_delay = $hsrp_info{$target}->{'hsrp_preempt_delay'}; my $hsrp_virtual_addr = $hsrp_info{$target}->{'hsrp_virtual_addr'}; my $hsrp_active_addr = $hsrp_info{$target}->{'hsrp_active_addr'}; my $hsrp_standby_addr = $hsrp_info{$target}->{'hsrp_standby_addr'}; my $hsrp_state = $hsrp_info{$target}->{'hsrp_state'}; my $hsrp_grp = $hsrp_info{$target}->{'hsrp_grp'}; my $if_descr = $hsrp_info{$target}->{'if_descr'}; # Sort $if_descr %if_descr_values = reverse %$if_descr; print {$handle} <{$iid}, $hsrp_priority->{$iid}, $hsrp_preempt->{$iid}, $hsrp_preempt_delay->{$iid}, $hsrp_state->{$iid}, $hsrp_active_addr->{$iid}, $hsrp_standby_addr->{$iid}, $hsrp_virtual_addr->{$iid}; } print {$handle} "\n\n"; } unless ($handle =~ /STDOUT/) { close $handle or warn "Cannot close $report_file: $!\n"; } # Make things look pretty print_it("\n\nEnding $PROGRAM_NAME"); # Debug trace trace_location('end') if $debug; return 1; } ######################################################################## # Output help ######################################################################## sub HELP_MESSAGE { print <