#!/opt/vdops/bin/perl # This script identifies unconfigured modules in Catalyst switches and e-mails # interested parties # V Who When What # --------------------------------------------------------------------------- # 1.3.0 skendric 2011-03-05 Look for ports with PoE disabled # 1.2.0 skendric 2011-02-21 Upgrade to Netops 1.4.0 # 1.1.1 skendric 2010-12-17 Futz with owner/owner_backup # 1.1.0 skendric 2010-01-26 Upgrade to perl 5.10.1 # 1.0.3 skendric 2007-030-21 Stylistic mods # 1.0.2 skendric 2006-11-19 Replace Object Values with OIDs # 1.0.1 skendric 2005-11-05 Upgrade to new WI::VDOPS module structure # 1.0.0 skendric 2005-07-19 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) # -Identifies modules whose ports all belong to VLAN1 or whose ports # are all configured with portfast disabled # -Produces a report identifying unconfigured modules # # # 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 WI::Netops collection # # # Assumptions: # # # Tested on: # -perl-5.12.2 # -net-snmp-5.6 # # # Instructions: # -Customize the script for your site: find the 'user-configurable # variables' section and modify as appropriate # -Try it out # # # # Caveats: # # # Known Bugs: # # # To do: # -In the report, specify which modules contain afflicted ports # -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 WI::Netops::HostTools 1.0.4; use WI::Netops::IFTools 1.3.1; use WI::Netops::NetopsTools 2.2.3; use WI::Netops::NetopsData 1.4.0; use WI::Netops::PingTools 1.1.7; use WI::Netops::SNMPTools 1.5.3; use WI::Netops::Utilities 1.4.4; # Declare global variables my %ifAdminStatus; # Hash of hash refs, keyed by ifIndex my %disabled_poe; # The number of interfaces on which PoE is # disabled, keyed by target my %disabled_port_fast; # The number of interfaces on which # portfast is disabled, keyed by target my %global_port_fast; # Whether or not portfast is enabled globally my %vlan_one; # The list of modules on which all ports belong # to VLAN1, keyed by target # Define global variables $program_name = 'unconf-modules-alarm'; $usage = 'Usage: unconf-modules-alarm -s {yes|no} [-d {integer}] [-r] [-a | -e {expr} | -f {filename} | target1 target2 target3 ...]'; $version = '1.3.0'; # Grab arguments getopts('ad:e:f:rs:', \%option); @target = @ARGV; # Set mode if ($option{r}) { $mode = 'report' } elsif (-t STDIN) { $mode = 'interactive' } else { $mode = 'batch' } ### Begin Main Program ############################################### { check_args(); # Check arguments read_config(); # Read Netops config file 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 identify_alarms(); # Figure out what is broken write_alarm_log(); # Record issues print_report(); # Print report notify_staff(); # Mail report } ##### End Main Program ############################################### ####################################################################### # Look for devices with portfast globally disabled ######################################################################## sub analyze_global_portfast { my %arg; # Args for snmpWalk my $host = shift; my $stpxFastStartGlobalDefaultMode; # Debug trace trace_location('begin') if $debug; # Acquire stpxFastStartGlobalDefaultMode %arg = ( host => $host, oid => 'stpxFastStartGlobalDefaultMode.0' ); $stpxFastStartGlobalDefaultMode = snmpGet(\%arg); # Whine or not given ($stpxFastStartGlobalDefaultMode) { when ('enable') { say "PortFast is globally enabled on $host" if $debug; $global_port_fast{$host} = 'Enabled'; } when ('disable') { log_it("PortFast is globally disabled on $host"); say "PortFast is globally disabled on $host" if $debug; $global_port_fast{$host} = 'Disabled'; $alarm_count{$host}++; } default { $global_port_fast{$host} = $DASH; say "Problem reading stpxFastStartGlobalDefaultMode / $host" if $debug; } } # Debug trace trace_location('end') if $debug; return 1; } ####################################################################### # Look for ports with portfast disabled ######################################################################## sub analyze_if_portfast { my %arg; # Args for snmpWalk my $host = shift; my $ifAdminStatus_ref; # Reference to an array of Varbinds my $stpxFastStartPortMode_ref; # Reference to an array of Varbinds my $vmMembership; # Hex-String # Debug trace trace_location('begin') if $debug; # Acquire stpxFastStartPortMode %arg = ( host => $host, oid => 'stpxFastStartPortMode' ); $stpxFastStartPortMode_ref = snmpWalk(\%arg); # Walk ports PORT: for my $varbind (@$stpxFastStartPortMode_ref) { my ($index, $status); # Pull out vlan and status $status = $varbind->{val}; $index = $varbind->{iid}; # Check portfast status if ($status =~ /disable/) { my $if; $disabled_port_fast{$host}++; $if = snmpGet( {host => $host, oid => "entPhysicalName.$index"} ); $if //= $QUERY; say "For $host, PortFast is disabled on $if" if $mode eq 'interactive'; log_it("For $host, PortFast is disabled on $if"); $alarm_count{$host}++; } } # Default $disabled_port_fast{$host} //= 0; # Debug trace trace_location('end') if $debug; return 1; } ####################################################################### # Look for ports with PoE disabled ######################################################################## sub analyze_poe { my %arg; # Args for snmpWalk my $host = shift; my $cefcFRUPowerOperStatus_ref; # Reference to an array of Varbinds # Debug trace trace_location('begin') if $debug; # Acquire stpxFastStartPortMode %arg = ( host => $host, oid => 'cefcFRUPowerOperStatus' ); $cefcFRUPowerOperStatus_ref = snmpWalk(\%arg); # Walk ports PORT: for my $varbind (@$cefcFRUPowerOperStatus_ref) { my ($index, $status); # Pull out vlan and status $status = $varbind->{val}; $index = $varbind->{iid}; # Check PoE status unless ($status eq 'offEnvOther' or $status eq 'on') { my $if; $disabled_poe{$host}++; $if = snmpGet( {host => $host, oid => "entPhysicalName.$index"} ); $if //= $QUERY; say "For $host, PoE status is $status on $if" if $mode eq 'interactive'; log_it("For $host, PoE status is $status on $if"); $alarm_count{$host}++; } } # Default $disabled_poe{$host} //= 0; # Debug trace trace_location('end') if $debug; return 1; } ####################################################################### # Look for VLAN1 on ports in given target ######################################################################## sub analyze_vlans { my $host = shift; my $vmVlan_ref; # Reference to an array of Varbinds # Debug trace trace_location('begin') if $debug; # Acquire vmMembershipSummaryMember2kPorts.1 say 'Walking vmVlan' if $debug > 3; $vmVlan_ref = snmpWalk( {host => $host, oid => 'vmVlan'} ); # Walk vmVlan for my $varbind (@$vmVlan_ref) { my ($index, $vlan); # Pull out ifIndex and vlan $index = $varbind->{iid}; $vlan = $varbind->{val}; # Check VLAN membership and ifAdminStatus if ($vlan == 1 and $ifAdminStatus{$host} eq 'up') { my $if; $vlan_one{$host}++; $if = snmpGet( {host => $host, oid => "entPhysicalName.$index"} ); $if //= $QUERY; say "\nFor $host, VLAN1 active on $if" if $mode eq 'interactive'; log_it("For $host, VLAN1 active on $if"); } } # Default $vlan_one{$host} //= 0; # Debug trace trace_location('end') if $debug; return 1; } ######################################################################## # Do the work: vlan and portfast information ######################################################################## sub do_the_work { # Debug trace trace_location('begin') if $debug; # Notify operator print_it('Acquiring portfast and vlan info...'); # Loop through targets for my $target (@target) { # Grab ifAdminStatus $ifAdminStatus{$target} = grab_if_admin_status($target); # Look for switches with portfast globally disabled analyze_global_portfast($target); # Look for ports with portfast disabled analyze_if_portfast($target); # Look for ports belonging to VLAN1 analyze_vlans($target); # Look for ports where PoE is disabled analyze_poe($target); # 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 @fields; my $handle; 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"; } print {$handle} <