merge in og-get_external_credentials

Squashed commit of the following:

commit 3fe8f383a7
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Mar 11 17:07:42 2019 +0000

    add debug lines and tested

commit 3249739e42
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Mar 11 16:54:11 2019 +0000

    change config name to get_credentials

commit e78558397a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Mar 11 16:51:11 2019 +0000

    separate out generic device auth to DeviceAuth module

commit 249f05165f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Mar 6 18:43:31 2019 +0000

    release 2.040007

commit e3af64df77
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Mar 6 18:42:47 2019 +0000

    #521-redux fix wifi date search

commit 48857ae300
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Mar 4 12:03:31 2019 +0000

    release 2.040006

commit e09dab5362
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Mar 4 11:39:12 2019 +0000

    #527 update List::MoreUtils version requirement

commit 6e7de3fff3
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Mar 4 09:59:41 2019 +0000

    release 2.040005

commit 0c98318a45
Author: Oliver Gorwits <oliver@spike.local>
Date:   Mon Mar 4 09:57:18 2019 +0000

    #526 fix discover syntax bug

commit e9efc45182
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 14:56:48 2019 +0000

    release 2.040004

commit 6cdfd80d10
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 14:34:00 2019 +0000

    allow undiscovered neighbors report to use discover_{waps,phones} setting

commit ac381e0802
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 14:13:20 2019 +0000

    #506 was a red herring

commit b83e614c85
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 13:00:36 2019 +0000

    make discover_{phones,waps} work with LLDP capabilities as well

commit 189d234b55
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 12:47:38 2019 +0000

    check discover_no_type and friends earlier on in neighbors list build

commit 9c956466f3
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 12:32:07 2019 +0000

    also update default config for new discover_phones and discover_waps settings

commit 09d29954d2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 12:26:50 2019 +0000

    #512 fix regression in phone/wap discovery exclusion

commit 2bae91f1b6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 12:01:34 2019 +0000

    rename match_devicetype() to match_to_setting()

commit 57cb6ddb70
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Mar 3 09:19:39 2019 +0000

    fix for over-eager fix to #506

commit ef560fb59a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 22:41:40 2019 +0000

    #506 relax device renumber so it works for an alias

commit 7a8bcb094e
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 22:23:39 2019 +0000

    #521 Search Node Date Range not working

commit a643820a62
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 21:54:27 2019 +0000

    #428 Port-Channels not showing in netmap

commit 5ba5bcd295
Merge: e7aacddb a1f95028
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 20:04:11 2019 +0000

    Merge branch 'master' of github.com:netdisco/netdisco

commit e7aacddbc6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 20:01:05 2019 +0000

    #498 Map with VLAN filter omits unconnected devices

commit a1f95028ca
Author: nick n <39005454+inphobia@users.noreply.github.com>
Date:   Sat Mar 2 19:54:22 2019 +0100

    catch up with changes

    noticed that rc-sshcollector-core received updates to changes, add them here as well.

    didn't mention #499 & #522

commit ce1b847cea
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 18:47:44 2019 +0000

    fix bug showing no nodes when only one matches in netmap

commit 78e30a7926
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 16:28:15 2019 +0000

    #500 filtering in device/ports on native vlan duplicates entries

commit 9952f0c6c7
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 15:02:12 2019 +0000

    #499 netdisco-do renumber reports wrong ip (inphobia)

commit ca3fd8f466
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 15:00:18 2019 +0000

    #505 device renumber should update device port properties and device skips

commit 1265bc8470
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 14:52:21 2019 +0000

    #520 catch slave ports defined without a master

commit d4c7579c10
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 14:47:49 2019 +0000

    #522 TypeAhead.pm can reference empty data (inphobia)

commit 77decc23b7
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Mar 2 14:45:37 2019 +0000

    #514 inconsistent results in ip inventory (inphobia)

commit 3f211650b8
Author: nick n <39005454+inphobia@users.noreply.github.com>
Date:   Fri Mar 1 12:34:42 2019 +0100

    last pieces for db schema upgrade

    last piece of #510
This commit is contained in:
Oliver Gorwits
2019-03-11 20:34:07 +00:00
parent 0347ba7bbd
commit 98d7a71024
25 changed files with 353 additions and 257 deletions

View File

@@ -47,7 +47,7 @@ Module::Build->new(
'JSON' => '2.90', 'JSON' => '2.90',
'JSON::XS' => '3.01', 'JSON::XS' => '3.01',
'List::Util' => '1.49', 'List::Util' => '1.49',
'List::MoreUtils' => '0.33', 'List::MoreUtils' => '0.428',
'MIME::Base64' => '3.13', 'MIME::Base64' => '3.13',
'Module::Load' => '0.32', 'Module::Load' => '0.32',
'Moo' => '1.001000', 'Moo' => '1.001000',

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
package App::Netdisco::Configuration; package App::Netdisco::Configuration;
use App::Netdisco::Environment; use App::Netdisco::Environment;
use App::Netdisco::Util::SNMP (); use App::Netdisco::Util::DeviceAuth ();
use Dancer ':script'; use Dancer ':script';
use Path::Class 'dir'; use Path::Class 'dir';
@@ -84,7 +84,8 @@ if ((setting('snmp_auth') and 0 == scalar @{ setting('snmp_auth') })
config->{'community_rw'} = [ @{setting('community_rw')}, 'private' ]; config->{'community_rw'} = [ @{setting('community_rw')}, 'private' ];
} }
# fix up device_auth (or create it from old snmp_auth and community settings) # fix up device_auth (or create it from old snmp_auth and community settings)
config->{'device_auth'} = [ App::Netdisco::Util::SNMP::fixup_device_auth() ]; config->{'device_auth'}
= [ App::Netdisco::Util::DeviceAuth::fixup_device_auth() ];
# defaults for workers # defaults for workers
setting('workers')->{queue} ||= 'PostgreSQL'; setting('workers')->{queue} ||= 'PostgreSQL';

View File

@@ -262,20 +262,27 @@ sub renumber {
foreach my $set (qw/ foreach my $set (qw/
DeviceIp DeviceIp
DeviceModule DeviceModule
DevicePower
DeviceVlan
DevicePort DevicePort
DevicePortLog DevicePortLog
DevicePortPower DevicePortPower
DevicePortProperties
DevicePortSsid DevicePortSsid
DevicePortVlan DevicePortVlan
DevicePortWireless DevicePortWireless
DevicePower
DeviceVlan
/) { /) {
$schema->resultset($set) $schema->resultset($set)
->search({ip => $old_ip}) ->search({ip => $old_ip})
->update({ip => $new_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') $schema->resultset('DevicePort')
->search({remote_ip => $old_ip}) ->search({remote_ip => $old_ip})
->update({remote_ip => $new_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.port) AS left_port,
array_agg(dp.name) AS left_descr, array_agg(dp.name) AS left_descr,
count(dpp.*) AS aggports,
sum(COALESCE(dpp.raw_speed, 0)) AS aggspeed, sum(COALESCE(dpp.raw_speed, 0)) AS aggspeed,
count(*) AS aggports,
di.ip AS right_ip, di.ip AS right_ip,
rd.dns AS right_dns, rd.dns AS right_dns,
@@ -32,8 +32,14 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
array_agg(dp2.name) AS right_descr array_agg(dp2.name) AS right_descr
FROM device_port dp 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 ld ON dp.ip = ld.ip
INNER JOIN device_ip di ON dp.remote_ip = di.alias INNER JOIN device_ip di ON dp.remote_ip = di.alias
INNER JOIN device rd ON di.ip = rd.ip 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 WHERE dp.remote_port IS NOT NULL
AND dp.port !~* 'vlan' AND dp.port !~* 'vlan'
AND (dp.descr IS NULL AND (dp.descr IS NULL OR dp.descr !~* 'vlan')
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)
GROUP BY left_ip, GROUP BY left_ip,
left_dns, left_dns,
@@ -58,6 +59,7 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
right_ip, right_ip,
right_dns, right_dns,
right_name ) right_name )
SELECT * SELECT *
FROM BothWays b FROM BothWays b
WHERE NOT EXISTS WHERE NOT EXISTS

View File

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

View File

@@ -47,16 +47,16 @@ sub with_times {
->search({}, ->search({},
{ {
'+columns' => { '+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')"), ."timestamp '1970-01-01 00:00:00-00')::text, 'mon', 'month')"),
first_seen_stamp => \"to_char(me.creation, 'YYYY-MM-DD HH24:MI')", 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_discover_stamp => \"to_char(me.last_discover, 'YYYY-MM-DD HH24:MI')",
last_macsuck_stamp => \"to_char(last_macsuck, 'YYYY-MM-DD HH24:MI')", last_macsuck_stamp => \"to_char(me.last_macsuck, 'YYYY-MM-DD HH24:MI')",
last_arpnip_stamp => \"to_char(last_arpnip, '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_first_seen => \"extract(epoch from (age(now(), me.creation)))",
since_last_discover => \"extract(epoch from (age(now(), last_discover)))", since_last_discover => \"extract(epoch from (age(now(), me.last_discover)))",
since_last_macsuck => \"extract(epoch from (age(now(), last_macsuck)))", since_last_macsuck => \"extract(epoch from (age(now(), me.last_macsuck)))",
since_last_arpnip => \"extract(epoch from (age(now(), last_arpnip)))", since_last_arpnip => \"extract(epoch from (age(now(), me.last_arpnip)))",
}, },
}); });
} }

View File

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

View File

@@ -0,0 +1,163 @@
package App::Netdisco::Util::DeviceAuth;
use Dancer qw/:syntax :script/;
use App::Netdisco::Util::DNS 'hostname_from_ip';
use Try::Tiny;
use base 'Exporter';
our @EXPORT = ();
our @EXPORT_OK = qw/
fixup_device_auth get_external_credentials
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK);
=head1 NAME
App::Netdisco::Util::DeviceAuth
=head1 DESCRIPTION
Helper functions for device authentication.
There are no default exports, however the C<:all> tag will export all
subroutines.
=head1 EXPORT_OK
=head2 fixup_device_auth
Rebuilds the C<device_auth> config with missing defaults and other fixups for
config changes over time. Returns a list which can replace C<device_auth>.
=cut
sub fixup_device_auth {
my $config = (setting('snmp_auth') || setting('device_auth'));
my @new_stanzas = ();
# new style snmp config
foreach my $stanza (@$config) {
# user tagged
my $tag = '';
if (1 == scalar keys %$stanza) {
$tag = (keys %$stanza)[0];
$stanza = $stanza->{$tag};
# corner case: untagged lone community
if ($tag eq 'community') {
$tag = $stanza;
$stanza = {community => $tag};
}
}
# defaults
$stanza->{tag} ||= $tag;
$stanza->{read} = 1 if !exists $stanza->{read};
$stanza->{no} ||= [];
$stanza->{only} ||= ['any'];
die "error: config: snmpv2 community in device_auth must be single item, not list\n"
if ref $stanza->{community};
die "error: config: stanza in device_auth must have a tag\n"
if not $stanza->{tag} and exists $stanza->{user};
push @new_stanzas, $stanza
}
# legacy config
# note: read strings tried before write
# note: read-write is no longer used for read operations
push @new_stanzas, map {{
read => 1, write => 0,
no => [], only => ['any'],
community => $_,
}} @{setting('community') || []};
push @new_stanzas, map {{
write => 1, read => 0,
no => [], only => ['any'],
community => $_,
}} @{setting('community_rw') || []};
foreach my $stanza (@new_stanzas) {
$stanza->{driver} ||= 'snmp'
if exists $stanza->{community}
or exists $stanza->{user};
}
return @new_stanzas;
}
=head2 get_external_credentials( $device, $mode )
Runs a command to gather SNMP credentials or a C<device_auth> stanza.
Mode can be C<read> or C<write> and defaults to 'read'.
=cut
sub get_external_credentials {
my ($device, $mode) = @_;
my $cmd = (setting('get_credentials') || setting('get_community'));
my $ip = $device->ip;
my $host = ($device->dns || hostname_from_ip($ip) || $ip);
$mode ||= 'read';
if (defined $cmd and length $cmd) {
# replace variables
$cmd =~ s/\%MODE\%/$mode/egi;
$cmd =~ s/\%HOST\%/$host/egi;
$cmd =~ s/\%IP\%/$ip/egi;
my $result = `$cmd`; # BACKTICKS
return () unless defined $result and length $result;
my @lines = split (m/\n/, $result);
foreach my $line (@lines) {
if ($line =~ m/^community\s*=\s*(.*)\s*$/i) {
if (length $1 and $mode eq 'read') {
debug sprintf '[%s] external read credentials added',
$device->ip;
return map {{
read => 1,
only => [$device->ip],
community => $_,
}} split(m/\s*,\s*/,$1);
}
}
elsif ($line =~ m/^setCommunity\s*=\s*(.*)\s*$/i) {
if (length $1 and $mode eq 'write') {
debug sprintf '[%s] external write credentials added',
$device->ip;
return map {{
write => 1,
only => [$device->ip],
community => $_,
}} split(m/\s*,\s*/,$1);
}
}
else {
my $stanza = undef;
try {
$stanza = from_json( $line );
debug sprintf '[%s] external credentials stanza added',
$device->ip;
}
catch {
info sprintf '[%s] error! failed to parse external credentials stanza',
$device->ip;
};
return $stanza if ref $stanza;
}
}
}
return ();
}
true;

View File

@@ -1,14 +1,11 @@
package App::Netdisco::Util::SNMP; package App::Netdisco::Util::SNMP;
use Dancer qw/:syntax :script/; use Dancer qw/:syntax :script/;
use App::Netdisco::Util::DNS 'hostname_from_ip'; use App::Netdisco::Util::DeviceAuth 'get_external_credentials';
use App::Netdisco::Util::Permission ':all';
use base 'Exporter'; use base 'Exporter';
our @EXPORT = (); our @EXPORT = ();
our @EXPORT_OK = qw/ our @EXPORT_OK = qw/ get_communities snmp_comm_reindex /;
fixup_device_auth get_communities snmp_comm_reindex
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK); our %EXPORT_TAGS = (all => \@EXPORT_OK);
=head1 NAME =head1 NAME
@@ -24,72 +21,6 @@ subroutines.
=head1 EXPORT_OK =head1 EXPORT_OK
=head2 fixup_device_auth
Rebuilds the C<device_auth> config with missing defaults and other fixups for
config changes over time. Returns a list which can replace C<device_auth>.
=cut
sub fixup_device_auth {
my $config = (setting('snmp_auth') || setting('device_auth'));
my @new_stanzas = ();
# new style snmp config
foreach my $stanza (@$config) {
# user tagged
my $tag = '';
if (1 == scalar keys %$stanza) {
$tag = (keys %$stanza)[0];
$stanza = $stanza->{$tag};
# corner case: untagged lone community
if ($tag eq 'community') {
$tag = $stanza;
$stanza = {community => $tag};
}
}
# defaults
$stanza->{tag} ||= $tag;
$stanza->{read} = 1 if !exists $stanza->{read};
$stanza->{no} ||= [];
$stanza->{only} ||= ['any'];
die "error: config: snmpv2 community in device_auth must be single item, not list\n"
if ref $stanza->{community};
die "error: config: stanza in device_auth must have a tag\n"
if not $stanza->{tag} and exists $stanza->{user};
push @new_stanzas, $stanza
}
# legacy config
# note: read strings tried before write
# note: read-write is no longer used for read operations
push @new_stanzas, map {{
read => 1, write => 0,
no => [], only => ['any'],
community => $_,
}} @{setting('community') || []};
push @new_stanzas, map {{
write => 1, read => 0,
no => [], only => ['any'],
community => $_,
}} @{setting('community_rw') || []};
foreach my $stanza (@new_stanzas) {
$stanza->{driver} ||= 'snmp'
if exists $stanza->{community}
or exists $stanza->{user};
}
return @new_stanzas;
}
=head2 get_communities( $device, $mode ) =head2 get_communities( $device, $mode )
Takes the current C<device_auth> setting and pushes onto the front of the list Takes the current C<device_auth> setting and pushes onto the front of the list
@@ -106,8 +37,7 @@ sub get_communities {
my @communities = (); my @communities = ();
# first of all, use external command if configured # first of all, use external command if configured
push @communities, _get_external_community($device, $mode) push @communities, get_external_credentials($device, $mode);
if setting('get_community') and length setting('get_community');
# last known-good by tag # last known-good by tag
my $tag_name = 'snmp_auth_tag_'. $mode; my $tag_name = 'snmp_auth_tag_'. $mode;
@@ -145,46 +75,6 @@ sub get_communities {
return ( @communities, @$config ); return ( @communities, @$config );
} }
sub _get_external_community {
my ($device, $mode) = @_;
my $cmd = setting('get_community');
my $ip = $device->ip;
my $host = ($device->dns || hostname_from_ip($ip) || $ip);
if (defined $cmd and length $cmd) {
# replace variables
$cmd =~ s/\%HOST\%/$host/egi;
$cmd =~ s/\%IP\%/$ip/egi;
my $result = `$cmd`; # BACKTICKS
return () unless defined $result and length $result;
my @lines = split (m/\n/, $result);
foreach my $line (@lines) {
if ($line =~ m/^community\s*=\s*(.*)\s*$/i) {
if (length $1 and $mode eq 'read') {
return map {{
read => 1,
only => [$device->ip],
community => $_,
}} split(m/\s*,\s*/,$1);
}
}
elsif ($line =~ m/^setCommunity\s*=\s*(.*)\s*$/i) {
if (length $1 and $mode eq 'write') {
return map {{
write => 1,
only => [$device->ip],
community => $_,
}} split(m/\s*,\s*/,$1);
}
}
}
}
return ();
}
=head2 snmp_comm_reindex( $snmp, $device, $vlan ) =head2 snmp_comm_reindex( $snmp, $device, $vlan )
Takes an established L<SNMP::Info> instance and makes a fresh connection using Takes an established L<SNMP::Info> instance and makes a fresh connection using

View File

@@ -7,7 +7,7 @@ use Dancer::Plugin::Auth::Extensible;
use URI (); use URI ();
use URL::Encode 'url_params_mixed'; 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 # build view settings for port connected nodes and devices
set('connected_properties' => [ set('connected_properties' => [
@@ -20,7 +20,7 @@ hook 'before_template' => sub {
my $tokens = shift; my $tokens = shift;
# allow checking of discoverability of remote connected device # 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'} my $defaults = var('sidebar_defaults')->{'device_ports'}
or return; 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() # create a new row object to avoid hitting the DB in get_device()
my $dev = schema('netdisco')->resultset('Device')->new({ip => $r->{remote_ip}}); my $dev = schema('netdisco')->resultset('Device')->new({ip => $r->{remote_ip}});
next unless is_discoverable( $dev, $r->{remote_type} ); 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; push @discoverable_results, $r;
} }
return unless scalar @discoverable_results; 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 $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$//; (my $right_name = lc($link->{right_dns} || $link->{right_name} || $link->{right_ip})) =~ s/$domain$//;
if ($link->{aggports} == 1) { my @zipped = List::MoreUtils::zip6
return sprintf '<b>%s:%s</b> (%s)<br><b>%s:%s</b> (%s)', @{$link->{left_port}}, @{$link->{left_descr}},
$left_name, $link->{left_port}->[0], @{$link->{right_port}}, @{$link->{right_descr}};
($link->{left_descr}->[0] || 'no description'),
$right_name, $link->{right_port}->[0], return join '<br><br>', map { sprintf '<b>%s:%s</b> (%s)<br><b>%s:%s</b> (%s)',
($link->{right_descr}->[0] || 'no description'); $left_name, $_->[0], ($_->[1] || 'no description'),
} $right_name, $_->[2], ($_->[3] || 'no description') } @zipped;
else {
return sprintf '<b>%s:(%s)</b><br><b>%s:(%s)</b>',
$left_name, join(',', @{$link->{left_port}}),
$right_name, join(',', @{$link->{right_port}});
}
} }
ajax '/ajax/data/device/netmap' => require_login sub { 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' }); }, { 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) { while (my $link = $links->next) {
push @{$data{'links'}}, { push @{$data{'links'}}, {
FROMID => $link->{left_ip}, FROMID => $link->{left_ip},
@@ -217,10 +201,19 @@ ajax '/ajax/data/device/netmap' => require_login sub {
join => 'throughput', join => 'throughput',
})->with_times; })->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) { DEVICE: while (my $device = $devices->next) {
# if in neighbors or vlan mode then use %ok_dev to filter # if in neighbors mode then use %ok_dev to filter
next DEVICE if (($mapshow eq 'neighbors') or $vlan) next DEVICE if ($device->ip ne $qdev->ip)
and (not $ok_dev{$device->ip}); and ($mapshow eq 'neighbors')
and (not $ok_dev{$device->ip}); # showing only neighbors but no link
# if location picked then filter # if location picked then filter
next DEVICE if ((scalar @lgrplist) and ((!defined $device->location) 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 ($f) {
if (($prefer eq 'vlan') or (not $prefer and $f =~ m/^\d+$/)) { if (($prefer eq 'vlan') or (not $prefer and $f =~ m/^\d+$/)) {
return unless $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 { else {
if (param('partial')) { 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 # now begin to join tables depending on the selected columns/options
# get vlans on the port # 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({}, { my $vlans = $set->search({}, {
select => [ select => [
'port', 'port',
@@ -131,7 +112,7 @@ get '/ajax/content/device/ports' => require_login sub {
group_by => 'me.port', 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 {( $vlans = { map {(
$_->port => { $_->port => {
# DBIC smart enough to work out this should be an arrayref :) # 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 # also get remote LLDP inventory if asked for
$set = $set->with_remote_inventory if param('n_inventory'); $set = $set->with_remote_inventory if param('n_inventory');
# sort ports (empty set would be a 'no records' msg) # run query
my $results = [ sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } $set->all ]; my @results = $set->all;
return unless scalar @$results;
# 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) { if (request->is_ajax) {
template 'ajax/device/ports.tt', { template 'ajax/device/ports.tt', {
results => $results, results => \@results,
nodes => $nodes_name, nodes => $nodes_name,
ips => $ips_name, ips => $ips_name,
device => $device, device => $device,
@@ -210,7 +215,7 @@ get '/ajax/content/device/ports' => require_login sub {
else { else {
header( 'Content-Type' => 'text/comma-separated-values' ); header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/device/ports_csv.tt', { template 'ajax/device/ports_csv.tt', {
results => $results, results => \@results,
nodes => $nodes_name, nodes => $nodes_name,
ips => $ips_name, ips => $ips_name,
device => $device, device => $device,

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@ use App::Netdisco::Transport::SNMP ();
use Dancer::Plugin::DBIC 'schema'; use Dancer::Plugin::DBIC 'schema';
use Encode; use Encode;
use App::Netdisco::Util::Device 'match_devicetype'; use App::Netdisco::Util::Device 'match_to_setting';
register_worker({ phase => 'main', driver => 'snmp' }, sub { register_worker({ phase => 'main', driver => 'snmp' }, sub {
my ($job, $workerconf) = @_; my ($job, $workerconf) = @_;
@@ -86,12 +86,12 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
my $remote_type = Encode::decode('UTF-8', $c_platform->{$idx} || ''); my $remote_type = Encode::decode('UTF-8', $c_platform->{$idx} || '');
$properties{ $port }->{remote_is_wap} = 'true' $properties{ $port }->{remote_is_wap} = 'true'
if scalar grep {match_devicetype($_, 'wap_capabilities')} @$remote_cap if scalar grep {match_to_setting($_, 'wap_capabilities')} @$remote_cap
or match_devicetype($remote_type, 'wap_platforms'); or match_to_setting($remote_type, 'wap_platforms');
$properties{ $port }->{remote_is_phone} = 'true' $properties{ $port }->{remote_is_phone} = 'true'
if scalar grep {match_devicetype($_, 'phone_capabilities')} @$remote_cap if scalar grep {match_to_setting($_, 'phone_capabilities')} @$remote_cap
or match_devicetype($remote_type, 'phone_platforms'); or match_to_setting($remote_type, 'phone_platforms');
next unless scalar grep {defined && m/^inventory$/} @{ $rem_media_cap->{$idx} }; 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 # must do this after building %interfaces so that we can set is_master
foreach my $sidx (keys %$agg_ports) { foreach my $sidx (keys %$agg_ports) {
my $slave = $interfaces->{$sidx} or next; my $slave = $interfaces->{$sidx} or next;
next unless defined $agg_ports->{$sidx}; # slave without a master?!
my $master = $interfaces->{ $agg_ports->{$sidx} } or next; my $master = $interfaces->{ $agg_ports->{$sidx} } or next;
next unless exists $interfaces{$slave} and exists $interfaces{$master}; 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::Transport::SNMP ();
use App::Netdisco::Util::Permission 'check_acl_no'; use App::Netdisco::Util::Permission 'check_acl_no';
use App::Netdisco::Util::PortMAC 'get_port_macs'; 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::Node 'check_mac';
use App::Netdisco::Util::SNMP 'snmp_comm_reindex'; use App::Netdisco::Util::SNMP 'snmp_comm_reindex';
use Dancer::Plugin::DBIC 'schema'; use Dancer::Plugin::DBIC 'schema';
@@ -342,7 +342,7 @@ sub walk_fwtable {
# neighbors otherwise it would kill the DB with device lookups. # neighbors otherwise it would kill the DB with device lookups.
my $neigh_cannot_macsuck = eval { # can fail my $neigh_cannot_macsuck = eval { # can fail
check_acl_no(($device_port->neighbor || "0 but true"), 'macsuck_unsupported') || 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 ($device_port->is_uplink) {
if ($neigh_cannot_macsuck) { if ($neigh_cannot_macsuck) {

View File

@@ -216,7 +216,7 @@ device_identity: []
community: [] community: []
community_rw: [] community_rw: []
device_auth: [] device_auth: []
get_community: "" get_credentials: ""
bulkwalk_off: false bulkwalk_off: false
bulkwalk_no: [] bulkwalk_no: []
bulkwalk_repeaters: 20 bulkwalk_repeaters: 20
@@ -229,9 +229,9 @@ devices_no: []
devices_only: [] devices_only: []
discover_no: [] discover_no: []
discover_only: [] discover_only: []
discover_no_type: discover_no_type: []
- '(?i)phone' discover_waps: true
- '(?i)(?:wap|wireless)' discover_phones: false
discover_min_age: 0 discover_min_age: 0
macsuck_no: [] macsuck_no: []
macsuck_only: [] macsuck_only: []

View File

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