Merge branch 'master' into og-multiple-domain-suffix
This commit is contained in:
@@ -71,7 +71,8 @@ L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||
|
||||
Netdisco has several Perl library dependencies which will be automatically
|
||||
installed. However it's required that you first install the following
|
||||
operating system packages:
|
||||
operating system packages, if not the installation will most likely fail
|
||||
further down the road.
|
||||
|
||||
On Ubuntu/Debian:
|
||||
|
||||
@@ -100,7 +101,7 @@ will take about 250MB including MIB files.
|
||||
root:~# useradd -m -p x -s /bin/bash netdisco
|
||||
|
||||
Netdisco uses the PostgreSQL database server. Install PostgreSQL (at least
|
||||
version 8.4) and then change to the PostgreSQL superuser (usually
|
||||
version 9.4) and then change to the PostgreSQL superuser (usually
|
||||
C<postgres>). Create a new database and PostgreSQL user for the Netdisco
|
||||
application:
|
||||
|
||||
@@ -115,14 +116,25 @@ application:
|
||||
You may wish to L<amend the PostgreSQL
|
||||
configuration|https://github.com/netdisco/netdisco/wiki/Install-Tips#enable-md5-authentication-to-postgresql>
|
||||
so that local connections are working. The default PostgreSQL configuration
|
||||
also needs tuning for modern server hardware. We recommend that you use the
|
||||
C<pgtune> Python program to auto-tune your C<postgresql.conf> file:
|
||||
can also use tuning for modern server hardware. We recommend that you use one of the following
|
||||
tools to tune your C<postgresql.conf> file:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
=item L<postgresqltuner|https://github.com/jfcoz/postgresqltuner>
|
||||
|
||||
L<https://github.com/elitwin/pgtune>
|
||||
Script that will check your operating system resources and settings as well as your
|
||||
running PostgreSQL database and will make recommendations based on actual load. Works
|
||||
on new netdisco installs but will make the best suggestions once the database contains
|
||||
a bigger dataset.
|
||||
|
||||
=item L<pgtune (fork)|https://pgtune.leopard.in.ua>
|
||||
|
||||
A web based application which will recommend which parameters to change.
|
||||
|
||||
=item L<pgtune|https://github.com/elitwin/pgtune>
|
||||
|
||||
Program to auto-tune your C<postgresql.conf>, regretfully not updated in a while.
|
||||
|
||||
=back
|
||||
|
||||
@@ -229,7 +241,7 @@ If you're running a version of Netdisco prior to 2.x then you should follow
|
||||
the full installation instructions, above. This process is for upgrading
|
||||
version 2.x only.
|
||||
|
||||
Before upgrading please review the latest L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||
Before upgrading always review the latest L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||
Then the process below should be run for each installation:
|
||||
|
||||
# upgrade Netdisco
|
||||
@@ -251,7 +263,7 @@ Then the process below should be run for each installation:
|
||||
|
||||
The main black navigation bar has a search box which is smart enough to work
|
||||
out what you're looking for in most cases. For example device names, node IP
|
||||
or MAC addreses, VLAN numbers, and so on.
|
||||
or MAC addresses, VLAN numbers, and so on.
|
||||
|
||||
=head2 Command-Line Device and Port Actions
|
||||
|
||||
@@ -332,7 +344,7 @@ built upon.
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2011-2018 by The Netdisco Developer Team.
|
||||
This software is copyright (c) 2011-2019 by The Netdisco Developer Team.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -70,7 +70,7 @@ sub display_name {
|
||||
|
||||
=head2 cancel
|
||||
|
||||
Log a status and prevent other stages from runnning.
|
||||
Log a status and prevent other stages from running.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ __PACKAGE__->load_namespaces(
|
||||
);
|
||||
|
||||
our # try to hide from kwalitee
|
||||
$VERSION = 58; # schema version used for upgrades, keep as integer
|
||||
$VERSION = 59; # schema version used for upgrades, keep as integer
|
||||
|
||||
use Path::Class;
|
||||
use File::ShareDir 'dist_dir';
|
||||
|
||||
@@ -242,6 +242,23 @@ __PACKAGE__->belongs_to( neighbor_alias => 'App::Netdisco::DB::Result::DeviceIp'
|
||||
{ join_type => 'LEFT' },
|
||||
);
|
||||
|
||||
=head2 last_node
|
||||
|
||||
This relationship will return the last node that was seen on the port.
|
||||
|
||||
The JOIN is of type "LEFT" in case there isn't any such node.
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->belongs_to(
|
||||
last_node => 'App::Netdisco::DB::Result::Virtual::LastNode', {
|
||||
'foreign.switch' => 'self.ip',
|
||||
'foreign.port' => 'self.port',
|
||||
}, {
|
||||
join_type => 'LEFT',
|
||||
}
|
||||
);
|
||||
|
||||
=head2 vlans
|
||||
|
||||
As compared to C<port_vlans>, this relationship returns a set of Device VLAN
|
||||
|
||||
@@ -29,6 +29,8 @@ __PACKAGE__->add_columns(
|
||||
{ data_type => "boolean", default_value => \"false", is_nullable => 1 },
|
||||
"ldap",
|
||||
{ data_type => "boolean", default_value => \"false", is_nullable => 1 },
|
||||
"radius",
|
||||
{ data_type => "boolean", default_value => \"false", is_nullable => 1 },
|
||||
"admin",
|
||||
{ data_type => "boolean", default_value => \"false", is_nullable => 1 },
|
||||
"fullname",
|
||||
|
||||
54
lib/App/Netdisco/DB/Result/Virtual/LastNode.pm
Normal file
54
lib/App/Netdisco/DB/Result/Virtual/LastNode.pm
Normal file
@@ -0,0 +1,54 @@
|
||||
package App::Netdisco::DB::Result::Virtual::LastNode;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'DBIx::Class::Core';
|
||||
|
||||
__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
|
||||
|
||||
__PACKAGE__->table('last_node');
|
||||
__PACKAGE__->result_source_instance->is_virtual(1);
|
||||
__PACKAGE__->result_source_instance->view_definition(<<ENDSQL
|
||||
SELECT DISTINCT ON (switch, port) * FROM node
|
||||
ORDER BY switch, port, time_last desc
|
||||
ENDSQL
|
||||
);
|
||||
|
||||
__PACKAGE__->add_columns(
|
||||
"mac",
|
||||
{ data_type => "macaddr", is_nullable => 0 },
|
||||
"switch",
|
||||
{ data_type => "inet", is_nullable => 0 },
|
||||
"port",
|
||||
{ data_type => "text", is_nullable => 0 },
|
||||
"active",
|
||||
{ data_type => "boolean", is_nullable => 1 },
|
||||
"oui",
|
||||
{ data_type => "varchar", is_nullable => 1, size => 8 },
|
||||
"time_first",
|
||||
{
|
||||
data_type => "timestamp",
|
||||
default_value => \"current_timestamp",
|
||||
is_nullable => 1,
|
||||
original => { default_value => \"now()" },
|
||||
},
|
||||
"time_recent",
|
||||
{
|
||||
data_type => "timestamp",
|
||||
default_value => \"current_timestamp",
|
||||
is_nullable => 1,
|
||||
original => { default_value => \"now()" },
|
||||
},
|
||||
"time_last",
|
||||
{
|
||||
data_type => "timestamp",
|
||||
default_value => \"current_timestamp",
|
||||
is_nullable => 1,
|
||||
original => { default_value => \"now()" },
|
||||
},
|
||||
"vlan",
|
||||
{ data_type => "text", is_nullable => 0, default_value => '0' },
|
||||
);
|
||||
|
||||
1;
|
||||
@@ -7,6 +7,7 @@ use base 'DBIx::Class::Core';
|
||||
|
||||
__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
|
||||
|
||||
# NOTE this query is in `git grep 'THREE PLACES'`
|
||||
__PACKAGE__->table('port_utilization');
|
||||
__PACKAGE__->result_source_instance->is_virtual(1);
|
||||
__PACKAGE__->result_source_instance->view_definition(<<ENDSQL
|
||||
@@ -17,11 +18,23 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
|
||||
ELSE 0 END) as ports_in_use,
|
||||
sum(CASE WHEN (dp.type != 'propVirtual' AND dp.up_admin != 'up') THEN 1
|
||||
ELSE 0 END) as ports_shutdown,
|
||||
sum(CASE WHEN (dp.type != 'propVirtual' AND dp.up_admin = 'up' AND dp.up != 'up'
|
||||
AND ( age(now(), to_timestamp(extract(epoch from d.last_discover) - (d.uptime - dp.lastchange)/100)) > ?::interval )) THEN 1
|
||||
ELSE 0 END) as ports_free
|
||||
FROM device d LEFT JOIN device_port dp
|
||||
sum(CASE
|
||||
WHEN ( dp.type != 'propVirtual' AND dp.up_admin = 'up' AND dp.up != 'up'
|
||||
AND (age(now(), to_timestamp(extract(epoch from d.last_discover) - (d.uptime/100))) < ?::interval)
|
||||
AND (last_node.time_last IS NULL OR (age(now(), last_node.time_last)) > ?::interval) )
|
||||
THEN 1
|
||||
WHEN ( dp.type != 'propVirtual' AND dp.up_admin = 'up' AND dp.up != 'up'
|
||||
AND (age(now(), to_timestamp(extract(epoch from d.last_discover) - (d.uptime - dp.lastchange)/100)) > ?::interval) )
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END) as ports_free
|
||||
FROM device d
|
||||
LEFT JOIN device_port dp
|
||||
ON d.ip = dp.ip
|
||||
LEFT JOIN
|
||||
( SELECT DISTINCT ON (switch, port) * FROM node
|
||||
ORDER BY switch, port, time_last desc ) AS last_node
|
||||
ON dp.port = last_node.port AND dp.ip = last_node.switch
|
||||
GROUP BY d.dns, d.ip
|
||||
ORDER BY d.dns, d.ip
|
||||
ENDSQL
|
||||
|
||||
@@ -20,6 +20,9 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
|
||||
SELECT username, 'ldap' AS role FROM users
|
||||
WHERE ldap
|
||||
UNION
|
||||
SELECT username, 'radius' AS role FROM users
|
||||
WHERE radius
|
||||
UNION
|
||||
SELECT username, 'api' AS role FROM users
|
||||
WHERE token IS NOT NULL AND token_from IS NOT NULL
|
||||
ENDSQL
|
||||
|
||||
@@ -38,7 +38,7 @@ sub get_distinct_col {
|
||||
|
||||
Returns a ResultSet for DataTables Server-side processing which populates
|
||||
the displayed table. Evaluates the supplied query parameters for filtering,
|
||||
paging, and ordering information. Note: query paramters are expected to be
|
||||
paging, and ordering information. Note: query parameters are expected to be
|
||||
passed as a reference to an expanded hash of hashes.
|
||||
|
||||
Filtering if present, will generate simple LIKE matching conditions for each
|
||||
@@ -75,7 +75,7 @@ sub get_datatables_data {
|
||||
Returns the total records, after filtering (i.e. the total number of
|
||||
records after filtering has been applied - not just the number of records
|
||||
being returned for this page of data) for a datatables ResultSet and
|
||||
query parameters. Note: query paramters are expected to be passed as a
|
||||
query parameters. Note: query parameters are expected to be passed as a
|
||||
reference to an expanded hash of hashes.
|
||||
|
||||
=cut
|
||||
|
||||
@@ -12,7 +12,7 @@ __PACKAGE__->load_components(qw/
|
||||
|
||||
=head2 skipped( $backend?, $max_deferrals?, $retry_after? )
|
||||
|
||||
Retuns a correlated subquery for the set of C<device_skip> entries that apply
|
||||
Returns a correlated subquery for the set of C<device_skip> entries that apply
|
||||
to some jobs. They match the device IP, current backend, and job action.
|
||||
|
||||
Pass the C<backend> FQDN (or the current host will be used as a default), the
|
||||
|
||||
@@ -187,11 +187,11 @@ Will match exactly the C<model> field.
|
||||
|
||||
=item os
|
||||
|
||||
Will match exactly the C<os> field, which is the operating sytem.
|
||||
Will match exactly the C<os> field, which is the operating system.
|
||||
|
||||
=item os_ver
|
||||
|
||||
Will match exactly the C<os_ver> field, which is the operating sytem software version.
|
||||
Will match exactly the C<os_ver> field, which is the operating system software version.
|
||||
|
||||
=item vendor
|
||||
|
||||
@@ -226,21 +226,20 @@ sub search_by_field {
|
||||
}
|
||||
|
||||
# For Search on Layers
|
||||
my @layer_search = ( '_', '_', '_', '_', '_', '_', '_' );
|
||||
# @layer_search is computer indexed, left->right
|
||||
my $layers = $p->{layers};
|
||||
my @layer_select = ();
|
||||
if ( defined $layers && ref $layers ) {
|
||||
foreach my $layer (@$layers) {
|
||||
next unless defined $layer and length($layer);
|
||||
next if ( $layer < 1 || $layer > 7 );
|
||||
$layer_search[ $layer - 1 ] = 1;
|
||||
push @layer_select,
|
||||
\[ 'substring(me.layers,9-?, 1)::int = 1', $layer ];
|
||||
}
|
||||
}
|
||||
elsif ( defined $layers ) {
|
||||
$layer_search[ $layers - 1 ] = 1;
|
||||
push @layer_select,
|
||||
\[ 'substring(me.layers,9-?, 1)::int = 1', $layers ];
|
||||
}
|
||||
# the database field is in order 87654321
|
||||
my $layer_string = join( '', reverse @layer_search );
|
||||
|
||||
return $rs
|
||||
->search_rs({}, $attrs)
|
||||
@@ -252,8 +251,6 @@ sub search_by_field {
|
||||
{ '-ilike' => "\%$p->{location}\%" }) : ()),
|
||||
($p->{description} ? ('me.description' =>
|
||||
{ '-ilike' => "\%$p->{description}\%" }) : ()),
|
||||
($p->{layers} ? ('me.layers' =>
|
||||
{ '-ilike' => "\%$layer_string" }) : ()),
|
||||
|
||||
($p->{model} ? ('me.model' =>
|
||||
{ '-in' => $p->{model} }) : ()),
|
||||
@@ -264,6 +261,8 @@ sub search_by_field {
|
||||
($p->{vendor} ? ('me.vendor' =>
|
||||
{ '-in' => $p->{vendor} }) : ()),
|
||||
|
||||
($p->{layers} ? (-or => \@layer_select) : ()),
|
||||
|
||||
($p->{dns} ? (
|
||||
-or => [
|
||||
'me.dns' => { '-ilike' => "\%$p->{dns}\%" },
|
||||
|
||||
@@ -40,7 +40,7 @@ sub with_times {
|
||||
});
|
||||
}
|
||||
|
||||
=head2 with_free_ports
|
||||
=head2 with_is_free
|
||||
|
||||
This is a modifier for any C<search()> (including the helpers below) which
|
||||
will add the following additional synthesized columns to the result set:
|
||||
@@ -67,12 +67,13 @@ sub with_is_free {
|
||||
->search({},
|
||||
{
|
||||
'+columns' => { is_free =>
|
||||
\["me.up != 'up' and "
|
||||
."age(now(), to_timestamp(extract(epoch from device.last_discover) "
|
||||
."- (device.uptime - me.lastchange)/100)) "
|
||||
."> ?::interval",
|
||||
[{} => $interval]] },
|
||||
join => 'device',
|
||||
# NOTE this query is in `git grep 'THREE PLACES'`
|
||||
\["me.up_admin = 'up' AND me.up != 'up' AND me.type != 'propVirtual' AND "
|
||||
."((age(now(), to_timestamp(extract(epoch from device.last_discover) - (device.uptime/100))) < ?::interval "
|
||||
."AND (last_node.time_last IS NULL OR age(now(), last_node.time_last) > ?::interval)) "
|
||||
."OR age(now(), to_timestamp(extract(epoch from device.last_discover) - (device.uptime - me.lastchange)/100)) > ?::interval)",
|
||||
[{} => $interval],[ {} => $interval],[ {} => $interval]] },
|
||||
join => [qw/device last_node/],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,14 +97,23 @@ sub only_free_ports {
|
||||
->search_rs($cond, $attrs)
|
||||
->search(
|
||||
{
|
||||
'me.up' => { '!=' => 'up' },
|
||||
},{
|
||||
where =>
|
||||
\["age(now(), to_timestamp(extract(epoch from device.last_discover) "
|
||||
."- (device.uptime - me.lastchange)/100)) "
|
||||
."> ?::interval",
|
||||
# NOTE this query is in `git grep 'THREE PLACES'`
|
||||
'me.up_admin' => 'up',
|
||||
'me.up' => { '!=' => 'up' },
|
||||
'me.type' => { '!=' => 'propVirtual' },
|
||||
-or => [
|
||||
-and => [
|
||||
\["age(now(), to_timestamp(extract(epoch from device.last_discover) - (device.uptime/100))) < ?::interval",
|
||||
[{} => $interval]],
|
||||
-or => [
|
||||
'last_node.time_last' => undef,
|
||||
\["age(now(), last_node.time_last) > ?::interval", [{} => $interval]],
|
||||
]
|
||||
],
|
||||
\["age(now(), to_timestamp(extract(epoch from device.last_discover) - (device.uptime - me.lastchange)/100)) > ?::interval",
|
||||
[{} => $interval]],
|
||||
join => 'device' },
|
||||
],
|
||||
},{ join => [qw/device last_node/] },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,19 @@ sub jq_warm_thrusters {
|
||||
actionset => $actionset{$_},
|
||||
}, { key => 'primary' }) for keys %actionset;
|
||||
});
|
||||
|
||||
# fix up the pseudo devices which need layer 3
|
||||
# TODO remove this after next release
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my @hosts = grep { defined }
|
||||
map { schema('netdisco')->resultset('Device')->search_for_device($_->{only}) }
|
||||
grep { exists $_->{only} and ref '' eq ref $_->{only} }
|
||||
grep { exists $_->{driver} and $_->{driver} eq 'cli' }
|
||||
@{ setting('device_auth') };
|
||||
|
||||
$_->update({ layers => \[q{overlay(layers placing '1' from 6 for 1)}] })
|
||||
for @hosts;
|
||||
});
|
||||
}
|
||||
|
||||
sub jq_getsome {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package App::Netdisco::SSHCollector::Platform::ACE;
|
||||
|
||||
# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4:
|
||||
|
||||
=head1 NAME
|
||||
|
||||
App::Netdisco::SSHCollector::Platform::ACE
|
||||
@@ -13,7 +11,7 @@ virtual contexts with individual ARP tables. Contexts are enumerated
|
||||
with C<show context>, afterwards the commands C<changeto CONTEXTNAME> and
|
||||
C<show arp> must be executed for every context.
|
||||
|
||||
The IOS shell does not permit to combine mulitple commands in a single
|
||||
The IOS shell does not permit to combine multiple commands in a single
|
||||
line, and Net::OpenSSH uses individual connections for individual commands,
|
||||
so we need to use Expect to execute the changeto and show commands in
|
||||
the same context.
|
||||
@@ -36,7 +34,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ C<enable> status after login:
|
||||
To use an C<enable> password separate from the login password, add an
|
||||
C<enable_password> under C<device_auth> tag in your configuration file:
|
||||
|
||||
device_auth:
|
||||
- tag: sshasa
|
||||
driver: cli
|
||||
platform: ASA
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
enable_password: myenablepass
|
||||
device_auth:
|
||||
- tag: sshasa
|
||||
driver: cli
|
||||
platform: ASA
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
enable_password: myenablepass
|
||||
|
||||
=cut
|
||||
|
||||
@@ -43,7 +43,7 @@ use Moo;
|
||||
Retrieve ARP and neighbor entries from device. C<$host> is the hostname or IP
|
||||
address of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ This collector uses "C<arp>" as the command for the arp utility on your
|
||||
system. Clish "C<show arp>" does not work correctly in versions prior to R77.30.
|
||||
Config example:
|
||||
|
||||
device_auth:
|
||||
- tag: sshcpvsx
|
||||
driver: cli
|
||||
platform: CPVSX
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
expert_password: letmein2
|
||||
device_auth:
|
||||
- tag: sshcpvsx
|
||||
driver: cli
|
||||
platform: CPVSX
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
expert_password: letmein2
|
||||
|
||||
|
||||
=cut
|
||||
|
||||
@@ -12,14 +12,14 @@ This collector uses "C<arp>" as the command for the arp utility on your
|
||||
system. If you wish to specify an absolute path, then add an C<arp_command>
|
||||
item to your configuration:
|
||||
|
||||
device_auth:
|
||||
- tag: sshfreebsd
|
||||
driver: cli
|
||||
platform: FreeBSD
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
arp_command: '/usr/sbin/arp'
|
||||
device_auth:
|
||||
- tag: sshfreebsd
|
||||
driver: cli
|
||||
platform: FreeBSD
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
arp_command: '/usr/sbin/arp'
|
||||
|
||||
=cut
|
||||
|
||||
@@ -39,7 +39,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -7,21 +7,21 @@ App::Netdisco::SSHCollector::Platform::GAIAEmbedded
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Collect ARP entries from Checkpoint GAIA embedded Systems
|
||||
To get this Plugin to work you have to add an User like 'netdisco' with
|
||||
'Network admin' right in the GAIA embedded OS
|
||||
To get this Plugin to work you have to add a user like 'netdisco' with
|
||||
'Network admin' rights in the GAIA embedded OS.
|
||||
|
||||
This collector uses "C<arp>" as the command for the arp utility on your
|
||||
system. If you wish to specify an absolute path, then add an C<arp_command>
|
||||
system. If you wish to specify an absolute path, then add an C<arp_command>
|
||||
item to your configuration:
|
||||
|
||||
device_auth:
|
||||
- tag: sshgaia
|
||||
driver: cli
|
||||
platform: GAIAEmbedded
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
arp_command: 'arp'
|
||||
device_auth:
|
||||
- tag: sshgaia
|
||||
driver: cli
|
||||
platform: GAIAEmbedded
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
arp_command: 'arp'
|
||||
|
||||
=cut
|
||||
|
||||
@@ -41,7 +41,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ This collector uses "C<arp>" as the command for the arp utility on your
|
||||
system. If you wish to specify an absolute path, then add an C<arp_command>
|
||||
item to your configuration:
|
||||
|
||||
device_auth:
|
||||
- tag: sshlinux
|
||||
driver: cli
|
||||
platform: Linux
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
arp_command: '/usr/sbin/arp'
|
||||
device_auth:
|
||||
- tag: sshlinux
|
||||
driver: cli
|
||||
platform: Linux
|
||||
only: '192.0.2.1'
|
||||
username: oliver
|
||||
password: letmein
|
||||
arp_command: '/usr/sbin/arp'
|
||||
|
||||
=cut
|
||||
|
||||
@@ -39,7 +39,7 @@ use Moo;
|
||||
Retrieve ARP entries from device. C<$host> is the hostname or IP address
|
||||
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
|
||||
|
||||
Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>.
|
||||
Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -58,8 +58,11 @@ Returns C<undef> if the connection fails.
|
||||
sub reader_for {
|
||||
my ($class, $ip, $useclass) = @_;
|
||||
my $device = get_device($ip) or return undef;
|
||||
return undef if $device->in_storage and $device->is_pseudo;
|
||||
|
||||
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));
|
||||
@@ -104,8 +107,11 @@ Returns C<undef> if the connection fails.
|
||||
sub writer_for {
|
||||
my ($class, $ip, $useclass) = @_;
|
||||
my $device = get_device($ip) or return undef;
|
||||
return undef if $device->in_storage and $device->is_pseudo;
|
||||
|
||||
my $writers = $class->instance->writers or return undef;
|
||||
return $writers->{$device->ip} if exists $writers->{$device->ip};
|
||||
|
||||
debug sprintf 'snmp writer cache warm: [%s]', $device->ip;
|
||||
return ($writers->{$device->ip}
|
||||
= _snmp_connect_generic('write', $device, $useclass));
|
||||
|
||||
@@ -158,6 +158,8 @@ 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.
|
||||
|
||||
Also checks if the device is a pseudo device (vendor is C<netdisco>).
|
||||
|
||||
Returns false if the host is not permitted to discover the target device.
|
||||
|
||||
=cut
|
||||
@@ -168,6 +170,9 @@ sub is_discoverable {
|
||||
$remote_type ||= '';
|
||||
$remote_cap ||= [];
|
||||
|
||||
return _bail_msg("is_discoverable: $device is pseudo-device")
|
||||
if $device->is_pseudo;
|
||||
|
||||
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
|
||||
@@ -192,9 +197,8 @@ sub is_discoverable {
|
||||
|
||||
=head2 is_discoverable_now( $ip, $device_type? )
|
||||
|
||||
Same as C<is_discoverable>, but also checks the last_discover field if the
|
||||
device is in storage, and returns false if that host has been too recently
|
||||
discovered.
|
||||
Same as C<is_discoverable>, but also compares the C<last_discover> field
|
||||
of the C<device> to the C<discover_min_age> configuration.
|
||||
|
||||
Returns false if the host is not permitted to discover the target device.
|
||||
|
||||
@@ -222,6 +226,8 @@ the local configuration to arpnip the device.
|
||||
The configuration items C<arpnip_no> and C<arpnip_only> are checked
|
||||
against the given IP.
|
||||
|
||||
Also checks if the device reports layer 3 capability.
|
||||
|
||||
Returns false if the host is not permitted to arpnip the target device.
|
||||
|
||||
=cut
|
||||
@@ -230,6 +236,9 @@ sub is_arpnipable {
|
||||
my $ip = shift;
|
||||
my $device = get_device($ip) or return 0;
|
||||
|
||||
return _bail_msg("is_arpnipable: $device has no layer 3 capability")
|
||||
unless $device->has_layer(3);
|
||||
|
||||
return _bail_msg("is_arpnipable: $device matched arpnip_no")
|
||||
if check_acl_no($device, 'arpnip_no');
|
||||
|
||||
@@ -241,9 +250,8 @@ sub is_arpnipable {
|
||||
|
||||
=head2 is_arpnipable_now( $ip )
|
||||
|
||||
Same as C<is_arpnipable>, but also checks the last_arpnip field if the
|
||||
device is in storage, and returns false if that host has been too recently
|
||||
arpnipped.
|
||||
Same as C<is_arpnipable>, but also compares the C<last_arpnip> field
|
||||
of the C<device> to the C<arpnip_min_age> configuration.
|
||||
|
||||
Returns false if the host is not permitted to arpnip the target device.
|
||||
|
||||
@@ -271,6 +279,8 @@ the local configuration to macsuck the device.
|
||||
The configuration items C<macsuck_no> and C<macsuck_only> are checked
|
||||
against the given IP.
|
||||
|
||||
Also checks if the device reports layer 2 capability.
|
||||
|
||||
Returns false if the host is not permitted to macsuck the target device.
|
||||
|
||||
=cut
|
||||
@@ -279,6 +289,9 @@ sub is_macsuckable {
|
||||
my $ip = shift;
|
||||
my $device = get_device($ip) or return 0;
|
||||
|
||||
return _bail_msg("is_macsuckable: $device has no layer 2 capability")
|
||||
unless $device->has_layer(2);
|
||||
|
||||
return _bail_msg("is_macsuckable: $device matched macsuck_no")
|
||||
if check_acl_no($device, 'macsuck_no');
|
||||
|
||||
@@ -290,9 +303,8 @@ sub is_macsuckable {
|
||||
|
||||
=head2 is_macsuckable_now( $ip )
|
||||
|
||||
Same as C<is_macsuckable>, but also checks the last_macsuck field if the
|
||||
device is in storage, and returns false if that host has been too recently
|
||||
macsucked.
|
||||
Same as C<is_macsuckable>, but also compares the C<last_macsuck> field
|
||||
of the C<device> to the C<macsuck_min_age> configuration.
|
||||
|
||||
Returns false if the host is not permitted to macsuck the target device.
|
||||
|
||||
|
||||
@@ -59,13 +59,20 @@ ajax qr{/ajax/control/admin/(?:\w+/)?delete} => require_role setting('defanged_a
|
||||
get '/admin/*' => require_role admin => sub {
|
||||
my ($tag) = splat;
|
||||
|
||||
# trick the ajax into working as if this were a tabbed page
|
||||
params->{tab} = $tag;
|
||||
if (exists setting('_admin_tasks')->{ $tag }) {
|
||||
# trick the ajax into working as if this were a tabbed page
|
||||
params->{tab} = $tag;
|
||||
|
||||
var(nav => 'admin');
|
||||
template 'admintask', {
|
||||
task => setting('_admin_tasks')->{ $tag },
|
||||
};
|
||||
var(nav => 'admin');
|
||||
template 'admintask', {
|
||||
task => setting('_admin_tasks')->{ $tag },
|
||||
};
|
||||
}
|
||||
else {
|
||||
var('notfound' => true);
|
||||
status 'not_found';
|
||||
template 'index';
|
||||
}
|
||||
};
|
||||
|
||||
true;
|
||||
|
||||
@@ -13,6 +13,7 @@ use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Passphrase;
|
||||
use Digest::MD5;
|
||||
use Net::LDAP;
|
||||
use Authen::Radius;
|
||||
use Try::Tiny;
|
||||
|
||||
sub authenticate_user {
|
||||
@@ -103,9 +104,20 @@ sub match_password {
|
||||
my $settings = $self->realm_settings;
|
||||
my $username_column = $settings->{users_username_column} || 'username';
|
||||
|
||||
return $user->ldap
|
||||
? $self->match_with_ldap($password, $user->$username_column)
|
||||
: $self->match_with_local_pass($password, $user);
|
||||
my $pwmatch_result = 0;
|
||||
my $username = $user->$username_column;
|
||||
|
||||
if ($user->ldap) {
|
||||
$pwmatch_result = $self->match_with_ldap($password, $username);
|
||||
}
|
||||
elsif ($user->radius) {
|
||||
$pwmatch_result = $self->match_with_radius($password, $username);
|
||||
}
|
||||
else {
|
||||
$pwmatch_result = $self->match_with_local_pass($password, $user);
|
||||
}
|
||||
|
||||
return $pwmatch_result;
|
||||
}
|
||||
|
||||
sub match_with_local_pass {
|
||||
@@ -215,4 +227,28 @@ sub _ldap_search {
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub match_with_radius {
|
||||
my($self, $pass, $user) = @_;
|
||||
return unless setting('radius') and ref {} eq ref setting('radius');
|
||||
|
||||
my $conf = setting('radius');
|
||||
my $radius = Authen::Radius->new(Host => $conf->{server}, Secret => $conf->{secret});
|
||||
# my $dict_dir = Path::Class::Dir->new( dist_dir('App-Netdisco') )
|
||||
# ->subdir('radius_dictionaries')->stringify;
|
||||
Authen::Radius->load_dictionary(); # put $dict_dir in here once it's useful
|
||||
|
||||
$radius->add_attributes(
|
||||
{ Name => 'User-Name', Value => $user },
|
||||
{ Name => 'User-Password', Value => $pass },
|
||||
{ Name => 'h323-return-code', Value => '0' }, # Cisco AV pair
|
||||
{ Name => 'Digest-Attributes', Value => { Method => 'REGISTER' } }
|
||||
);
|
||||
$radius->send_packet(ACCESS_REQUEST);
|
||||
|
||||
my $type = $radius->recv_packet();
|
||||
my $radius_return = ($type eq ACCESS_ACCEPT) ? 1 : 0;
|
||||
|
||||
return $radius_return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -36,7 +36,7 @@ ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
|
||||
ip => param('ip'),
|
||||
dns => param('dns'),
|
||||
vendor => 'netdisco',
|
||||
layers => '00000100',
|
||||
layers => param('layers'),
|
||||
last_discover => \'now()',
|
||||
});
|
||||
return unless $device;
|
||||
@@ -87,6 +87,9 @@ ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
|
||||
})->delete;
|
||||
}
|
||||
}
|
||||
|
||||
# also set layers
|
||||
$device->update({layers => param('layers')});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ ajax '/ajax/control/admin/users/add' => require_role setting('defanged_admin') =
|
||||
password => _make_password(param('password')),
|
||||
fullname => param('fullname'),
|
||||
ldap => (param('ldap') ? \'true' : \'false'),
|
||||
radius => (param('radius') ? \'true' : \'false'),
|
||||
port_control => (param('port_control') ? \'true' : \'false'),
|
||||
admin => (param('admin') ? \'true' : \'false'),
|
||||
note => param('note'),
|
||||
@@ -71,6 +72,7 @@ ajax '/ajax/control/admin/users/update' => require_role setting('defanged_admin'
|
||||
: ()),
|
||||
fullname => param('fullname'),
|
||||
ldap => (param('ldap') ? \'true' : \'false'),
|
||||
radius => (param('radius') ? \'true' : \'false'),
|
||||
port_control => (param('port_control') ? \'true' : \'false'),
|
||||
admin => (param('admin') ? \'true' : \'false'),
|
||||
note => param('note'),
|
||||
|
||||
@@ -31,7 +31,7 @@ get '/ajax/content/device/ports' => require_login sub {
|
||||
# change wildcard chars to SQL
|
||||
$f =~ s/\*/%/g;
|
||||
$f =~ s/\?/_/g;
|
||||
# set wilcards at param boundaries
|
||||
# set wildcards at param boundaries
|
||||
if ($f !~ m/[%_]/) {
|
||||
$f =~ s/^\%*/%/;
|
||||
$f =~ s/\%*$/%/;
|
||||
@@ -82,6 +82,8 @@ get '/ajax/content/device/ports' => require_login sub {
|
||||
});
|
||||
}
|
||||
delete $port_state{free};
|
||||
# showing free ports requires showing down ports
|
||||
++$port_state{down};
|
||||
}
|
||||
|
||||
if (scalar keys %port_state < 3) {
|
||||
|
||||
@@ -47,7 +47,7 @@ get '/ajax/content/report/nodevendor/data' => require_login sub {
|
||||
my $match = $vendor eq 'blank' ? undef : $vendor;
|
||||
|
||||
$rs = $rs->search( { 'oui.abbrev' => $match },
|
||||
{ '+columns' => [qw/ device.dns device.name oui.abbrev /],
|
||||
{ '+columns' => [qw/ device.dns device.name oui.abbrev oui.company /],
|
||||
join => [qw/ oui device /],
|
||||
collapse => 1,
|
||||
});
|
||||
@@ -86,7 +86,7 @@ get '/ajax/content/report/nodevendor' => require_login sub {
|
||||
my $match = $vendor eq 'blank' ? undef : $vendor;
|
||||
|
||||
$rs = $rs->search( { 'oui.abbrev' => $match },
|
||||
{ '+columns' => [qw/ device.dns device.name oui.abbrev /],
|
||||
{ '+columns' => [qw/ device.dns device.name oui.abbrev oui.company /],
|
||||
join => [qw/ oui device /],
|
||||
collapse => 1,
|
||||
});
|
||||
@@ -102,9 +102,9 @@ get '/ajax/content/report/nodevendor' => require_login sub {
|
||||
$rs = $rs->search(
|
||||
{ },
|
||||
{ join => 'oui',
|
||||
select => [ 'oui.abbrev', { count => {distinct => 'me.mac'}} ],
|
||||
as => [qw/ vendor count /],
|
||||
group_by => [qw/ oui.abbrev /]
|
||||
select => [ 'oui.abbrev', 'oui.company', { count => {distinct => 'me.mac'}} ],
|
||||
as => [qw/ abbrev vendor count /],
|
||||
group_by => [qw/ oui.abbrev oui.company /]
|
||||
}
|
||||
)->order_by( { -desc => 'count' } );
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ get '/ajax/content/report/portutilization' => require_login sub {
|
||||
my $age_num = param('age_num') || 3;
|
||||
my $age_unit = param('age_unit') || 'months';
|
||||
my @results = schema('netdisco')->resultset('Virtual::PortUtilization')
|
||||
->search(undef, { bind => [ "$age_num $age_unit" ] })->hri->all;
|
||||
->search(undef, { bind => [ "$age_num $age_unit", "$age_num $age_unit", "$age_num $age_unit" ] })->hri->all;
|
||||
|
||||
if (request->is_ajax) {
|
||||
my $json = to_json (\@results);
|
||||
|
||||
@@ -6,6 +6,7 @@ use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use NetAddr::IP::Lite ':lower';
|
||||
use Regexp::Common 'net';
|
||||
use NetAddr::MAC ();
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
@@ -23,10 +24,14 @@ ajax '/ajax/content/search/node' => require_login sub {
|
||||
my ( $start, $end ) = param('daterange') =~ m/(\d+-\d+-\d+)/gmx;
|
||||
|
||||
my $mac = NetAddr::MAC->new(mac => $node);
|
||||
undef $mac if ($mac and $mac->as_ieee and ($mac->as_ieee eq '00:00:00:00'));
|
||||
my @active = (param('archived') ? () : (-bool => 'active'));
|
||||
undef $mac if
|
||||
($mac and $mac->as_ieee
|
||||
and (($mac->as_ieee eq '00:00:00:00:00:00')
|
||||
or ($mac->as_ieee !~ m/$RE{net}{MAC}/)));
|
||||
|
||||
my @active = (param('archived') ? () : (-bool => 'active'));
|
||||
my (@times, @wifitimes, @porttimes);
|
||||
|
||||
if ( $start and $end ) {
|
||||
$start = $start . ' 00:00:00';
|
||||
$end = $end . ' 23:59:59';
|
||||
|
||||
@@ -6,6 +6,7 @@ use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Util::Web 'sql_match';
|
||||
use Regexp::Common 'net';
|
||||
use NetAddr::MAC ();
|
||||
|
||||
hook 'before_template' => sub {
|
||||
@@ -39,7 +40,11 @@ get '/search' => require_login sub {
|
||||
my $nd = $s->resultset('Device')->search_fuzzy($q);
|
||||
my ($likeval, $likeclause) = sql_match($q);
|
||||
my $mac = NetAddr::MAC->new($q);
|
||||
undef $mac if ($mac and $mac->as_ieee and ($mac->as_ieee eq '00:00:00:00'));
|
||||
|
||||
undef $mac if
|
||||
($mac and $mac->as_ieee
|
||||
and (($mac->as_ieee eq '00:00:00:00:00:00')
|
||||
or ($mac->as_ieee !~ m/$RE{net}{MAC}/)));
|
||||
|
||||
if ($nd and $nd->count) {
|
||||
if ($nd->count == 1) {
|
||||
|
||||
@@ -16,9 +16,6 @@ register_worker({ phase => 'check' }, sub {
|
||||
return Status->error("arpnip skipped: $device not yet discovered")
|
||||
unless $device->in_storage;
|
||||
|
||||
return Status->info("arpnip skipped: $device has no layer 3 capability")
|
||||
unless $device->has_layer(3);
|
||||
|
||||
return Status->info("arpnip skipped: $device is not arpnipable")
|
||||
unless is_arpnipable_now($device);
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
|
||||
push @{ vars->{'v6arps'} },
|
||||
@{get_arps_snmp($device, $snmp->ipv6_n2p_mac, $snmp->ipv6_n2p_addr) };
|
||||
|
||||
$device->update({layers => \[q{overlay(layers placing '1' from 6 for 1)}]});
|
||||
return Status->done("Gathered arp caches from $device");
|
||||
});
|
||||
|
||||
@@ -82,24 +83,25 @@ sub get_arps_snmp {
|
||||
}
|
||||
|
||||
register_worker({ phase => 'main', driver => 'cli' }, sub {
|
||||
my ($job, $workerconf) = @_;
|
||||
my ($job, $workerconf) = @_;
|
||||
|
||||
my $device = $job->device;
|
||||
my $cli = App::Netdisco::Transport::SSH->session_for($device)
|
||||
or return Status->defer("arpnip failed: could not SSH connect to $device");
|
||||
my $device = $job->device;
|
||||
my $cli = App::Netdisco::Transport::SSH->session_for($device)
|
||||
or return Status->defer("arpnip failed: could not SSH connect to $device");
|
||||
|
||||
# should be both v4 and v6
|
||||
my @arps = @{ get_arps_cli($device, [$cli->arpnip]) };
|
||||
# should be both v4 and v6
|
||||
my @arps = @{ get_arps_cli($device, [$cli->arpnip]) };
|
||||
|
||||
# cache v4 arp table
|
||||
push @{ vars->{'v4arps'} },
|
||||
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 32 } @arps;
|
||||
# cache v4 arp table
|
||||
push @{ vars->{'v4arps'} },
|
||||
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 32 } @arps;
|
||||
|
||||
# cache v6 neighbor cache
|
||||
push @{ vars->{'v6arps'} },
|
||||
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 128 } @arps;
|
||||
# cache v6 neighbor cache
|
||||
push @{ vars->{'v6arps'} },
|
||||
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 128 } @arps;
|
||||
|
||||
return Status->done("Gathered arp caches from $device");
|
||||
$device->update({layers => \[q{overlay(layers placing '1' from 6 for 1)}]});
|
||||
return Status->done("Gathered arp caches from $device");
|
||||
});
|
||||
|
||||
sub get_arps_cli {
|
||||
|
||||
@@ -16,9 +16,6 @@ register_worker({ phase => 'check' }, sub {
|
||||
return Status->error("discover failed: no device param (need -d ?)")
|
||||
if $device->ip eq '0.0.0.0';
|
||||
|
||||
return Status->info("discover skipped: $device is pseudo-device")
|
||||
if $device->is_pseudo;
|
||||
|
||||
# runner has already called get_device to promote $job->device
|
||||
return $job->cancel("fresh discover cancelled: $device already known")
|
||||
if $device->in_storage
|
||||
|
||||
@@ -95,7 +95,7 @@ port relationships.
|
||||
The Device database object can be a fresh L<DBIx::Class::Row> object which is
|
||||
not yet stored to the database.
|
||||
|
||||
A list of discovererd neighbors will be returned as [C<$ip>, C<$type>] tuples.
|
||||
A list of discovered neighbors will be returned as [C<$ip>, C<$type>] tuples.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -16,12 +16,6 @@ register_worker({ phase => 'check' }, sub {
|
||||
return Status->error("macsuck skipped: $device not yet discovered")
|
||||
unless $device->in_storage;
|
||||
|
||||
return Status->info("macsuck skipped: $device is pseudo-device")
|
||||
if $device->is_pseudo;
|
||||
|
||||
return Status->info("macsuck skipped: $device has no layer 2 capability")
|
||||
unless $device->has_layer(2);
|
||||
|
||||
return Status->info("macsuck skipped: $device is not macsuckable")
|
||||
unless is_macsuckable_now($device);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
|
||||
debug sprintf ' [%s] macsuck - %s updated forwarding table entries',
|
||||
$device->ip, $total_nodes;
|
||||
|
||||
# a use for $now ... need to archive dissapeared nodes
|
||||
# a use for $now ... need to archive disappeared nodes
|
||||
my $archived = 0;
|
||||
|
||||
if (setting('node_freshness')) {
|
||||
@@ -105,7 +105,7 @@ All four fields in the tuple are required. If you don't know the VLAN ID,
|
||||
Netdisco supports using ID "0".
|
||||
|
||||
Optionally, a fifth argument can be the literal string passed to the time_last
|
||||
field of the database record. If not provided, it defauls to C<now()>.
|
||||
field of the database record. If not provided, it defaults to C<now()>.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ email config and creating the repository with C<rancid-cvs>.
|
||||
=head2 C<rancid_conf>
|
||||
|
||||
The location where the rancid configuration (F<rancid.types.base> and
|
||||
F<rancid.types.conf>) is installed. It will be used to check the existance
|
||||
F<rancid.types.conf>) is installed. It will be used to check the existence
|
||||
of device types before exporting the devices to the rancid configuration. If no match
|
||||
is found the device will not be added to rancid.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user