This commit is contained in:
Christian Ramseyer
2019-03-05 10:08:29 +01:00
24 changed files with 228 additions and 142 deletions

View File

@@ -46,7 +46,7 @@ Module::Build->new(
'JSON' => '2.90',
'JSON::XS' => '3.01',
'List::Util' => '1.49',
'List::MoreUtils' => '0.33',
'List::MoreUtils' => '0.428',
'MIME::Base64' => '3.13',
'Module::Load' => '0.32',
'Moo' => '1.001000',
@@ -72,7 +72,7 @@ Module::Build->new(
'Starman' => '0.4008',
'Storable' => '0',
'Sys::SigAction' => '0',
'SNMP::Info' => '3.64',
'SNMP::Info' => '3.65',
'SQL::Abstract' => '1.85',
'SQL::Translator' => '0.11024',
'Template' => '2.24',

40
Changes
View File

@@ -1,3 +1,43 @@
2.040006 - 2019-03-04
[BUG FIXES]
* #527 update List::MoreUtils version requirement
2.040005 - 2019-03-04
[BUG FIXES]
* #526 fix discover syntax bug
2.040004 - 2019-03-03
[NEW FEATURES]
* #510 store ifindex in Device Port Properties table (rc9000)
* new discover_waps and discover_phones boolean settings (ollyg)
[ENHANCEMENTS]
* #428 Port-Channels now showing in netmap (ollyg)
* #490 use new LLDP capability checks for ports having phones (ollyg)
* #494 update Cisco ASA ssh collector (stromsoe)
[BUG FIXES]
* #492 Port Control incorrectly uses VLAN config check (inphobia)
* #493 HTML tag fix (inphobia)
* #498 Map with VLAN filter omits unconnected devices (ollyg)
* #499 netdisco-do renumber reports wrong ip (inphobia)
* #500 no more duplicate entries in vlan filter (ollyg)
* #505 renumbering device missed a few tables (ollyg)
* #512 fix regression in phone/wap discovery exclusion (ollyg)
* #514 ipinventory report returns consistent data (inphobia)
* #520 make sure aggports have a master<->slave (ollyg)
* #521 Search Node Date Range not working (ollyg)
* #522 TypeAhead.pm can reference empty data (inphobia)
* fix bug showing no nodes when only one matches in netmap (ollyg)
2.040003 - 2019-01-18
[NEW FEATURES]

View File

@@ -364,6 +364,7 @@ share/schema_versions/App-Netdisco-DB-5-6-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-50-51-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-51-52-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-52-53-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-53-54-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-6-7-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-7-8-PostgreSQL.sql
share/schema_versions/App-Netdisco-DB-8-9-PostgreSQL.sql

View File

@@ -60,7 +60,7 @@
"IO::Socket::SSL" : "2.048",
"JSON" : "2.90",
"JSON::XS" : "3.01",
"List::MoreUtils" : "0.33",
"List::MoreUtils" : "0.428",
"List::Util" : "1.49",
"MCE" : "1.703",
"MIME::Base64" : "3.13",
@@ -81,7 +81,7 @@
"Plack::Middleware::ReverseProxy" : "0.15",
"Pod::Usage" : "0",
"Role::Tiny" : "1.002005",
"SNMP::Info" : "3.64",
"SNMP::Info" : "3.65",
"SQL::Abstract" : "1.85",
"SQL::Translator" : "0.11024",
"Scope::Guard" : "0",
@@ -118,7 +118,7 @@
"provides" : {
"App::Netdisco" : {
"file" : "lib/App/Netdisco.pm",
"version" : "2.040003"
"version" : "2.040006"
},
"App::Netdisco::AnyEvent::Nbtstat" : {
"file" : "lib/App/Netdisco/AnyEvent/Nbtstat.pm"
@@ -140,7 +140,7 @@
},
"App::Netdisco::DB" : {
"file" : "lib/App/Netdisco/DB.pm",
"version" : "53"
"version" : "54"
},
"App::Netdisco::DB::ExplicitLocking" : {
"file" : "lib/App/Netdisco/DB/ExplicitLocking.pm"
@@ -800,6 +800,6 @@
"x_IRC" : "irc://irc.freenode.org/#netdisco",
"x_MailingList" : "https://lists.sourceforge.net/lists/listinfo/netdisco-users"
},
"version" : "2.040003",
"version" : "2.040006",
"x_serialization_backend" : "JSON::PP version 2.97001"
}

View File

@@ -22,7 +22,7 @@ name: App-Netdisco
provides:
App::Netdisco:
file: lib/App/Netdisco.pm
version: '2.040003'
version: '2.040006'
App::Netdisco::AnyEvent::Nbtstat:
file: lib/App/Netdisco/AnyEvent/Nbtstat.pm
App::Netdisco::Backend::Job:
@@ -37,7 +37,7 @@ provides:
file: lib/App/Netdisco/Configuration.pm
App::Netdisco::DB:
file: lib/App/Netdisco/DB.pm
version: '53'
version: '54'
App::Netdisco::DB::ExplicitLocking:
file: lib/App/Netdisco/DB/ExplicitLocking.pm
App::Netdisco::DB::Result::Admin:
@@ -497,7 +497,7 @@ requires:
IO::Socket::SSL: '2.048'
JSON: '2.90'
JSON::XS: '3.01'
List::MoreUtils: '0.33'
List::MoreUtils: '0.428'
List::Util: '1.49'
MCE: '1.703'
MIME::Base64: '3.13'
@@ -518,7 +518,7 @@ requires:
Plack::Middleware::ReverseProxy: '0.15'
Pod::Usage: '0'
Role::Tiny: '1.002005'
SNMP::Info: '3.64'
SNMP::Info: '3.65'
SQL::Abstract: '1.85'
SQL::Translator: '0.11024'
Scope::Guard: '0'
@@ -549,5 +549,5 @@ resources:
homepage: http://netdisco.org/
license: http://opensource.org/licenses/bsd-license.php
repository: https://github.com/netdisco/netdisco
version: '2.040003'
version: '2.040006'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'

View File

@@ -4,7 +4,7 @@ use strict;
use warnings;
use 5.010_000;
our $VERSION = '2.040003';
our $VERSION = '2.040006';
use App::Netdisco::Configuration;
=head1 NAME

View File

@@ -262,20 +262,27 @@ sub renumber {
foreach my $set (qw/
DeviceIp
DeviceModule
DevicePower
DeviceVlan
DevicePort
DevicePortLog
DevicePortPower
DevicePortProperties
DevicePortSsid
DevicePortVlan
DevicePortWireless
DevicePower
DeviceVlan
/) {
$schema->resultset($set)
->search({ip => $old_ip})
->update({ip => $new_ip});
}
$schema->resultset('DeviceSkip')
->search({device => $new_ip})->delete;
$schema->resultset('DeviceSkip')
->search({device => $old_ip})
->update({device => $new_ip});
$schema->resultset('DevicePort')
->search({remote_ip => $old_ip})
->update({remote_ip => $new_ip});

View File

@@ -22,8 +22,8 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
array_agg(dp.port) AS left_port,
array_agg(dp.name) AS left_descr,
count(dpp.*) AS aggports,
sum(COALESCE(dpp.raw_speed, 0)) AS aggspeed,
count(*) AS aggports,
di.ip AS right_ip,
rd.dns AS right_dns,
@@ -32,8 +32,14 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
array_agg(dp2.name) AS right_descr
FROM device_port dp
LEFT OUTER JOIN device_port_properties dpp USING (ip,
port)
LEFT OUTER JOIN device_port_properties dpp ON (
(dp.ip = dpp.ip) AND (dp.port = dpp.port)
AND (dp.type IS NULL
OR dp.type !~* '^(53|ieee8023adLag|propVirtual|l2vlan|l3ipvlan|135|136|137)\$')
AND (dp.is_master = 'false'
OR dp.slave_of IS NOT NULL) )
INNER JOIN device ld ON dp.ip = ld.ip
INNER JOIN device_ip di ON dp.remote_ip = di.alias
INNER JOIN device rd ON di.ip = rd.ip
@@ -45,12 +51,7 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
WHERE dp.remote_port IS NOT NULL
AND dp.port !~* 'vlan'
AND (dp.descr IS NULL
OR dp.descr !~* 'vlan')
AND (dp.type IS NULL
OR dp.type !~* '^(53|ieee8023adLag|propVirtual|l2vlan|l3ipvlan|135|136|137)\$')
AND (dp.is_master = 'false'
OR dp.slave_of IS NOT NULL)
AND (dp.descr IS NULL OR dp.descr !~* 'vlan')
GROUP BY left_ip,
left_dns,
@@ -58,6 +59,7 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
right_ip,
right_dns,
right_name )
SELECT *
FROM BothWays b
WHERE NOT EXISTS

View File

@@ -15,6 +15,7 @@ __PACKAGE__->result_source_instance->view_definition(<<'ENDSQL');
d.ip, d.name, d.dns,
p.port, p.name AS port_description,
p.remote_ip, p.remote_id, p.remote_type, p.remote_port,
dpp.remote_is_wap, dpp.remote_is_phone,
l.log AS comment,
a.log, a.finished
@@ -23,6 +24,7 @@ __PACKAGE__->result_source_instance->view_definition(<<'ENDSQL');
INNER JOIN device d USING (ip)
LEFT OUTER JOIN device_skip ds
ON ('discover' = ANY(ds.actionset) AND p.remote_ip = ds.device)
LEFT OUTER JOIN device_port_properties dpp USING (ip, port)
LEFT OUTER JOIN device_port_log l USING (ip, port)
LEFT OUTER JOIN admin a
ON (p.remote_ip = a.device AND a.action = 'discover')
@@ -58,6 +60,10 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 1 },
"remote_id",
{ data_type => "text", is_nullable => 1 },
"remote_is_wap",
{ data_type => "boolean", is_nullable => 1 },
"remote_is_phone",
{ data_type => "boolean", is_nullable => 1 },
"comment",
{ data_type => "text", is_nullable => 1 },
"log",

View File

@@ -47,16 +47,16 @@ sub with_times {
->search({},
{
'+columns' => {
uptime_age => \("replace(age(timestamp 'epoch' + uptime / 100 * interval '1 second', "
uptime_age => \("replace(age(timestamp 'epoch' + me.uptime / 100 * interval '1 second', "
."timestamp '1970-01-01 00:00:00-00')::text, 'mon', 'month')"),
first_seen_stamp => \"to_char(me.creation, 'YYYY-MM-DD HH24:MI')",
last_discover_stamp => \"to_char(last_discover, 'YYYY-MM-DD HH24:MI')",
last_macsuck_stamp => \"to_char(last_macsuck, 'YYYY-MM-DD HH24:MI')",
last_arpnip_stamp => \"to_char(last_arpnip, 'YYYY-MM-DD HH24:MI')",
last_discover_stamp => \"to_char(me.last_discover, 'YYYY-MM-DD HH24:MI')",
last_macsuck_stamp => \"to_char(me.last_macsuck, 'YYYY-MM-DD HH24:MI')",
last_arpnip_stamp => \"to_char(me.last_arpnip, 'YYYY-MM-DD HH24:MI')",
since_first_seen => \"extract(epoch from (age(now(), me.creation)))",
since_last_discover => \"extract(epoch from (age(now(), last_discover)))",
since_last_macsuck => \"extract(epoch from (age(now(), last_macsuck)))",
since_last_arpnip => \"extract(epoch from (age(now(), last_arpnip)))",
since_last_discover => \"extract(epoch from (age(now(), me.last_discover)))",
since_last_macsuck => \"extract(epoch from (age(now(), me.last_macsuck)))",
since_last_arpnip => \"extract(epoch from (age(now(), me.last_arpnip)))",
},
});
}

View File

@@ -10,7 +10,7 @@ our @EXPORT_OK = qw/
get_device
delete_device
renumber_device
match_devicetype
match_to_setting
is_discoverable is_discoverable_now
is_arpnipable is_arpnipable_now
is_macsuckable is_macsuckable_now
@@ -120,7 +120,7 @@ sub renumber_device {
schema('netdisco')->resultset('UserLog')->create({
username => session('logged_in_user'),
userip => scalar eval {request->remote_address},
event => (sprintf "Renumber device %s to %s", $device->ip, $new_ip),
event => (sprintf "Renumber device %s to %s", $ip, $new_ip),
});
$happy = 1;
@@ -129,7 +129,7 @@ sub renumber_device {
return $happy;
}
=head2 match_devicetype( $type, $setting_name )
=head2 match_to_setting( $type, $setting_name )
Given a C<$type> (which may be any text value), returns true if any of the
list of regular expressions in C<$setting_name> is matched, otherwise returns
@@ -137,7 +137,7 @@ false.
=cut
sub match_devicetype {
sub match_to_setting {
my ($type, $setting_name) = @_;
return 0 unless $type and $setting_name;
return (scalar grep {$type =~ m/$_/}
@@ -146,7 +146,7 @@ sub match_devicetype {
sub _bail_msg { debug $_[0]; return 0; }
=head2 is_discoverable( $ip, $device_type? )
=head2 is_discoverable( $ip, [$device_type, \@device_capabilities]? )
Given an IP address, returns C<true> if Netdisco on this host is permitted by
the local configuration to discover the device.
@@ -154,20 +154,32 @@ the local configuration to discover the device.
The configuration items C<discover_no> and C<discover_only> are checked
against the given IP.
If C<$device_type> is also given, then C<discover_no_type> will also be
checked.
If C<$device_type> is also given, then C<discover_no_type> will be checked.
Also respects C<discover_phones> and C<discover_waps> if either are set to
false.
Returns false if the host is not permitted to discover the target device.
=cut
sub is_discoverable {
my ($ip, $remote_type) = @_;
my ($ip, $remote_type, $remote_cap) = @_;
my $device = get_device($ip) or return 0;
$remote_type ||= '';
$remote_cap ||= [];
if (match_devicetype($remote_type, 'discover_no_type')) {
return _bail_msg("is_discoverable: $device matched discover_no_type");
}
return _bail_msg("is_discoverable: $device matches wap_platforms but discover_waps is not enabled")
if ((not setting('discover_waps')) and
(match_to_setting($remote_type, 'wap_platforms') or
scalar grep {match_to_setting($_, 'wap_capabilities')} @$remote_cap));
return _bail_msg("is_discoverable: $device matches phone_platforms but discover_phones is not enabled")
if ((not setting('discover_phones')) and
(match_to_setting($remote_type, 'phone_platforms') or
scalar grep {match_to_setting($_, 'phone_capabilities')} @$remote_cap));
return _bail_msg("is_discoverable: $device matched discover_no_type")
if (match_to_setting($remote_type, 'discover_no_type'));
return _bail_msg("is_discoverable: $device matched discover_no")
if check_acl_no($device, 'discover_no');

View File

@@ -7,7 +7,7 @@ use Dancer::Plugin::Auth::Extensible;
use URI ();
use URL::Encode 'url_params_mixed';
use App::Netdisco::Util::Device 'match_devicetype';
use App::Netdisco::Util::Device 'match_to_setting';
# build view settings for port connected nodes and devices
set('connected_properties' => [
@@ -20,7 +20,7 @@ hook 'before_template' => sub {
my $tokens = shift;
# allow checking of discoverability of remote connected device
$tokens->{has_snmp} = sub { not match_devicetype(shift, 'discover_no_type') };
$tokens->{has_snmp} = sub { not match_to_setting(shift, 'discover_no_type') };
my $defaults = var('sidebar_defaults')->{'device_ports'}
or return;

View File

@@ -27,6 +27,8 @@ get '/ajax/content/admin/undiscoveredneighbors' => require_role admin => sub {
# create a new row object to avoid hitting the DB in get_device()
my $dev = schema('netdisco')->resultset('Device')->new({ip => $r->{remote_ip}});
next unless is_discoverable( $dev, $r->{remote_type} );
next if (not setting('discover_waps')) and $r->{remote_is_wap};
next if (not setting('discover_phones')) and $r->{remote_is_phone};
push @discoverable_results, $r;
}
return unless scalar @discoverable_results;

View File

@@ -125,18 +125,13 @@ sub make_link_infostring {
(my $left_name = lc($link->{left_dns} || $link->{left_name} || $link->{left_ip})) =~ s/$domain$//;
(my $right_name = lc($link->{right_dns} || $link->{right_name} || $link->{right_ip})) =~ s/$domain$//;
if ($link->{aggports} == 1) {
return sprintf '<b>%s:%s</b> (%s)<br><b>%s:%s</b> (%s)',
$left_name, $link->{left_port}->[0],
($link->{left_descr}->[0] || 'no description'),
$right_name, $link->{right_port}->[0],
($link->{right_descr}->[0] || 'no description');
}
else {
return sprintf '<b>%s:(%s)</b><br><b>%s:(%s)</b>',
$left_name, join(',', @{$link->{left_port}}),
$right_name, join(',', @{$link->{right_port}});
}
my @zipped = List::MoreUtils::zip6
@{$link->{left_port}}, @{$link->{left_descr}},
@{$link->{right_port}}, @{$link->{right_descr}};
return join '<br><br>', map { sprintf '<b>%s:%s</b> (%s)<br><b>%s:%s</b> (%s)',
$left_name, $_->[0], ($_->[1] || 'no description'),
$right_name, $_->[2], ($_->[3] || 'no description') } @zipped;
}
ajax '/ajax/data/device/netmap' => require_login sub {
@@ -179,17 +174,6 @@ ajax '/ajax/data/device/netmap' => require_login sub {
]) : ())
}, { result_class => 'DBIx::Class::ResultClass::HashRefInflator' });
if ($vlan) {
$links = $links->search({
-or => [
{ 'left_vlans.vlan' => $vlan },
{ 'right_vlans.vlan' => $vlan },
],
}, {
join => [qw/left_vlans right_vlans/],
});
}
while (my $link = $links->next) {
push @{$data{'links'}}, {
FROMID => $link->{left_ip},
@@ -217,10 +201,19 @@ ajax '/ajax/data/device/netmap' => require_login sub {
join => 'throughput',
})->with_times;
# filter by vlan for all or neighbors only
if ($vlan) {
$devices = $devices->search(
{ 'vlans.vlan' => $vlan },
{ join => 'vlans' }
);
}
DEVICE: while (my $device = $devices->next) {
# if in neighbors or vlan mode then use %ok_dev to filter
next DEVICE if (($mapshow eq 'neighbors') or $vlan)
and (not $ok_dev{$device->ip});
# if in neighbors mode then use %ok_dev to filter
next DEVICE if ($device->ip ne $qdev->ip)
and ($mapshow eq 'neighbors')
and (not $ok_dev{$device->ip}); # showing only neighbors but no link
# if location picked then filter
next DEVICE if ((scalar @lgrplist) and ((!defined $device->location)

View File

@@ -25,25 +25,6 @@ get '/ajax/content/device/ports' => require_login sub {
if ($f) {
if (($prefer eq 'vlan') or (not $prefer and $f =~ m/^\d+$/)) {
return unless $f =~ m/^\d+$/;
if (param('invert')) {
$set = $set->search({
'me.vlan' => { '!=' => $f },
'port_vlans.vlan' => [
'-or' => { '!=' => $f }, { '=' => undef }
],
}, { join => 'port_vlans' });
}
else {
$set = $set->search({
-or => {
'me.vlan' => $f,
'port_vlans.vlan' => $f,
},
}, { join => 'port_vlans' });
}
return unless $set->count;
}
else {
if (param('partial')) {
@@ -120,7 +101,7 @@ get '/ajax/content/device/ports' => require_login sub {
# now begin to join tables depending on the selected columns/options
# get vlans on the port
# leave this query dormant (lazy) unless c_vmember is set
# leave this query dormant (lazy) unless c_vmember is set or vlan filtering
my $vlans = $set->search({}, {
select => [
'port',
@@ -131,7 +112,7 @@ get '/ajax/content/device/ports' => require_login sub {
group_by => 'me.port',
});
if (param('c_vmember')) {
if (param('c_vmember') or ($prefer eq 'vlan') or (not $prefer and $f =~ m/^\d+$/)) {
$vlans = { map {(
$_->port => {
# DBIC smart enough to work out this should be an arrayref :)
@@ -194,13 +175,37 @@ get '/ajax/content/device/ports' => require_login sub {
# also get remote LLDP inventory if asked for
$set = $set->with_remote_inventory if param('n_inventory');
# sort ports (empty set would be a 'no records' msg)
my $results = [ sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } $set->all ];
return unless scalar @$results;
# run query
my @results = $set->all;
# filter for tagged vlan using existing agg query,
# which is better than join inflation
if (($prefer eq 'vlan') or (not $prefer and $f =~ m/^\d+$/)) {
if (param('invert')) {
@results = grep {
(!defined $_->vlan or $_->vlan ne $f)
and
(0 == scalar grep {defined and $_ ne $f} @{ $vlans->{$_->port}->{vlan_set} })
} @results;
}
else {
@results = grep {
($_->vlan eq $f)
or
(scalar grep {defined and $_ eq $f} @{ $vlans->{$_->port}->{vlan_set} })
} @results;
}
}
# sort ports
@results = sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } @results;
# empty set would be a 'no records' msg
return unless scalar @results;
if (request->is_ajax) {
template 'ajax/device/ports.tt', {
results => $results,
results => \@results,
nodes => $nodes_name,
ips => $ips_name,
device => $device,
@@ -210,7 +215,7 @@ get '/ajax/content/device/ports' => require_login sub {
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/device/ports_csv.tt', {
results => $results,
results => \@results,
nodes => $nodes_name,
ips => $ips_name,
device => $device,

View File

@@ -110,12 +110,12 @@ get '/ajax/content/report/ipinventory' => require_login sub {
'ip', 'mac', 'dns', 'time_last', 'time_first',
'active', 'node', 'age'
],
order_by => [{-asc => 'ip'}, {-desc => 'active'}],
order_by => [{-asc => 'ip'}, {-desc => 'active'}, {-asc => 'node'}],
}
)->as_query;
my $rs;
if ( $start && $end ) {
if ( $start and $end ) {
$start = $start . ' 00:00:00';
$end = $end . ' 23:59:59';

View File

@@ -30,32 +30,48 @@ ajax '/ajax/content/search/node' => require_login sub {
if ( $start and $end ) {
$start = $start . ' 00:00:00';
$end = $end . ' 23:59:59';
if ($agenot) {
@times = (-or => [
time_first => [ { '<', $start }, undef ],
time_last => { '>', $end },
time_first => [ undef ],
time_last => [ { '<', $start }, { '>', $end } ]
]);
@wifitimes = (-or => [
time_last => { '<', $start },
time_last => { '>', $end },
time_first => [ undef ],
time_last => [ { '<', $start }, { '>', $end } ]
]);
@porttimes = (-or => [
creation => { '<', $start },
creation => { '>', $end },
creation => [ undef ],
creation => [ { '<', $start }, { '>', $end } ]
]);
}
else {
@times = (-and => [
time_first => { '>=', $start },
time_last => { '<=', $end },
]);
@wifitimes = (-and => [
@times = (-or => [
-and => [
time_first => undef,
time_last => undef,
],
-and => [
time_last => { '>=', $start },
time_last => { '<=', $end },
],
]);
@porttimes = (-and => [
@wifitimes = (-or => [
-and => [
time_first => undef,
time_last => undef,
],
-and => [
time_last => { '>=', $start },
time_last => { '<=', $end },
],
]);
@porttimes = (-or => [
creation => undef,
-and => [
creation => { '>=', $start },
creation => { '<=', $end },
],
]);
}
}

View File

@@ -49,7 +49,7 @@ ajax '/ajax/data/port/typeahead' => require_login sub {
if $port;
my $results = [
map {{ label => (sprintf "%s (%s)", $_->port, $_->name), value => $_->port }}
map {{ label => (sprintf "%s (%s)", $_->port, ($_->name || '')), value => $_->port }}
sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } $set->all
];

View File

@@ -45,7 +45,7 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
# only enqueue if device is not already discovered,
# discover_* config permits the discovery
foreach my $neighbor (@to_discover) {
my ($ip, $remote_type, $remote_id) = @$neighbor;
my ($ip, $remote_id) = @$neighbor;
if ($seen_ip{ $ip }++) {
debug sprintf
' queue - skip: IP %s is already queued from %s',
@@ -63,13 +63,6 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
my $newdev = get_device($ip);
next if $newdev->in_storage;
if (not is_discoverable($newdev, $remote_type)) {
debug sprintf
' queue - skip: %s of type [%s] excluded by discover_* config',
$ip, ($remote_type || '');
next;
}
# risk of things going wrong...?
# https://quickview.cloudapps.cisco.com/quickview/bug/CSCur12254
@@ -127,6 +120,7 @@ sub store_neighbors {
my $c_port = $snmp->c_port;
my $c_id = $snmp->c_id;
my $c_platform = $snmp->c_platform;
my $c_cap = $snmp->c_cap;
# cache the device ports to save hitting the database for many single rows
vars->{'device_ports'} =
@@ -176,6 +170,7 @@ sub store_neighbors {
my $remote_port = undef;
my $remote_type = Encode::decode('UTF-8', $c_platform->{$entry} || '');
my $remote_id = Encode::decode('UTF-8', $c_id->{$entry});
my $remote_cap = $c_cap->{$entry} || [];
next unless $remote_ip;
my $r_netaddr = NetAddr::IP::Lite->new($remote_ip);
@@ -246,7 +241,15 @@ sub store_neighbors {
# what we came here to do.... discover the neighbor
debug sprintf ' [%s] neigh - %s with ID [%s] on %s',
$device->ip, $remote_ip, ($remote_id || ''), $port;
push @to_discover, [$remote_ip, $remote_type, $remote_id];
if (is_discoverable($remote_ip, $remote_type, $remote_cap)) {
push @to_discover, [$remote_ip, $remote_id];
}
else {
debug sprintf
' [%s] neigh - skip: %s of type [%s] excluded by discover_* config',
$device->ip, $remote_ip, ($remote_type || '');
}
$remote_port = $c_port->{$entry};
if (defined $remote_port) {

View File

@@ -8,7 +8,7 @@ use App::Netdisco::Transport::SNMP ();
use Dancer::Plugin::DBIC 'schema';
use Encode;
use App::Netdisco::Util::Device 'match_devicetype';
use App::Netdisco::Util::Device 'match_to_setting';
register_worker({ phase => 'main', driver => 'snmp' }, sub {
my ($job, $workerconf) = @_;
@@ -86,12 +86,12 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
my $remote_type = Encode::decode('UTF-8', $c_platform->{$idx} || '');
$properties{ $port }->{remote_is_wap} = 'true'
if scalar grep {match_devicetype($_, 'wap_capabilities')} @$remote_cap
or match_devicetype($remote_type, 'wap_platforms');
if scalar grep {match_to_setting($_, 'wap_capabilities')} @$remote_cap
or match_to_setting($remote_type, 'wap_platforms');
$properties{ $port }->{remote_is_phone} = 'true'
if scalar grep {match_devicetype($_, 'phone_capabilities')} @$remote_cap
or match_devicetype($remote_type, 'phone_platforms');
if scalar grep {match_to_setting($_, 'phone_capabilities')} @$remote_cap
or match_to_setting($remote_type, 'phone_platforms');
next unless scalar grep {defined && m/^inventory$/} @{ $rem_media_cap->{$idx} };

View File

@@ -238,6 +238,7 @@ register_worker({ phase => 'early', driver => 'snmp' }, sub {
# must do this after building %interfaces so that we can set is_master
foreach my $sidx (keys %$agg_ports) {
my $slave = $interfaces->{$sidx} or next;
next unless defined $agg_ports->{$sidx}; # slave without a master?!
my $master = $interfaces->{ $agg_ports->{$sidx} } or next;
next unless exists $interfaces{$slave} and exists $interfaces{$master};

View File

@@ -7,7 +7,7 @@ use aliased 'App::Netdisco::Worker::Status';
use App::Netdisco::Transport::SNMP ();
use App::Netdisco::Util::Permission 'check_acl_no';
use App::Netdisco::Util::PortMAC 'get_port_macs';
use App::Netdisco::Util::Device 'match_devicetype';
use App::Netdisco::Util::Device 'match_to_setting';
use App::Netdisco::Util::Node 'check_mac';
use App::Netdisco::Util::SNMP 'snmp_comm_reindex';
use Dancer::Plugin::DBIC 'schema';
@@ -342,7 +342,7 @@ sub walk_fwtable {
# neighbors otherwise it would kill the DB with device lookups.
my $neigh_cannot_macsuck = eval { # can fail
check_acl_no(($device_port->neighbor || "0 but true"), 'macsuck_unsupported') ||
match_devicetype($device_port->remote_type, 'macsuck_unsupported_type') };
match_to_setting($device_port->remote_type, 'macsuck_unsupported_type') };
if ($device_port->is_uplink) {
if ($neigh_cannot_macsuck) {

View File

@@ -229,9 +229,9 @@ devices_no: []
devices_only: []
discover_no: []
discover_only: []
discover_no_type:
- '(?i)phone'
- '(?i)(?:wap|wireless)'
discover_no_type: []
discover_waps: true
discover_phones: false
discover_min_age: 0
macsuck_no: []
macsuck_only: []

View File

@@ -39,20 +39,18 @@ device_auth:
# ¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸
#
# SOME MORE INTERESTING SETTINGS WHERE THE DEFAULTS ARE PROBABLY OKAY
#
# ¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸
# ---------------------------------------------------------------
# OTHER INTERESTING SETTINGS WHERE THE DEFAULTS ARE PROBABLY OKAY
# ---------------------------------------------------------------
# do not discover IP Phones or Wireless Access Points.
# discover Wireless Access Points, but not IP Phones
# usually these are visible as device neighbors but don't support
# SNMP, which just clogs up the job queue.
# ```````````````````````````````````````````````````````````````
#discover_no_type:
# - '(?i)phone'
# - '(?i)(?:wap|wireless)'
#discover_waps: true
#disover_phones: false
# this is the schedule for automatically keeping netdisco up-to-date;
# these are good defaults, so only uncomment if needing to change.