Merge branch 'master' into og-multiple-domain-suffix
This commit is contained in:
37
.github/issue_template.md
vendored
37
.github/issue_template.md
vendored
@@ -1,12 +1,33 @@
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
<!---
|
||||
|
||||
<!-- stop! If your ticket is about a device not being detected correctly, -->
|
||||
<!-- see SNMP::Info: https://github.com/netdisco/snmp-info/issues/new -->
|
||||
READ THIS FIRST!
|
||||
----------------
|
||||
|
||||
<!-- stop! If you have new MIBs to submit, -->
|
||||
<!-- see netdisco-mibs: https://github.com/netdisco/netdisco-mibs/issues/new -->
|
||||
STOP! If your ticket is about a device not being detected correctly,
|
||||
see SNMP::Info: https://github.com/netdisco/snmp-info/issues/new
|
||||
|
||||
STOP! If you have new MIBs to submit,
|
||||
see netdisco-mibs: https://github.com/netdisco/netdisco-mibs/issues/new
|
||||
|
||||
STOP! If you are running a netdisco docker setup,
|
||||
see netdisco-docker: https://github.com/netdisco/netdisco-docker/issues/new
|
||||
|
||||
|
||||
|
||||
everything else about Netdisco's behaviour is good, here :-D
|
||||
|
||||
the more info you can provide, the easier it is for us the help you, so please
|
||||
fill out as many of the items below as possible.
|
||||
|
||||
Provide a general summary of the issue in the Title above
|
||||
|
||||
when including netdisco config snippets, whitespace matters since it's a yaml file
|
||||
for github issues it really helps if you include the relevant config parts in a codeblock (code fencing)
|
||||
see the "code" subject on https://guides.github.com/features/mastering-markdown/ for that)
|
||||
this should preserve spaces in the issue tracker and make troubleshooting quicker
|
||||
|
||||
-->
|
||||
|
||||
<!-- everything else about Netdisco's behaviour is good, here :-D -->
|
||||
|
||||
## Expected Behavior
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
@@ -37,6 +58,10 @@
|
||||
* Netdisco version used:
|
||||
* SNMP::Info version used:
|
||||
|
||||
## Config info (deployment.yml)
|
||||
<!--- if possible include all options you added to your deployment.yml file, since -->
|
||||
<!--- some options can change the behaviour in drastic ways -->
|
||||
|
||||
## Device information
|
||||
<!--- if the issue relates to specific devices their info would be usefull -->
|
||||
<!--- do note that the following command might contain sensitive info, you can -->
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,3 +15,7 @@ _build
|
||||
blib
|
||||
!.docker/hooks/*
|
||||
.idea
|
||||
node_modules/*
|
||||
yarn.lock
|
||||
package.json
|
||||
.stylelintrc
|
||||
|
||||
@@ -2,6 +2,8 @@ language: perl
|
||||
perl:
|
||||
- "5.30"
|
||||
- "5.10"
|
||||
os: linux
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -15,7 +17,7 @@ branches:
|
||||
- /^2\.\d{6}$/
|
||||
- 'master'
|
||||
install:
|
||||
- cpanm --quiet --notest PkgConfig Test::CChecker Alien::zlib::Static Alien::OpenSSL::Static Alien::SNMP
|
||||
- cpanm --quiet --notest https://github.com/egiles/test-compile/archive/v2.1.2.tar.gz PkgConfig Test::CChecker Alien::zlib::Static Alien::OpenSSL::Static Alien::SNMP
|
||||
script: |
|
||||
perl Build.PL && \
|
||||
./Build && \
|
||||
|
||||
1
Build.PL
1
Build.PL
@@ -26,6 +26,7 @@ Module::Build->new(
|
||||
'App::cpanminus' => '1.6108',
|
||||
'App::local::lib::helper' => '0.07',
|
||||
'Archive::Extract' => '0',
|
||||
'Authen::Radius' => '0',
|
||||
'CGI::Expand' => '2.05',
|
||||
'Data::Printer' => '0',
|
||||
'DBD::Pg' => '0',
|
||||
|
||||
24
LICENCE
24
LICENCE
@@ -1,24 +0,0 @@
|
||||
Copyright (c) 2012, The Netdisco Developer Team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Netdisco Project nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE NETDISCO DEVELOPER TEAM BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
29
LICENSE.md
Normal file
29
LICENSE.md
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2019, The Netdisco Developer Team.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
6
MANIFEST
6
MANIFEST
@@ -62,6 +62,7 @@ lib/App/Netdisco/DB/Result/Virtual/DevicePoeStatus.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/DevicePortSpeed.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/DuplexMismatch.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/GenericReport.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/LastNode.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/NodeIp4.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/NodeIp6.pm
|
||||
lib/App/Netdisco/DB/Result/Virtual/NodeMonitor.pm
|
||||
@@ -237,7 +238,7 @@ lib/App/Netdisco/Worker/Plugin/Vlan/Core.pm
|
||||
lib/App/Netdisco/Worker/Runner.pm
|
||||
lib/App/Netdisco/Worker/Status.pm
|
||||
lib/Dancer/Template/NetdiscoTemplateToolkit.pm
|
||||
LICENCE
|
||||
LICENSE.md
|
||||
MANIFEST This list of files
|
||||
META.json
|
||||
META.yml
|
||||
@@ -318,6 +319,7 @@ share/public/javascripts/netdisco_portcontrol.js
|
||||
share/public/javascripts/portsort.js
|
||||
share/public/javascripts/toastr.js
|
||||
share/public/javascripts/underscore.min.js
|
||||
share/radius_dictionaries/TODO
|
||||
share/schema_versions/App-Netdisco-DB-1-2-PostgreSQL.sql
|
||||
share/schema_versions/App-Netdisco-DB-10-11-PostgreSQL.sql
|
||||
share/schema_versions/App-Netdisco-DB-11-12-PostgreSQL.sql
|
||||
@@ -371,6 +373,7 @@ share/schema_versions/App-Netdisco-DB-54-55-PostgreSQL.sql
|
||||
share/schema_versions/App-Netdisco-DB-55-56-PostgreSQL.sql
|
||||
share/schema_versions/App-Netdisco-DB-56-57-PostgreSQL.sql
|
||||
share/schema_versions/App-Netdisco-DB-57-58-PostgreSQL.sql
|
||||
share/schema_versions/App-Netdisco-DB-58-59-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
|
||||
@@ -505,6 +508,7 @@ share/views/sidebar/search/device.tt
|
||||
share/views/sidebar/search/node.tt
|
||||
share/views/sidebar/search/port.tt
|
||||
xt/00-compile.t
|
||||
xt/01-local-pod.t
|
||||
xt/10-sort_port.t
|
||||
xt/11-portsort.t
|
||||
xt/20-checkacl.t
|
||||
|
||||
12
META.json
12
META.json
@@ -4,7 +4,7 @@
|
||||
"Oliver Gorwits <oliver@cpan.org>"
|
||||
],
|
||||
"dynamic_config" : 1,
|
||||
"generated_by" : "Module::Build version 0.4224",
|
||||
"generated_by" : "Module::Build version 0.4229",
|
||||
"license" : [
|
||||
"bsd"
|
||||
],
|
||||
@@ -39,6 +39,7 @@
|
||||
"App::cpanminus" : "1.6108",
|
||||
"App::local::lib::helper" : "0.07",
|
||||
"Archive::Extract" : "0",
|
||||
"Authen::Radius" : "0",
|
||||
"CGI::Expand" : "2.05",
|
||||
"DBD::Pg" : "0",
|
||||
"DBIx::Class" : "0.082841",
|
||||
@@ -143,7 +144,7 @@
|
||||
},
|
||||
"App::Netdisco::DB" : {
|
||||
"file" : "lib/App/Netdisco/DB.pm",
|
||||
"version" : "58"
|
||||
"version" : "59"
|
||||
},
|
||||
"App::Netdisco::DB::ExplicitLocking" : {
|
||||
"file" : "lib/App/Netdisco/DB/ExplicitLocking.pm"
|
||||
@@ -268,6 +269,9 @@
|
||||
"App::Netdisco::DB::Result::Virtual::GenericReport" : {
|
||||
"file" : "lib/App/Netdisco/DB/Result/Virtual/GenericReport.pm"
|
||||
},
|
||||
"App::Netdisco::DB::Result::Virtual::LastNode" : {
|
||||
"file" : "lib/App/Netdisco/DB/Result/Virtual/LastNode.pm"
|
||||
},
|
||||
"App::Netdisco::DB::Result::Virtual::NodeIp4" : {
|
||||
"file" : "lib/App/Netdisco/DB/Result/Virtual/NodeIp4.pm"
|
||||
},
|
||||
@@ -804,7 +808,7 @@
|
||||
},
|
||||
"homepage" : "http://netdisco.org/",
|
||||
"license" : [
|
||||
"http://opensource.org/licenses/BSD-3-Clause"
|
||||
"http://opensource.org/licenses/bsd-license.php"
|
||||
],
|
||||
"repository" : {
|
||||
"url" : "https://github.com/netdisco/netdisco"
|
||||
@@ -813,5 +817,5 @@
|
||||
"x_MailingList" : "https://lists.sourceforge.net/lists/listinfo/netdisco-users"
|
||||
},
|
||||
"version" : "2.042010",
|
||||
"x_serialization_backend" : "JSON::PP version 2.97001"
|
||||
"x_serialization_backend" : "JSON::PP version 4.02"
|
||||
}
|
||||
|
||||
9
META.yml
9
META.yml
@@ -14,7 +14,7 @@ configure_requires:
|
||||
DBIx::Class: '0.082810'
|
||||
Module::Build: '0.42'
|
||||
dynamic_config: 1
|
||||
generated_by: 'Module::Build version 0.4224, CPAN::Meta::Converter version 2.150010'
|
||||
generated_by: 'Module::Build version 0.4229, CPAN::Meta::Converter version 2.150010'
|
||||
license: bsd
|
||||
meta-spec:
|
||||
url: http://module-build.sourceforge.net/META-spec-v1.4.html
|
||||
@@ -38,7 +38,7 @@ provides:
|
||||
file: lib/App/Netdisco/Configuration.pm
|
||||
App::Netdisco::DB:
|
||||
file: lib/App/Netdisco/DB.pm
|
||||
version: '58'
|
||||
version: '59'
|
||||
App::Netdisco::DB::ExplicitLocking:
|
||||
file: lib/App/Netdisco/DB/ExplicitLocking.pm
|
||||
App::Netdisco::DB::Result::Admin:
|
||||
@@ -121,6 +121,8 @@ provides:
|
||||
file: lib/App/Netdisco/DB/Result/Virtual/DuplexMismatch.pm
|
||||
App::Netdisco::DB::Result::Virtual::GenericReport:
|
||||
file: lib/App/Netdisco/DB/Result/Virtual/GenericReport.pm
|
||||
App::Netdisco::DB::Result::Virtual::LastNode:
|
||||
file: lib/App/Netdisco/DB/Result/Virtual/LastNode.pm
|
||||
App::Netdisco::DB::Result::Virtual::NodeIp4:
|
||||
file: lib/App/Netdisco/DB/Result/Virtual/NodeIp4.pm
|
||||
App::Netdisco::DB::Result::Virtual::NodeIp6:
|
||||
@@ -483,6 +485,7 @@ requires:
|
||||
App::cpanminus: '1.6108'
|
||||
App::local::lib::helper: '0.07'
|
||||
Archive::Extract: '0'
|
||||
Authen::Radius: '0'
|
||||
CGI::Expand: '2.05'
|
||||
DBD::Pg: '0'
|
||||
DBIx::Class: '0.082841'
|
||||
@@ -556,7 +559,7 @@ resources:
|
||||
MailingList: https://lists.sourceforge.net/lists/listinfo/netdisco-users
|
||||
bugtracker: https://github.com/netdisco/netdisco/issues
|
||||
homepage: http://netdisco.org/
|
||||
license: http://opensource.org/licenses/BSD-3-Clause
|
||||
license: http://opensource.org/licenses/bsd-license.php
|
||||
repository: https://github.com/netdisco/netdisco
|
||||
version: '2.042010'
|
||||
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
|
||||
|
||||
@@ -71,7 +71,7 @@ these is an optional service which the user is asked to confirm.
|
||||
Pre-existing requirements are that there be a database table created and a
|
||||
user with rights to create tables in that database. Both the table and user
|
||||
name must match those configured in your environment YAML file (default
|
||||
C<~/environments/deployment.yml>).
|
||||
F<~/environments/deployment.yml>).
|
||||
|
||||
This script will download the latest MAC address vendor prefix data from the
|
||||
Internet, and update the OUI table in the database. Hence Internet access is
|
||||
@@ -80,10 +80,17 @@ required to run the script.
|
||||
Similarly the latest Netdisco MIB bundle is also downloaded and placed into
|
||||
the user's home directory (or C<$ENV{NETDISCO_HOME}>).
|
||||
|
||||
If you upgrade Netdisco make sure you run this script again to make sure
|
||||
your config remains compatible.
|
||||
|
||||
Before each upgrade also review the
|
||||
L<Release notes|https://github.com/netdisco/netdisco/wiki/Release-Notes> since
|
||||
additional steps might be required!
|
||||
|
||||
=cut
|
||||
|
||||
print color 'bold cyan';
|
||||
say 'This is the Netdisco II deployment script.';
|
||||
say 'This is the Netdisco 2 deployment script.';
|
||||
say '';
|
||||
say 'Before we continue, the following prerequisites must be in place:';
|
||||
say ' * Database added to PostgreSQL for Netdisco';
|
||||
@@ -92,6 +99,11 @@ say ' * "~/environments/deployment.yml" file configured with Database dsn/user/p
|
||||
say ' * A full backup of any existing Netdisco database data';
|
||||
say ' * Internet access (for OUIs and MIBs)';
|
||||
say '';
|
||||
say 'If you are upgrading Netdisco 2 read the release notes:';
|
||||
say 'https://github.com/netdisco/netdisco/wiki/Release-Notes';
|
||||
say 'There you will find required and incompatible changes';
|
||||
say 'which are not covered by this script.';
|
||||
say '';
|
||||
say 'You will be asked to confirm all changes to your system.';
|
||||
say '';
|
||||
print color 'reset';
|
||||
@@ -194,13 +206,13 @@ sub deploy_db {
|
||||
}
|
||||
|
||||
sub get_userpass {
|
||||
my $term = shift;
|
||||
my $name = $term->get_reply(prompt => 'Username: ');
|
||||
my $pass = $term->get_reply(prompt => 'Password: ');
|
||||
my $upterm = shift;
|
||||
my $name = $upterm->get_reply(prompt => 'Username: ');
|
||||
my $pass = $upterm->get_reply(prompt => 'Password: ');
|
||||
|
||||
unless ($name and $pass) {
|
||||
say 'username and password cannot be empty, please try again.';
|
||||
($name, $pass) = get_userpass($term);
|
||||
($name, $pass) = get_userpass($upterm);
|
||||
}
|
||||
|
||||
return ($name, $pass);
|
||||
@@ -257,7 +269,7 @@ sub deploy_oui {
|
||||
print color 'reset';
|
||||
}
|
||||
|
||||
# This subroutine is from Wireshark's make-manuf
|
||||
# This subroutine is based on Wireshark's make-manuf
|
||||
# http://anonsvn.wireshark.org/wireshark/trunk/tools/make-manuf
|
||||
sub shorten {
|
||||
my $manuf = shift;
|
||||
@@ -271,22 +283,27 @@ sub shorten {
|
||||
# & isn't needed when Standalone
|
||||
$manuf =~ s/ \& / /g;
|
||||
|
||||
# remove junk whitespace
|
||||
$manuf =~ s/\s+/ /g;
|
||||
|
||||
# Remove any "the", "inc", "plc" ...
|
||||
$manuf
|
||||
=~ s/\s(the|inc|incorporated|plc|systems|corp|corporation|s\/a|a\/s|ab|ag|kg|gmbh|co|company|limited|ltd|holding|spa)(?= )//gi;
|
||||
=~ s/\s(?:the|inc|incorporated|plc|systems|corp|corporation|s\/a|a\/s|ab|ag|kg|gmbh|co|company|limited|ltd|holding|spa)(?= )//gi;
|
||||
|
||||
# Convert to consistent case
|
||||
$manuf =~ s/(\w+)/\u\L$1/g;
|
||||
|
||||
# Remove all spaces
|
||||
$manuf =~ s/\s+//g;
|
||||
|
||||
# Deviating from make-manuf for HP
|
||||
$manuf =~ s/Hewlett[-]?Packard/Hp/;
|
||||
|
||||
# Truncate all names to a reasonable length, say, 8 characters.
|
||||
# If the string contains UTF-8, this may be substantially more than 8 bytes.
|
||||
$manuf = substr( $manuf, 0, 8 );
|
||||
# Truncate all names to first two words max 20 chars
|
||||
if (length($manuf) > 21) {
|
||||
my @twowords = grep {defined} (split ' ', $manuf)[0 .. 1];
|
||||
$manuf = join ' ', @twowords;
|
||||
}
|
||||
|
||||
# Remove all spaces
|
||||
$manuf =~ s/\s+//g;
|
||||
|
||||
return encode( "utf8", $manuf );
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -20,8 +20,9 @@ database:
|
||||
# RECOMMENDED SETTINGS
|
||||
# --------------------
|
||||
|
||||
# SNMP community string(s)
|
||||
# ````````````````````````
|
||||
# Device authentication settings
|
||||
# define snmp communities and ssh credentials here
|
||||
# ````````````````````````````````````````````````
|
||||
device_auth:
|
||||
- tag: 'default_v2_readonly'
|
||||
community: 'public'
|
||||
@@ -50,7 +51,7 @@ device_auth:
|
||||
# SNMP, which just clogs up the job queue.
|
||||
# ```````````````````````````````````````````````````````````````
|
||||
#discover_waps: true
|
||||
#disover_phones: false
|
||||
#discover_phones: false
|
||||
|
||||
# this is the schedule for automatically keeping netdisco up-to-date;
|
||||
# these are good defaults, so only uncomment if needing to change.
|
||||
|
||||
@@ -245,6 +245,13 @@ td > form.nd_inline-form {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* badge for pseudo devices layer three toggle */
|
||||
.nd_layer-three-link {
|
||||
text-decoration: none !important;
|
||||
display: inline-block;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
/* for the job control admin page play/pause links */
|
||||
#nd_countdown-refresh:hover, #nd_countdown-control:hover {
|
||||
text-decoration: none;
|
||||
@@ -359,7 +366,7 @@ td > form.nd_inline-form {
|
||||
.container-fluid > .nd_sidebar {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
width: 200px;
|
||||
width: 205px;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
|
||||
0
share/radius_dictionaries/TODO
Normal file
0
share/radius_dictionaries/TODO
Normal file
11
share/schema_versions/App-Netdisco-DB-58-59-PostgreSQL.sql
Normal file
11
share/schema_versions/App-Netdisco-DB-58-59-PostgreSQL.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users ADD COLUMN "radius" boolean DEFAULT false;
|
||||
|
||||
UPDATE device SET layers = NULL WHERE vendor = 'netdisco';
|
||||
|
||||
UPDATE device SET layers = '00000000' WHERE layers IS NULL;
|
||||
|
||||
ALTER TABLE device ALTER layers SET DEFAULT '00000000';
|
||||
|
||||
COMMIT;
|
||||
@@ -4,6 +4,7 @@
|
||||
<th class="nd_center-cell">Device Name</th>
|
||||
<th class="nd_center-cell">Device IP</th>
|
||||
<th class="nd_center-cell">Number of Ports</th>
|
||||
<th class="nd_center-cell">Services</th>
|
||||
<th class="nd_center-cell">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -11,7 +12,12 @@
|
||||
<tr>
|
||||
<td class="nd_center-cell"><input data-form="add" name="dns" type="text"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" name="ip" type="text"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" name="ports" type="number"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" name="ports" type="number" value="1"></td>
|
||||
<td class="nd_center-cell">
|
||||
<span class="badge"> </span><span class="badge"> </span>
|
||||
<a class="nd_layer-three-link" href="#" rel="tooltip" data-placement="bottom" data-offset="3" data-title="Enable Arpnip"><span class="badge">3</span></a><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span>
|
||||
<input data-form="add" name="layers" type="hidden" value="00000000">
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<button class="btn btn-small nd_adminbutton" name="add" type="submit"><i class="icon-plus-sign"></i> Add</button>
|
||||
</td>
|
||||
@@ -26,6 +32,11 @@
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="ports" type="number" value="[% row.port_count | html_entity %]">
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<span class="badge"> </span><span class="badge"> </span>
|
||||
<a class="nd_layer-three-link" href="#" rel="tooltip" data-placement="bottom" data-offset="3" data-title="Enable Arpnip"><span class="badge[% ' badge-success' IF row.layers.substr(5,1) %]">3</span></a><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span>
|
||||
<input data-form="update" name="layers" type="hidden" value="[% row.layers | html_entity %]">
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="dns" type="hidden" value="[% row.dns | html_entity %]">
|
||||
<input data-form="update" name="ip" type="hidden" value="[% row.ip | html_entity %]">
|
||||
@@ -68,6 +79,17 @@ $(document).ready(function() {
|
||||
} ],
|
||||
[% INCLUDE 'ajax/datatabledefaults.tt' -%]
|
||||
} );
|
||||
$('.nd_layer-three-link').click(function() {
|
||||
var badge = $(this).children('span').first();
|
||||
var layers = $(this).parent().children('input').first();
|
||||
$(badge).toggleClass('badge-success');
|
||||
if ($(badge).hasClass('badge-success')) {
|
||||
$(layers).attr('value', '00000100');
|
||||
}
|
||||
else {
|
||||
$(layers).attr('value', '00000000');
|
||||
}
|
||||
});
|
||||
} );
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<th class="nd_center-cell">Username</th>
|
||||
<th class="nd_center-cell">Password</th>
|
||||
<th class="nd_center-cell">LDAP Auth</th>
|
||||
<th class="nd_center-cell">RADIUS Auth</th>
|
||||
<th class="nd_center-cell">Port Control</th>
|
||||
<th class="nd_center-cell">Administrator</th>
|
||||
<th class="nd_center-cell">Created</th>
|
||||
@@ -16,15 +17,16 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="nd_center-cell"><input data-form="add" name="fullname" type="text"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" name="username" type="text"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" name="password" type="password"></td>
|
||||
<td class="nd_center-cell"><input class="span2" data-form="add" name="username" type="text"></td>
|
||||
<td class="nd_center-cell"><input class="span2" data-form="add" name="password" type="password"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="ldap"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="radius"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="port_control"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="admin"></td>
|
||||
<td class="nd_center-cell"></td>
|
||||
<td class="nd_center-cell"></td>
|
||||
<td class="nd_center-cell"><input data-form="add" name="note" type="text"></td>
|
||||
<td class="nd_center-cell">
|
||||
<td class="nd_center-cell"><input class="span2" data-form="add" name="note" type="text"></td>
|
||||
<td nowrap class="nd_center-cell">
|
||||
<button class="btn btn-small nd_adminbutton" name="add" type="submit"><i class="icon-plus-sign"></i> Add</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -37,14 +39,17 @@
|
||||
<input data-form="update" name="fullname" type="text" value="[% row.fullname | html_entity %]">
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="username" type="text" value="[% row.username | html_entity %]">
|
||||
<input class="span2" data-form="update" name="username" type="text" value="[% row.username | html_entity %]">
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="password" type="password" value="********">
|
||||
<input class="span2" data-form="update" name="password" type="password" value="********">
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="ldap" type="checkbox" [% ' checked="checked"' IF row.ldap %]>
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="radius" type="checkbox" [% ' checked="checked"' IF row.radius %]>
|
||||
</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="port_control" type="checkbox" [% ' checked="checked"' IF row.port_control %]>
|
||||
</td>
|
||||
@@ -54,10 +59,10 @@
|
||||
<td class="nd_center-cell">[% row.created | html_entity %]</td>
|
||||
<td class="nd_center-cell">[% row.last_seen | html_entity %]</td>
|
||||
<td class="nd_center-cell">
|
||||
<input data-form="update" name="note" type="text" value="[% row.note | html_entity %]">
|
||||
<input class="span2" data-form="update" name="note" type="text" value="[% row.note | html_entity %]">
|
||||
</td>
|
||||
|
||||
<td class="nd_center-cell">
|
||||
<td nowrap class="nd_center-cell">
|
||||
<button class="btn nd_adminbutton" name="update" type="submit"><i class="icon-save text-warning"></i></button>
|
||||
|
||||
<button class="btn" data-toggle="modal"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[% USE CSV -%]
|
||||
[% CSV.dump([ 'Full Name' 'Username'
|
||||
'LDAP Auth' 'Port Control' 'Administrator' 'Created'
|
||||
'LDAP Auth' 'RADIUS Auth' 'Port Control' 'Administrator' 'Created'
|
||||
'Last Login' 'Note']) %]
|
||||
|
||||
[% FOREACH row IN results %]
|
||||
@@ -8,6 +8,7 @@
|
||||
[% mylist.push(row.fullname) %]
|
||||
[% mylist.push(row.username) %]
|
||||
[% mylist.push(row.ldap) %]
|
||||
[% mylist.push(row.radius) %]
|
||||
[% mylist.push(row.port_control) %]
|
||||
[% mylist.push(row.admin) %]
|
||||
[% mylist.push(row.created) %]
|
||||
|
||||
@@ -37,9 +37,13 @@
|
||||
[% ELSIF row.error_disable_cause %]
|
||||
<i class="icon-exclamation-sign text-error icon-large"></i>
|
||||
[% ELSIF row.has_column_loaded('is_free') AND row.is_free %]
|
||||
<i class="icon-arrow-down text-success icon-large"></i>
|
||||
<i class="icon-circle-arrow-down text-success icon-large"></i>
|
||||
[% ELSIF row.up_admin == 'up' AND (row.up != 'up' AND row.up != 'dormant') %]
|
||||
<i class="icon-arrow-down text-error icon-large"></i>
|
||||
[% IF params.port_state == 'free' %]
|
||||
<i class="icon-circle-arrow-down text-success icon-large"></i>
|
||||
[% ELSE %]
|
||||
<i class="icon-arrow-down text-error icon-large"></i>
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
<i class="icon-angle-up text-success icon-large"></i>
|
||||
[% END %]
|
||||
@@ -244,7 +248,7 @@
|
||||
<i class="icon-off nd_power-on"></i>
|
||||
[% END %]
|
||||
<span>
|
||||
[% IF row.power.power > 0 %]
|
||||
[% IF row.power.power AND row.power.power > 0 %]
|
||||
[% row.power.power | html_entity %] mW
|
||||
[% ELSE %]
|
||||
([% row.power.status | html_entity %])
|
||||
|
||||
@@ -43,7 +43,7 @@ $(document).ready(function() {
|
||||
}, {
|
||||
"data": 'oui.abbrev',
|
||||
"render": function(data, type, row, meta) {
|
||||
return '<a href="[% uri_for('/report/nodevendor') %]?vendor=' + encodeURIComponent(data || 'blank') + '">' + he.encode(data ||'(Unknown Vendor)') + '</a>';
|
||||
return '<a href="[% uri_for('/report/nodevendor') %]?vendor=' + encodeURIComponent(row.oui.abbrev || 'blank') + '">' + he.encode(row.oui.company ||'(Unknown Vendor)') + '</a>';
|
||||
}
|
||||
}, {
|
||||
"data": 'port',
|
||||
@@ -71,7 +71,7 @@ $(document).ready(function() {
|
||||
{
|
||||
"data": 'vendor',
|
||||
"render": function(data, type, row, meta) {
|
||||
return '<a href="[% uri_for('/report/nodevendor') %]?vendor=' + encodeURIComponent(data || 'blank') + '">' + he.encode(data ||'(Unknown Vendor)') + '</a>';
|
||||
return '<a href="[% uri_for('/report/nodevendor') %]?vendor=' + encodeURIComponent(row.abbrev || 'blank') + '">' + he.encode(row.vendor ||'(Unknown Vendor)') + '</a>';
|
||||
}
|
||||
}, {
|
||||
"data": 'count',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[% USE CSV -%]
|
||||
[% IF opt %]
|
||||
[% CSV.dump(['MAC' 'Vendor' 'Company' 'Device' 'Port']) %]
|
||||
[% CSV.dump(['MAC' 'Company' 'Device' 'Port']) %]
|
||||
|
||||
[% FOREACH row IN results %]
|
||||
[% mylist = [] %]
|
||||
[% device = row.device.dns || row.device.name || row.switch %]
|
||||
[% FOREACH col IN [ row.mac.upper row.oui.abbrev row.oui.company device row.port ] %]
|
||||
[% FOREACH col IN [ row.mac.upper row.oui.company device row.port ] %]
|
||||
[% mylist.push(col) %]
|
||||
[% END %]
|
||||
[% CSV.dump(mylist) %]
|
||||
|
||||
@@ -71,8 +71,9 @@
|
||||
,minLength: 0
|
||||
});
|
||||
|
||||
// activate modals
|
||||
// activate modals and tooltips
|
||||
$('.nd_modal').modal({show: false});
|
||||
$("[rel=tooltip]").tooltip({live: true});
|
||||
}
|
||||
|
||||
// on load, establish global delegations for now and future
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
[% session.logged_in_fullname || session.logged_in_user | html_entity %] <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
[% IF NOT user_has_role('ldap') %]
|
||||
[% IF NOT ( user_has_role('ldap') OR user_has_role('radius') ) %]
|
||||
<li><a href="[% uri_for('/password') %]">Change Password</a></li>
|
||||
[% END %]
|
||||
[% IF NOT settings.no_auth %]
|
||||
|
||||
@@ -34,10 +34,12 @@
|
||||
<ul class="icons-ul"><!-- nd_inputs-list unstyled"> -->
|
||||
<li><i class="icon-li icon-angle-up text-success"></i> Link Up</li>
|
||||
<li><i class="icon-li icon-arrow-down text-error"></i> Link Down</li>
|
||||
<li><i class="icon-li icon-arrow-down text-success"></i> Port Free</li>
|
||||
<li><i class="icon-li icon-circle-arrow-down text-success"></i> Port Free</li>
|
||||
<li><i class="icon-li icon-remove"></i> Admin Disabled</li>
|
||||
<li><i class="icon-li icon-exclamation-sign text-error"></i> Error Disabled</li>
|
||||
<li><i class="icon-li icon-ban-circle text-info"></i> Blocking</li>
|
||||
<li><i class="icon-li icon-off"></i> PoE Disabled</li>
|
||||
<li><i class="icon-li icon-off nd_power-on"></i> PoE Enabled</li>
|
||||
<li><i class="icon-li icon-link text-warning"></i> Manual Topology</li>
|
||||
<li><i class="icon-li icon-link"></i> Neighbor Device</li>
|
||||
<li><i class="icon-li icon-unlink text-error"></i> Neighbor Inacessible</li>
|
||||
|
||||
8
xt/01-local-pod.t
Normal file
8
xt/01-local-pod.t
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More;
|
||||
use Test::Pod;
|
||||
|
||||
all_pod_files_ok();
|
||||
Reference in New Issue
Block a user