diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/Neighbors.pm b/lib/App/Netdisco/Worker/Plugin/Discover/Neighbors.pm index 570b951b..16ccb9a7 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/Neighbors.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/Neighbors.pm @@ -127,6 +127,10 @@ sub store_neighbors { my $c_id = $snmp->c_id; my $c_platform = $snmp->c_platform; + # cache the device ports to save hitting the database for many single rows + my $device_ports = vars->{'device_ports'} + || { map {($_->port => $_)} $device->ports->all }; + # v4 and v6 neighbor tables my $c_ip = ($snmp->c_ip || {}); my %c_ipv6 = %{ ($snmp->can('hasLLDP') and $snmp->hasLLDP) @@ -144,9 +148,9 @@ sub store_neighbors { next; } - my $port = $interfaces->{ $c_if->{$entry} }; - my $portrow = schema('netdisco')->resultset('DevicePort') - ->single({ip => $device->ip, port => $port}); + # WRT #475 this is SAFE because we check against known ports below + my $port = $interfaces->{ $c_if->{$entry} } or next; + my $portrow = $device_ports->{$port}; if (!defined $portrow) { info sprintf ' [%s] neigh - local port %s not in database!', diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/PortPower.pm b/lib/App/Netdisco/Worker/Plugin/Discover/PortPower.pm index c355224e..8fc2e34b 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/PortPower.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/PortPower.pm @@ -32,6 +32,10 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { }; } + # cache the device ports to save hitting the database for many single rows + my $device_ports = vars->{'device_ports'} + || { map {($_->port => $_)} $device->ports->all }; + my $interfaces = $snmp->interfaces; my $p_ifindex = $snmp->peth_port_ifindex; my $p_admin = $snmp->peth_port_admin; @@ -42,11 +46,16 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { # build device port power info suitable for DBIC my @portpower; foreach my $entry (keys %$p_ifindex) { - my $port = $interfaces->{ $p_ifindex->{$entry} }; - next unless $port; + # WRT #475 this is SAFE because we check against known ports below + my $port = $interfaces->{ $p_ifindex->{$entry} } or next; + + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] power - local port %s not in database!', + $device->ip, $port; + next; + } my ($module) = split m/\./, $entry; - push @portpower, { port => $port, module => $module, diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/PortProperties.pm b/lib/App/Netdisco/Worker/Plugin/Discover/PortProperties.pm index 1680feac..8693e657 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/PortProperties.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/PortProperties.pm @@ -21,10 +21,20 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { my $interfaces = $snmp->interfaces || {}; my %properties = (); + # cache the device ports to save hitting the database for many single rows + my $device_ports = vars->{'device_ports'} + || { map {($_->port => $_)} $device->ports->all }; + my $raw_speed = $snmp->i_speed_raw || {}; foreach my $idx (keys %$raw_speed) { my $port = $interfaces->{$idx} or next; + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] properties/speed - local port %s not in database!', + $device->ip, $port; + next; + } + $properties{ $port }->{raw_speed} = $raw_speed->{$idx}; } @@ -32,6 +42,12 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { foreach my $idx (keys %$err_cause) { my $port = $interfaces->{$idx} or next; + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] properties/errdis - local port %s not in database!', + $device->ip, $port; + next; + } + $properties{ $port }->{error_disable_cause} = $err_cause->{$idx}; } @@ -39,6 +55,12 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { foreach my $idx (keys %$faststart) { my $port = $interfaces->{$idx} or next; + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] properties/faststart - local port %s not in database!', + $device->ip, $port; + next; + } + $properties{ $port }->{faststart} = $faststart->{$idx}; } @@ -54,6 +76,11 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { foreach my $idx (keys %$c_if) { my $port = $interfaces->{ $c_if->{$idx} } or next; + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] properties/lldpcap - local port %s not in database!', + $device->ip, $port; + next; + } my $remote_cap = $c_cap->{$idx} || []; my $remote_type = Encode::decode('UTF-8', $c_platform->{$idx} || ''); diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm b/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm index f2537ca7..f10808fb 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm @@ -252,6 +252,10 @@ register_worker({ phase => 'early', driver => 'snmp' }, sub { $device->update_or_insert(undef, {for => 'update'}); $device->ports->populate([values %interfaces]); + # cache for later phases of the discovery + vars->{'device_ports'} = { map {($_->port => $_)} + $device->ports->search(undef, {columns => 'port'})->all }; + return Status->info(sprintf ' [%s] interfaces - added %d new interfaces', $device->ip, scalar values %interfaces); }); diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/VLANs.pm b/lib/App/Netdisco/Worker/Plugin/Discover/VLANs.pm index 0445661e..f5b1d734 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/VLANs.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/VLANs.pm @@ -33,6 +33,10 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { }; } + # cache the device ports to save hitting the database for many single rows + my $device_ports = vars->{'device_ports'} + || { map {($_->port => $_)} $device->ports->all }; + my $i_vlan = $snmp->i_vlan; my $i_vlan_membership = $snmp->i_vlan_membership; my $i_vlan_type = $snmp->i_vlan_type; @@ -42,8 +46,13 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { my @portvlans = (); foreach my $entry (keys %$i_vlan_membership) { my %port_vseen = (); - my $port = $interfaces->{$entry}; - next unless defined $port; + my $port = $interfaces->{$entry} or next; + + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] vlans - local port %s not in database!', + $device->ip, $port; + next; + } my $type = $i_vlan_type->{$entry}; diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/Wireless.pm b/lib/App/Netdisco/Worker/Plugin/Discover/Wireless.pm index a86640af..b80fbc8c 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/Wireless.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/Wireless.pm @@ -18,6 +18,10 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { my $ssidlist = $snmp->i_ssidlist; return unless scalar keys %$ssidlist; + # cache the device ports to save hitting the database for many single rows + my $device_ports = vars->{'device_ports'} + || { map {($_->port => $_)} $device->ports->all }; + my $interfaces = $snmp->interfaces; my $ssidbcast = $snmp->i_ssidbcast; my $ssidmac = $snmp->i_ssidmac; @@ -36,6 +40,12 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { next; } + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] wireless - local port %s not in database!', + $device->ip, $port; + next; + } + push @ssids, { port => $port, ssid => $ssidlist->{$entry}, @@ -64,6 +74,12 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub { next; } + if (!defined $device_ports->{$port}) { + info sprintf ' [%s] wireless - local port %s not in database!', + $device->ip, $port; + next; + } + push @channels, { port => $port, channel => $channel->{$entry}, diff --git a/lib/App/Netdisco/Worker/Plugin/Macsuck/Nodes.pm b/lib/App/Netdisco/Worker/Plugin/Macsuck/Nodes.pm index b46e78a4..ba8da6e9 100644 --- a/lib/App/Netdisco/Worker/Plugin/Macsuck/Nodes.pm +++ b/lib/App/Netdisco/Worker/Plugin/Macsuck/Nodes.pm @@ -299,6 +299,8 @@ sub walk_fwtable { next; } + # WRT #475 this is SAFE because we check against known ports below + # but we do need the SNMP interface IDs to get the job done my $port = $interfaces->{$iid}; unless (defined $port) { @@ -318,6 +320,7 @@ sub walk_fwtable { # this uses the cached $ports resultset to limit hits on the db my $device_port = $device_ports->{$port}; + # WRT #475 ... see? :-) unless (defined $device_port) { debug sprintf ' [%s] macsuck %s - port %s is not in database - skipping.',