update test_class.pl utility to allow ignore of snmp.conf and test summarize more standard class methods
This commit is contained in:
384
t/test_class.pl
384
t/test_class.pl
@@ -1,186 +1,221 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl
|
||||||
#
|
#
|
||||||
# test_class.pl
|
# 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 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
|
# Default Values
|
||||||
$Class = '';
|
my $class = $EMPTY;
|
||||||
$Dev = '';
|
my @dump = ();
|
||||||
$Comm = '';
|
my $debug = 0;
|
||||||
$Ver = 2;
|
my $device = '';
|
||||||
@Dump = ();
|
my $comm = '';
|
||||||
$Debug = 0;
|
my $ver = 2;
|
||||||
$NoBulk = 0;
|
my $ignore = 0;
|
||||||
|
my $help = 0;
|
||||||
|
my $nobulk = 0;
|
||||||
|
my $mibdirs;
|
||||||
|
my %dumped;
|
||||||
|
|
||||||
GetOptions ('c|class=s' => \$Class,
|
GetOptions(
|
||||||
'd|dev=s' => \$Dev,
|
'c|class=s' => \$class,
|
||||||
's|comm=s' => \$Comm,
|
'd|dev=s' => \$device,
|
||||||
'v|ver=i' => \$Ver,
|
's|comm=s' => \$comm,
|
||||||
'h|help' => \&usage,
|
'v|ver=i' => \$ver,
|
||||||
'p|print=s' => \@Dump,
|
'i|ignore' => \$ignore,
|
||||||
'x|debug+' => \$Debug,
|
'p|print=s' => \@dump,
|
||||||
'n|nobulk' => \$NoBulk,
|
'x|debug+' => \$debug,
|
||||||
'm|mibdir=s@' => \$MibDirs,
|
'm|mibdir=s' => \$mibdirs,
|
||||||
);
|
'n|nobulk' => \$nobulk,
|
||||||
|
'h|?|help' => sub { pod2usage(1); },
|
||||||
|
);
|
||||||
|
|
||||||
&usage unless ($Dev and $Comm);
|
unless ( $device and $comm ) {
|
||||||
|
pod2usage(2);
|
||||||
# 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"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$Class = $Class ? "SNMP::Info::$Class" : 'SNMP::Info';
|
if ( $ignore && !defined $mibdirs ) {
|
||||||
eval "require $Class;";
|
print "mibdirs must be provided if ignoring snmp.conf \n\n";
|
||||||
if ($@) {
|
pod2usage(1);
|
||||||
die "Can't load Class specified : $Class.\n\n$@\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $class_ver = 'undef';
|
if ($ignore) { local $ENV{'SNMPCONFPATH'} = $EMPTY }
|
||||||
{ no strict 'refs';
|
if ($ignore) { local $ENV{'MIBDIRS'} = "$mibdirs" }
|
||||||
$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;
|
|
||||||
|
|
||||||
%args = ();
|
if ( defined $mibdirs ) {
|
||||||
if ($NoBulk) {
|
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;
|
$args{BulkWalk} = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $dev = new $Class( 'AutoSpecify' => 0,
|
my $dev = $class->new(
|
||||||
|
'AutoSpecify' => 0,
|
||||||
'AutoVerBack' => 0,
|
'AutoVerBack' => 0,
|
||||||
'Version' => $Ver,
|
'Debug' => $debug,
|
||||||
'Debug' => $Debug,
|
'MibDirs' => $mibdirs,
|
||||||
'DestHost' => $Dev,
|
'Version' => $ver,
|
||||||
'Community' => $Comm,
|
'DestHost' => $device,
|
||||||
'MibDirs' => $MibDirs,
|
'Community' => $comm,
|
||||||
%args
|
%args
|
||||||
) or die "\n";
|
) or die "\n";
|
||||||
|
|
||||||
print "Connected to $Dev.\n";
|
print "Connected to $device.\n";
|
||||||
print "Detected Class: ", $dev->device_type(), "\n";
|
print 'Detected Class: ', $dev->device_type(), "\n";
|
||||||
print "Using Class: $Class (-c to change)\n";
|
print "Using Class: $class (-c to change)\n";
|
||||||
|
|
||||||
my $layers = $dev->layers();
|
my $layers = $dev->layers();
|
||||||
my $descr = $dev->description();
|
my $descr = $dev->description();
|
||||||
|
|
||||||
unless (defined $layers or defined $descr){
|
if ( !defined $layers || !defined $descr ) {
|
||||||
die "Are you sure you got the right community string and version?\nCan't fetch layers or description.\n";
|
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
|
my @base_fns = qw/vendor model os os_ver description contact location
|
||||||
ps1_type ps2_type ps1_status ps2_status fan slots vendor os os_ver/;
|
layers mac serial/;
|
||||||
|
|
||||||
foreach my $global (@globals){
|
foreach my $fn (@base_fns) {
|
||||||
test_global($dev,$global);
|
test_global( $dev, $fn );
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\nFetching interface info...\n\n";
|
print "\nFetching interface info...\n\n";
|
||||||
|
|
||||||
my @fns = qw/interfaces i_type i_ignore i_description i_mtu i_speed i_mac i_up
|
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_up_admin i_name i_duplex i_duplex_admin i_stp_state
|
||||||
i_lastchange/;
|
i_vlan i_pvid i_lastchange/;
|
||||||
|
|
||||||
foreach my $fn (@fns){
|
foreach my $fn (@fns) {
|
||||||
test_fn($dev,$fn);
|
test_fn( $dev, $fn );
|
||||||
}
|
}
|
||||||
|
|
||||||
print "\nTesting Misc...\n\n";
|
print "\nFetching VLAN info...\n\n";
|
||||||
my @misc = qw/v_name v_port/;
|
|
||||||
foreach my $fn (@misc){
|
my @vlan = qw/v_index v_name/;
|
||||||
test_fn($dev,$fn);
|
|
||||||
|
foreach my $fn (@vlan) {
|
||||||
|
test_fn( $dev, $fn );
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach my $fn (@Dump) {
|
print "\nFetching topology info...\n\n";
|
||||||
test_fn($dev,$fn) unless $Dumped{$fn};
|
|
||||||
|
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 {
|
sub test_global {
|
||||||
my $dev = shift;
|
my $info = shift;
|
||||||
my $method = shift;
|
my $method = shift;
|
||||||
|
|
||||||
my $value;
|
my $value = $info->$method();
|
||||||
eval {
|
|
||||||
$value = $dev->$method();
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@){
|
if ( !defined $value ) {
|
||||||
my $err = $@;
|
printf "%-20s Does not exist.\n", $method;
|
||||||
$err =~ s/[[:cntrl:]]+/ /g;
|
|
||||||
printf "%-20s Blew up. $err\n",$method;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
$value =~ s/[[:cntrl:]]+/ /gx;
|
||||||
unless (defined $value){
|
if ( length $value > 60 ) {
|
||||||
printf "%-20s Does not exist.\n",$method;
|
$value = substr $value, 0, 60;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
$value =~ s/[[:cntrl:]]+/ /g;
|
|
||||||
if (length $value > 60) {
|
|
||||||
$value = substr($value,0,60);
|
|
||||||
$value .= '...';
|
$value .= '...';
|
||||||
}
|
}
|
||||||
printf "%-20s %s \n",$method,$value;
|
printf "%-20s %s \n", $method, $value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub test_fn {
|
sub test_fn {
|
||||||
my $dev = shift;
|
my $info = shift;
|
||||||
my $method = shift;
|
my $method = shift;
|
||||||
|
|
||||||
my $results;
|
my $results = $info->$method();
|
||||||
|
|
||||||
eval {
|
|
||||||
$results = $dev->$method();
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@){
|
|
||||||
my $err = $@;
|
|
||||||
$err =~ s/\n/ /g;
|
|
||||||
printf "%-20s Blew up. $err\n",$method;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# If accidentally called on a global, pass it along nicely.
|
# 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);
|
return test_global( $dev, $method );
|
||||||
}
|
}
|
||||||
unless (defined $results and scalar keys %$results) {
|
if ( !defined $results && !scalar keys %{$results} ) {
|
||||||
printf "%-20s Empty Results.\n",$method;
|
printf "%-20s Empty Results.\n", $method;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf "%-20s %d rows.\n",$method, scalar(keys %$results);
|
printf "%-20s %d rows.\n", $method, scalar keys %{$results};
|
||||||
if (grep(/^$method$/,@Dump)) {
|
if ( grep {/^$method$/x} @dump ) {
|
||||||
$Dumped{$method} = 1;
|
$dumped{$method} = 1;
|
||||||
foreach my $iid (keys %$results){
|
foreach my $iid ( keys %{$results} ) {
|
||||||
print " $iid : ";
|
print " $iid : ";
|
||||||
if (ref($results->{$iid}) eq 'ARRAY') {
|
if ( ref( $results->{$iid} ) eq 'ARRAY' ) {
|
||||||
print "[ ", join(", ", @{$results->{$iid}}), " ]";
|
print '[ ', join( ', ', @{ $results->{$iid} } ), ' ]';
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
print $results->{$iid};
|
print $results->{$iid};
|
||||||
}
|
}
|
||||||
print "\n";
|
print "\n";
|
||||||
@@ -189,20 +224,105 @@ sub test_fn {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub usage {
|
__END__
|
||||||
print << "end_usage";
|
|
||||||
|
|
||||||
test_class - Test a device against an SNMP::Info class
|
=head1 NAME
|
||||||
-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)
|
|
||||||
|
|
||||||
end_usage
|
test_class.pl - Test a device against an SNMP::Info class.
|
||||||
exit;
|
|
||||||
}
|
=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