update test_class.pl utility to allow ignore of snmp.conf and test summarize more standard class methods
This commit is contained in:
362
t/test_class.pl
362
t/test_class.pl
@@ -1,146 +1,191 @@
|
||||
#!/usr/bin/perl -w
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# test_class.pl
|
||||
#
|
||||
# Test a device class in SNMP::Info against a device.
|
||||
# Copyright (c) 2013 Eric Miller
|
||||
# All rights reserved.
|
||||
#
|
||||
# Max Baker
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# $Id$
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the University of California, Santa Cruz nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../..";
|
||||
#use lib '/usr/local/netdisco';
|
||||
|
||||
use SNMP::Info;
|
||||
use Getopt::Long;
|
||||
use strict;
|
||||
use vars qw/$Class $Dev $Comm $Ver @Dump %Dumped $Debug %args $NoBulk $MibDirs/;
|
||||
use warnings;
|
||||
use Carp;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use SNMP::Info;
|
||||
|
||||
my $EMPTY = q{};
|
||||
|
||||
# Default Values
|
||||
$Class = '';
|
||||
$Dev = '';
|
||||
$Comm = '';
|
||||
$Ver = 2;
|
||||
@Dump = ();
|
||||
$Debug = 0;
|
||||
$NoBulk = 0;
|
||||
my $class = $EMPTY;
|
||||
my @dump = ();
|
||||
my $debug = 0;
|
||||
my $device = '';
|
||||
my $comm = '';
|
||||
my $ver = 2;
|
||||
my $ignore = 0;
|
||||
my $help = 0;
|
||||
my $nobulk = 0;
|
||||
my $mibdirs;
|
||||
my %dumped;
|
||||
|
||||
GetOptions ('c|class=s' => \$Class,
|
||||
'd|dev=s' => \$Dev,
|
||||
's|comm=s' => \$Comm,
|
||||
'v|ver=i' => \$Ver,
|
||||
'h|help' => \&usage,
|
||||
'p|print=s' => \@Dump,
|
||||
'x|debug+' => \$Debug,
|
||||
'n|nobulk' => \$NoBulk,
|
||||
'm|mibdir=s@' => \$MibDirs,
|
||||
GetOptions(
|
||||
'c|class=s' => \$class,
|
||||
'd|dev=s' => \$device,
|
||||
's|comm=s' => \$comm,
|
||||
'v|ver=i' => \$ver,
|
||||
'i|ignore' => \$ignore,
|
||||
'p|print=s' => \@dump,
|
||||
'x|debug+' => \$debug,
|
||||
'm|mibdir=s' => \$mibdirs,
|
||||
'n|nobulk' => \$nobulk,
|
||||
'h|?|help' => sub { pod2usage(1); },
|
||||
);
|
||||
|
||||
&usage unless ($Dev and $Comm);
|
||||
|
||||
# Default MIB directories
|
||||
my $n = '/usr/local/netdisco';
|
||||
unless (defined $MibDirs) {
|
||||
$MibDirs = ["$n/mibs/allied", "$n/mibs/asante", "$n/mibs/cisco", "$n/mibs/foundry",
|
||||
"$n/mibs/hp", "$n/mibs/nortel", "$n/mibs/extreme", "$n/mibs/rfc",
|
||||
"$n/mibs/net-snmp"];
|
||||
unless ( $device and $comm ) {
|
||||
pod2usage(2);
|
||||
}
|
||||
|
||||
$Class = $Class ? "SNMP::Info::$Class" : 'SNMP::Info';
|
||||
eval "require $Class;";
|
||||
if ($@) {
|
||||
die "Can't load Class specified : $Class.\n\n$@\n";
|
||||
if ( $ignore && !defined $mibdirs ) {
|
||||
print "mibdirs must be provided if ignoring snmp.conf \n\n";
|
||||
pod2usage(1);
|
||||
}
|
||||
|
||||
my $class_ver = 'undef';
|
||||
{ no strict 'refs';
|
||||
$class_ver = ${"${Class}::VERSION"};
|
||||
}
|
||||
print "Class $Class ($class_ver) loaded from SNMP::Info $SNMP::Info::VERSION.\n";
|
||||
#print "MIB Dirs : ",join(', ',@$MibDirs),"\n";
|
||||
print "Dumping : ",join(',',@Dump),"\n" if scalar @Dump;
|
||||
if ($ignore) { local $ENV{'SNMPCONFPATH'} = $EMPTY }
|
||||
if ($ignore) { local $ENV{'MIBDIRS'} = "$mibdirs" }
|
||||
|
||||
%args = ();
|
||||
if ($NoBulk) {
|
||||
if ( defined $mibdirs ) {
|
||||
SNMP::addMibDirs($mibdirs);
|
||||
}
|
||||
|
||||
$class = $class ? "SNMP::Info::$class" : 'SNMP::Info';
|
||||
|
||||
( my $mod = "$class.pm" )
|
||||
=~ s{::}{/}xg; # SNMP::Info::Layer3 => SNMP/Info/Layer3.pm
|
||||
if ( !eval { require $mod; 1; } ) {
|
||||
croak "Could not load $class. Error Message: $@\n";
|
||||
}
|
||||
|
||||
my $class_ver = $class->VERSION();
|
||||
|
||||
print
|
||||
"Class $class ($class_ver) loaded from SNMP::Info $SNMP::Info::VERSION.\n";
|
||||
|
||||
if ( scalar @dump ) { print 'Dumping : ', join( q{,}, @dump ), "\n" }
|
||||
|
||||
my %args = ();
|
||||
if ($nobulk) {
|
||||
$args{BulkWalk} = 0;
|
||||
}
|
||||
|
||||
my $dev = new $Class( 'AutoSpecify' => 0,
|
||||
my $dev = $class->new(
|
||||
'AutoSpecify' => 0,
|
||||
'AutoVerBack' => 0,
|
||||
'Version' => $Ver,
|
||||
'Debug' => $Debug,
|
||||
'DestHost' => $Dev,
|
||||
'Community' => $Comm,
|
||||
'MibDirs' => $MibDirs,
|
||||
'Debug' => $debug,
|
||||
'MibDirs' => $mibdirs,
|
||||
'Version' => $ver,
|
||||
'DestHost' => $device,
|
||||
'Community' => $comm,
|
||||
%args
|
||||
) or die "\n";
|
||||
|
||||
print "Connected to $Dev.\n";
|
||||
print "Detected Class: ", $dev->device_type(), "\n";
|
||||
print "Using Class: $Class (-c to change)\n";
|
||||
print "Connected to $device.\n";
|
||||
print 'Detected Class: ', $dev->device_type(), "\n";
|
||||
print "Using Class: $class (-c to change)\n";
|
||||
|
||||
my $layers = $dev->layers();
|
||||
my $descr = $dev->description();
|
||||
|
||||
unless (defined $layers or defined $descr){
|
||||
die "Are you sure you got the right community string and version?\nCan't fetch layers or description.\n";
|
||||
if ( !defined $layers || !defined $descr ) {
|
||||
die
|
||||
"Are you sure you got the right community string and version?\nCan't fetch layers or description.\n";
|
||||
}
|
||||
|
||||
print "Fetching global info...\n\n";
|
||||
print "\nFetching base info...\n\n";
|
||||
|
||||
my @globals = qw/description uptime contact name location layers ports mac serial
|
||||
ps1_type ps2_type ps1_status ps2_status fan slots vendor os os_ver/;
|
||||
my @base_fns = qw/vendor model os os_ver description contact location
|
||||
layers mac serial/;
|
||||
|
||||
foreach my $global (@globals){
|
||||
test_global($dev,$global);
|
||||
foreach my $fn (@base_fns) {
|
||||
test_global( $dev, $fn );
|
||||
}
|
||||
|
||||
print "\nFetching interface info...\n\n";
|
||||
|
||||
my @fns = qw/interfaces i_type i_ignore i_description i_mtu i_speed i_mac i_up
|
||||
i_up_admin i_name i_duplex i_duplex_admin i_stp_state
|
||||
i_lastchange/;
|
||||
i_vlan i_pvid i_lastchange/;
|
||||
|
||||
foreach my $fn (@fns) {
|
||||
test_fn( $dev, $fn );
|
||||
}
|
||||
|
||||
print "\nTesting Misc...\n\n";
|
||||
my @misc = qw/v_name v_port/;
|
||||
foreach my $fn (@misc){
|
||||
print "\nFetching VLAN info...\n\n";
|
||||
|
||||
my @vlan = qw/v_index v_name/;
|
||||
|
||||
foreach my $fn (@vlan) {
|
||||
test_fn( $dev, $fn );
|
||||
}
|
||||
|
||||
foreach my $fn (@Dump) {
|
||||
test_fn($dev,$fn) unless $Dumped{$fn};
|
||||
print "\nFetching topology info...\n\n";
|
||||
|
||||
my @topo = qw/c_if c_ip c_port c_id c_platform/;
|
||||
|
||||
foreach my $fn (@topo) {
|
||||
test_fn( $dev, $fn );
|
||||
}
|
||||
|
||||
print "\nFetching module info...\n\n";
|
||||
|
||||
my @modules = qw/e_descr e_type e_parent e_name e_class e_pos e_hwver
|
||||
e_fwver e_swver e_model e_serial e_fru/;
|
||||
|
||||
foreach my $fn (@modules) {
|
||||
test_fn( $dev, $fn );
|
||||
}
|
||||
|
||||
foreach my $fn (@dump) {
|
||||
if ( !$dumped{$fn} ) { test_fn( $dev, $fn ) }
|
||||
}
|
||||
|
||||
#--------------------------------
|
||||
|
||||
sub test_global {
|
||||
my $dev = shift;
|
||||
my $info = shift;
|
||||
my $method = shift;
|
||||
|
||||
my $value;
|
||||
eval {
|
||||
$value = $dev->$method();
|
||||
};
|
||||
my $value = $info->$method();
|
||||
|
||||
if ($@){
|
||||
my $err = $@;
|
||||
$err =~ s/[[:cntrl:]]+/ /g;
|
||||
printf "%-20s Blew up. $err\n",$method;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unless (defined $value){
|
||||
if ( !defined $value ) {
|
||||
printf "%-20s Does not exist.\n", $method;
|
||||
return 0;
|
||||
}
|
||||
$value =~ s/[[:cntrl:]]+/ /g;
|
||||
$value =~ s/[[:cntrl:]]+/ /gx;
|
||||
if ( length $value > 60 ) {
|
||||
$value = substr($value,0,60);
|
||||
$value = substr $value, 0, 60;
|
||||
$value .= '...';
|
||||
}
|
||||
printf "%-20s %s \n", $method, $value;
|
||||
@@ -148,39 +193,29 @@ sub test_global {
|
||||
}
|
||||
|
||||
sub test_fn {
|
||||
my $dev = shift;
|
||||
my $info = shift;
|
||||
my $method = shift;
|
||||
|
||||
my $results;
|
||||
|
||||
eval {
|
||||
$results = $dev->$method();
|
||||
};
|
||||
|
||||
if ($@){
|
||||
my $err = $@;
|
||||
$err =~ s/\n/ /g;
|
||||
printf "%-20s Blew up. $err\n",$method;
|
||||
return 0;
|
||||
}
|
||||
my $results = $info->$method();
|
||||
|
||||
# If accidentally called on a global, pass it along nicely.
|
||||
if (defined($results) and !ref($results)) {
|
||||
if ( defined $results && !ref $results ) {
|
||||
return test_global( $dev, $method );
|
||||
}
|
||||
unless (defined $results and scalar keys %$results) {
|
||||
if ( !defined $results && !scalar keys %{$results} ) {
|
||||
printf "%-20s Empty Results.\n", $method;
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf "%-20s %d rows.\n",$method, scalar(keys %$results);
|
||||
if (grep(/^$method$/,@Dump)) {
|
||||
$Dumped{$method} = 1;
|
||||
foreach my $iid (keys %$results){
|
||||
printf "%-20s %d rows.\n", $method, scalar keys %{$results};
|
||||
if ( grep {/^$method$/x} @dump ) {
|
||||
$dumped{$method} = 1;
|
||||
foreach my $iid ( keys %{$results} ) {
|
||||
print " $iid : ";
|
||||
if ( ref( $results->{$iid} ) eq 'ARRAY' ) {
|
||||
print "[ ", join(", ", @{$results->{$iid}}), " ]";
|
||||
} else {
|
||||
print '[ ', join( ', ', @{ $results->{$iid} } ), ' ]';
|
||||
}
|
||||
else {
|
||||
print $results->{$iid};
|
||||
}
|
||||
print "\n";
|
||||
@@ -189,20 +224,105 @@ sub test_fn {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
print << "end_usage";
|
||||
__END__
|
||||
|
||||
test_class - Test a device against an SNMP::Info class
|
||||
-c --class Layer2::Catalyst
|
||||
-d --dev myswitch
|
||||
-s --comm public
|
||||
-v --ver 2
|
||||
-p --print i_blah
|
||||
-p --print i_blah2
|
||||
-x --debug debugging flag
|
||||
-n --nobulk disable bulkwalk
|
||||
-m --mibdirs directory (repeat as needed)
|
||||
=head1 NAME
|
||||
|
||||
end_usage
|
||||
exit;
|
||||
}
|
||||
test_class.pl - Test a device against an SNMP::Info class.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Eric Miller
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
test_class.pl [options]
|
||||
|
||||
Options:
|
||||
|
||||
-c|class SNMP::Info class to use, Layer2::Catalyst
|
||||
-d|dev Device
|
||||
-s|comm SNMP community
|
||||
-v|ver SNMP version
|
||||
-p|print Print values
|
||||
-x|debug Debugging flag
|
||||
-i|ignore Ignore Net-SNMP configuration file
|
||||
-m|mibdir Directory containing MIB Files
|
||||
-n|nobulk Disable bulkwalk
|
||||
-h|?|help Brief help message
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<-class>
|
||||
|
||||
Specific SNMP::Info class to use. Defaults to SNMP::Info if no specific
|
||||
class provided.
|
||||
|
||||
-class Layer2::Catalyst
|
||||
|
||||
=item B<-dev>
|
||||
|
||||
Device to test against. No default and a mandatory option.
|
||||
|
||||
-dev 1.2.3.4
|
||||
|
||||
=item B<-comm>
|
||||
|
||||
SNMP community string. No default and a mandatory option.
|
||||
|
||||
-comm public
|
||||
|
||||
=item B<-ver>
|
||||
|
||||
SNMP version. Default 2.
|
||||
|
||||
-ver 1
|
||||
|
||||
=item B<-print>
|
||||
|
||||
Print values of a class method rather than summarizing. May be repeated
|
||||
multiple times.
|
||||
|
||||
-print i_description -print i_type
|
||||
|
||||
=item B<-debug>
|
||||
|
||||
Turns on SNMP::Info debug.
|
||||
|
||||
-debug
|
||||
|
||||
=item B<-ignore >
|
||||
|
||||
Ignore Net-SNMP configuration file snmp.conf. If this used mibdirs must be
|
||||
provided.
|
||||
|
||||
-ignore
|
||||
|
||||
=item B<-mibdir>
|
||||
|
||||
Directory containing MIB Files. Multiple directories should be separated by a
|
||||
colon ':'.
|
||||
|
||||
-mibdir /usr/local/share/snmp/mibs/rfc:/usr/local/share/snmp/mibs/net-snmp
|
||||
|
||||
=item B<-nobulk >
|
||||
|
||||
Disable SNMP bulkwalk. Default bulkwalk is on and utilized with version 2.
|
||||
|
||||
-nobulk
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print help message and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<test_class.pl> will test a device against a specfied SNMP::Info class.
|
||||
This allows debugging and testing of live devices to include validating
|
||||
device support with existing classes.
|
||||
|
||||
=cut
|
||||
|
||||
Reference in New Issue
Block a user