diff --git a/lib/App/Netdisco/Transport/SNMP.pm b/lib/App/Netdisco/Transport/SNMP.pm index 04f3b1a4..fa397c08 100644 --- a/lib/App/Netdisco/Transport/SNMP.pm +++ b/lib/App/Netdisco/Transport/SNMP.pm @@ -1,6 +1,8 @@ package App::Netdisco::Transport::SNMP; use Dancer qw/:syntax :script/; +use Dancer::Plugin::DBIC 'schema'; + use App::Netdisco::Util::SNMP 'get_communities'; use App::Netdisco::Util::Device 'get_device'; use App::Netdisco::Util::Permission ':all'; @@ -9,6 +11,7 @@ use SNMP::Info; use Try::Tiny; use Module::Load (); use Path::Class 'dir'; +use NetAddr::IP::Lite ':lower'; use base 'Dancer::Object::Singleton'; @@ -61,6 +64,34 @@ sub reader_for { = _snmp_connect_generic('read', $device, $useclass)); } +=head1 test_connection( $ip ) + +Similar to C but will use the literal IP address passed, and does +not support specifying the device class. The purpose is to test the SNMP +connectivity to the device before a renumber. + +Attempts to have no side effect, however there will be a stored SNMP +authentication hint (tag) in the database if the connection is successful. + +Returns C if the connection fails. + +=cut + +sub test_connection { + my ($class, $ip) = @_; + my $addr = NetAddr::IP::Lite->new($ip) or return undef; + # avoid renumbering to localhost loopbacks + return undef if $addr->addr eq '0.0.0.0' + or check_acl_no($addr->addr, 'group:__LOCAL_ADDRESSES__'); + my $device = schema('netdisco')->resultset('Device') + ->new_result({ ip => $addr->addr }) or return undef; + my $readers = $class->instance->readers or return undef; + return $readers->{$device->ip} if exists $readers->{$device->ip}; + debug sprintf 'snmp reader cache warm: [%s]', $device->ip; + return ($readers->{$device->ip} + = _snmp_connect_generic('read', $device, $useclass)); +} + =head1 writer_for( $ip, $useclass? ) Same as C but uses the read-write community strings from the diff --git a/lib/App/Netdisco/Util/SNMP.pm b/lib/App/Netdisco/Util/SNMP.pm index 832cd958..f75dcf73 100644 --- a/lib/App/Netdisco/Util/SNMP.pm +++ b/lib/App/Netdisco/Util/SNMP.pm @@ -1,6 +1,7 @@ package App::Netdisco::Util::SNMP; use Dancer qw/:syntax :script/; +use App::Netdisco::Util::DNS 'hostname_from_ip'; use App::Netdisco::Util::Permission ':all'; use base 'Exporter'; @@ -138,7 +139,8 @@ sub get_communities { # clean the community table of obsolete tags eval { $device->community->update({$tag_name => undef}) } - if not $stored_tag or !exists $seen_tags->{ $stored_tag }; + if $device->in_storage + and (not $stored_tag or !exists $seen_tags->{ $stored_tag }); return ( @communities, @$config ); } @@ -147,7 +149,7 @@ sub _get_external_community { my ($device, $mode) = @_; my $cmd = setting('get_community'); my $ip = $device->ip; - my $host = $device->dns || $ip; + my $host = ($device->dns || hostname_from_ip($ip) || $ip); if (defined $cmd and length $cmd) { # replace variables diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/CanonicalIP.pm b/lib/App/Netdisco/Worker/Plugin/Discover/CanonicalIP.pm index f6b86d71..105f4185 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/CanonicalIP.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/CanonicalIP.pm @@ -22,7 +22,7 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { my $revofname = ipv4_from_hostname($snmp->name); if (setting('reverse_sysname') and $revofname) { - if ($snmp->snmp_connect_ip( $new_ip )) { + if (App::Netdisco::Transport::SNMP->test_connection( $new_ip )) { $new_ip = $revofname; } else { @@ -46,8 +46,7 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { if (check_acl_only($device, $key) and check_acl_only($alias, $map->{$key})) { - # if ($snmp->snmp_connect_ip( $alias->alias )) { FIXME - if (App::Netdisco::Transport::SNMP->reader_for( $alias->alias )) { + if (App::Netdisco::Transport::SNMP->test_connection( $alias->alias )) { $new_ip = $alias->alias; last ALIAS; }