update docs to use GitHub wiki
This commit is contained in:
@@ -53,15 +53,15 @@ See the demo at: L<https://netdisco2-demo.herokuapp.com/>
|
|||||||
=back
|
=back
|
||||||
|
|
||||||
We have several other pages with tips for
|
We have several other pages with tips for
|
||||||
L<alternate deployment scenarios|App::Netdisco::Manual::Deployment>,
|
L<alternate deployment scenarios|https://github.com/netdisco/netdisco/wiki/Install-Tips>,
|
||||||
L<understanding and troubleshooting Netdisco|App::Netdisco::Manual::Troubleshooting>,
|
L<understanding and troubleshooting Netdisco|https://github.com/netdisco/netdisco/wiki/Troubleshooting>,
|
||||||
L<tips and tricks for specific platforms|App::Netdisco::Manual::Vendors>,
|
L<tips and tricks for specific platforms|https://github.com/netdisco/netdisco/wiki/Vendor-Tips>,
|
||||||
and L<all the configuration options|App::Netdisco::Manual::Configuration>.
|
and L<all the configuration options|https://github.com/netdisco/netdisco/wiki/Configuration>.
|
||||||
|
|
||||||
You can also speak to someone in the C<#netdisco@freenode> IRC channel, or on
|
You can also speak to someone in the C<#netdisco@freenode> IRC channel, or on
|
||||||
the L<community email list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
the L<community email list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
||||||
Before installing or upgrading please always review the latest
|
Before installing or upgrading please always review the latest
|
||||||
L<Release Notes|App::Netdisco::Manual::ReleaseNotes>.
|
L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||||
|
|
||||||
=head1 Dependencies
|
=head1 Dependencies
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ On Fedora/Red-Hat:
|
|||||||
|
|
||||||
root:~# yum install perl-core perl-DBD-Pg net-snmp-perl net-snmp-devel openssl-devel make automake gcc
|
root:~# yum install perl-core perl-DBD-Pg net-snmp-perl net-snmp-devel openssl-devel make automake gcc
|
||||||
|
|
||||||
On BSD systems please see L<our BSD tips|App::Netdisco::Manual::BSDInstall>.
|
On BSD systems please see L<our BSD tips|https://github.com/netdisco/netdisco/wiki/BSD-Install>.
|
||||||
|
|
||||||
With those installed, please check that your system's clock is correct.
|
With those installed, please check that your system's clock is correct.
|
||||||
|
|
||||||
@@ -118,8 +118,8 @@ The following is a general guide which works well in most circumstances. It
|
|||||||
assumes you have a user C<netdisco> on your system, that you want to perform
|
assumes you have a user C<netdisco> on your system, that you want to perform
|
||||||
an on-line installation, and have the application run self-contained from
|
an on-line installation, and have the application run self-contained from
|
||||||
within that user's home. There are alternatives: see the
|
within that user's home. There are alternatives: see the
|
||||||
L<Deployment|App::Netdisco::Manual::Deployment> documentation for further
|
L<Deployment|https://github.com/netdisco/netdisco/wiki/Install-Tips>
|
||||||
details.
|
documentation for further details.
|
||||||
|
|
||||||
To avoid muddying your system, use the following script to download and
|
To avoid muddying your system, use the following script to download and
|
||||||
install Netdisco and its dependencies into the C<netdisco> user's home area
|
install Netdisco and its dependencies into the C<netdisco> user's home area
|
||||||
@@ -160,7 +160,7 @@ uncomment the C<schedule> setting to enable SNMP data gathering from
|
|||||||
devices (this replaces cron jobs in Netdisco 1).
|
devices (this replaces cron jobs in Netdisco 1).
|
||||||
|
|
||||||
Have a quick read of the other settings to make sure you're happy, then move
|
Have a quick read of the other settings to make sure you're happy, then move
|
||||||
on. See L<Configuration|App::Netdisco::Manual::Configuration> for further
|
on. See L<Configuration|https://github.com/netdisco/netdisco/wiki/Configuration> for further
|
||||||
details.
|
details.
|
||||||
|
|
||||||
=head1 Initialisation
|
=head1 Initialisation
|
||||||
@@ -174,7 +174,7 @@ script will take care of all this for you:
|
|||||||
|
|
||||||
If this is a new installation of Netdisco 2, answer yes to all questions. If
|
If this is a new installation of Netdisco 2, answer yes to all questions. If
|
||||||
you wish to deploy without Internet access, see the
|
you wish to deploy without Internet access, see the
|
||||||
L<Deployment|App::Netdisco::Manual::Deployment> documentation.
|
L<Deployment|https://github.com/netdisco/netdisco/wiki/Install-Tips> documentation.
|
||||||
|
|
||||||
=head1 Startup
|
=head1 Startup
|
||||||
|
|
||||||
@@ -196,15 +196,15 @@ C<~netdisco/perl5> directory and re-run the C<curl> command above, to update
|
|||||||
Netdisco's C library bindings.
|
Netdisco's C library bindings.
|
||||||
|
|
||||||
We have several other pages with tips for
|
We have several other pages with tips for
|
||||||
L<alternate deployment scenarios|App::Netdisco::Manual::Deployment>,
|
L<alternate deployment scenarios|https://github.com/netdisco/netdisco/wiki/Install-Tips>,
|
||||||
L<understanding and troubleshooting Netdisco|App::Netdisco::Manual::Troubleshooting>,
|
L<understanding and troubleshooting Netdisco|https://github.com/netdisco/netdisco/wiki/Troubleshooting>,
|
||||||
L<tips and tricks for specific platforms|App::Netdisco::Manual::Vendors>,
|
L<tips and tricks for specific platforms|https://github.com/netdisco/netdisco/wiki/Vendor-Tips>,
|
||||||
and L<all the configuration options|App::Netdisco::Manual::Configuration>.
|
and L<all the configuration options|https://github.com/netdisco/netdisco/wiki/Configuration>.
|
||||||
|
|
||||||
You can also speak to someone in the C<#netdisco@freenode> IRC channel, or on
|
You can also speak to someone in the C<#netdisco@freenode> IRC channel, or on
|
||||||
the L<community email list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
the L<community email list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
||||||
Before installing or upgrading please always review the latest
|
Before installing or upgrading please always review the latest
|
||||||
L<Release Notes|App::Netdisco::Manual::ReleaseNotes>.
|
L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||||
|
|
||||||
=head1 Upgrading from 2.x
|
=head1 Upgrading from 2.x
|
||||||
|
|
||||||
@@ -212,9 +212,8 @@ 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
|
the full installation instructions, above. This process is for upgrading
|
||||||
version 2.x only.
|
version 2.x only.
|
||||||
|
|
||||||
Before upgrading please review the latest L<Release
|
Before upgrading please review the latest L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||||
Notes|App::Netdisco::Manual::ReleaseNotes>. Then the process below should be
|
Then the process below should be run for each installation:
|
||||||
run for each installation:
|
|
||||||
|
|
||||||
# upgrade Netdisco
|
# upgrade Netdisco
|
||||||
~/bin/localenv cpanm --notest App::Netdisco
|
~/bin/localenv cpanm --notest App::Netdisco
|
||||||
@@ -262,18 +261,20 @@ run:
|
|||||||
|
|
||||||
Bundled with this distribution is a L<DBIx::Class> layer for the Netdisco
|
Bundled with this distribution is a L<DBIx::Class> layer for the Netdisco
|
||||||
database. This abstracts away all the SQL into an elegant, re-usable OO
|
database. This abstracts away all the SQL into an elegant, re-usable OO
|
||||||
interface. See the L<Developer|App::Netdisco::Manual::Developing>
|
interface. See the L<Developer|https://github.com/netdisco/netdisco/wiki/Developing>
|
||||||
documentation for further information.
|
documentation for further information.
|
||||||
|
|
||||||
=head2 Plugins
|
=head2 Plugins
|
||||||
|
|
||||||
Netdisco includes a Plugin subsystem for customizing the web user interface.
|
Netdisco includes a Plugin subsystem for customizing the web user interface and backend daemon.
|
||||||
See L<App::Netdisco::Web::Plugin> for further information.
|
See L<Web Plugins|https://github.com/netdisco/netdisco/wiki/Web-Plugins>
|
||||||
|
and L<Backend Plugins|https://github.com/netdisco/netdisco/wiki/Backend-Plugins>
|
||||||
|
for further information.
|
||||||
|
|
||||||
=head2 Developing
|
=head2 Developing
|
||||||
|
|
||||||
Lots of information about the architecture of this application is contained
|
Lots of information about the architecture of this application is contained
|
||||||
within the L<Developer|App::Netdisco::Manual::Developing> documentation.
|
within the L<Developer|https://github.com/netdisco/netdisco/wiki/Developing> documentation.
|
||||||
|
|
||||||
=head1 AUTHOR
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::BSDInstall - BSD Install Instructions
|
|
||||||
|
|
||||||
=head1 Introduction
|
|
||||||
|
|
||||||
This document is compiled from suggestions and comments on the Netdisco mail
|
|
||||||
lists. We're grateful for the help, and if you have any additions please do
|
|
||||||
let the project staff know.
|
|
||||||
|
|
||||||
You could also look at the following guide for FreeBSD 11: L<http://www.davidbolton.com/?p=681>
|
|
||||||
|
|
||||||
=head1 Ports Installs
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Perl (if not already installed)
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
C<p5-DBD-Pg> (will also pull in C<postgresqlXX-client>)
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
C<postgresqlXX-server>
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
C<net-snmp> (should install the Perl binding C<SNMP.pm>)
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
C<openssl>
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 Additional Steps
|
|
||||||
|
|
||||||
=head2 Netdisco User
|
|
||||||
|
|
||||||
pw useradd netdisco -N -m -s /bin/sh -w no
|
|
||||||
|
|
||||||
=head2 PostgreSQL Setup
|
|
||||||
|
|
||||||
/usr/local/etc/rc.d/postgresql initdb
|
|
||||||
/usr/local/etc/rc.d/postgresql start
|
|
||||||
|
|
||||||
Make sure PostgreSQL starts at boot by adding the following to
|
|
||||||
"C</etc/rc.conf>":
|
|
||||||
|
|
||||||
postgresql_enable="YES"
|
|
||||||
|
|
||||||
When installing C<postgresqlXX-server> port, it creates the C<pgsql> user with
|
|
||||||
"C<nologin>" shell. As root, do C<vipw> and change the shell to C</bin/sh> or
|
|
||||||
whichever shell you want, so that you can do the C<createuser> step from the
|
|
||||||
main instructions.
|
|
||||||
|
|
||||||
C<pgtune> doesn't seem to work on NetBSD. This needs looking into. Nothing
|
|
||||||
will break, but it just means the server probably isn't tuned to your system's
|
|
||||||
hardware (RAM, etc).
|
|
||||||
|
|
||||||
=head1 Run Control Script
|
|
||||||
|
|
||||||
# PROVIDE: netdiscoweb
|
|
||||||
# REQUIRE: DAEMON
|
|
||||||
# BEFORE: LOGIN
|
|
||||||
# KEYWORD: shutdown
|
|
||||||
|
|
||||||
rcvar="netdisco_enable"
|
|
||||||
|
|
||||||
See also L<https://www.freebsd.org/doc/en/books/porters-handbook/rc-scripts.html>
|
|
||||||
|
|
||||||
=cut
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,199 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::Deployment - Tips and Tricks for Deployment
|
|
||||||
|
|
||||||
=head1 Init and Run Control Scripts
|
|
||||||
|
|
||||||
The Netdisco applications will generate RC scripts suitable for Linux systems:
|
|
||||||
|
|
||||||
bin/netdisco-web get_init_file
|
|
||||||
bin/netdisco-backend get_init_file
|
|
||||||
|
|
||||||
On C<systemd>-based systems please see L<our systemd
|
|
||||||
guide|App::Netdisco::Manual::Systemd>.
|
|
||||||
|
|
||||||
On BSD systems please see L<our BSD tips|App::Netdisco::Manual::BSDInstall>,
|
|
||||||
and submit patches against the L<Daemon::Control> distribution.
|
|
||||||
|
|
||||||
=head1 Enable MD5 authentication to PostgreSQL
|
|
||||||
|
|
||||||
Some installations of PostgreSQL don't have MD5 authentication enabled by
|
|
||||||
default, which blocks database connections with the default Netdisco
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
If your database and Netdisco are on the same system, then the easiest
|
|
||||||
solution is to comment out the "C<host:>" line in your C<deployment.yml> file.
|
|
||||||
|
|
||||||
Alternatively, reconfigure PostgreSQL to permit MD5 auth for TCP connections
|
|
||||||
by adding the following to your system's "C<pg_hba.conf>" file (and restarting
|
|
||||||
the database service):
|
|
||||||
|
|
||||||
# TYPE DATABASE USER ADDRESS METHOD
|
|
||||||
host all all 127.0.0.1/32 md5
|
|
||||||
|
|
||||||
=head1 Run multiple poller daemons
|
|
||||||
|
|
||||||
A common scenario is that the network is split into security domains (or
|
|
||||||
zones) and one Netdisco poller daemon cannot see all devices.
|
|
||||||
|
|
||||||
You can run multiple pollers, as long as they all connect back to the same
|
|
||||||
PostgreSQL database. Use the C<devices_only> or C<devices_no> configuration
|
|
||||||
settings to control which devices are "seen" by each poller. You can also
|
|
||||||
include only the necessary minimum SNMP community/authentication settings in
|
|
||||||
each poller's configuration.
|
|
||||||
|
|
||||||
Of course you will also need to start the web server somewhere, as well.
|
|
||||||
|
|
||||||
=head1 Connect to PostgreSQL database on non-standard port
|
|
||||||
|
|
||||||
The standard port for PostgreSQL is 5432. To connect on a different port you
|
|
||||||
need to use the C<host> option under C<database:> config in your
|
|
||||||
C<~/environments/deployment.yml> file. For example if connecting to a database
|
|
||||||
on the local server:
|
|
||||||
|
|
||||||
database:
|
|
||||||
name: 'netdisco'
|
|
||||||
user: 'changeme'
|
|
||||||
pass: 'changeme'
|
|
||||||
host: 'localhost;port=5432'
|
|
||||||
|
|
||||||
Obviously, substitute the C<user>, C<pass>, and actual port number for your
|
|
||||||
local values. Note the separator character is a semicolon.
|
|
||||||
|
|
||||||
=head1 Deploy without Internet access
|
|
||||||
|
|
||||||
The C<netdisco-deploy> script asks for Internet access but it is possible to
|
|
||||||
install off-line. You should download the following two files:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
https://raw.githubusercontent.com/netdisco/upstream-sources/master/ieee/oui.txt
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
https://github.com/netdisco/netdisco-mibs/releases/latest (download link is on the page)
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Run the C<netdisco-deploy> script but pass the OUI file name as a parameter on
|
|
||||||
the command line, for example:
|
|
||||||
|
|
||||||
~/bin/netdisco-deploy ./oui.txt
|
|
||||||
|
|
||||||
Then answer yes to questions, even though you're not connected to the
|
|
||||||
Internet.
|
|
||||||
|
|
||||||
For the MIBs you can simply extract the downloaded archive to the home
|
|
||||||
directory of Netdisco, and change the name of the directory to
|
|
||||||
C<netdisco-mibs>.
|
|
||||||
|
|
||||||
=head1 Relocating the Installation
|
|
||||||
|
|
||||||
The installation process installs Netdisco self-contained to your home
|
|
||||||
directory. The target directory can easily be changed by setting the
|
|
||||||
C<NETDISCO_HOME> environment variable, for example:
|
|
||||||
|
|
||||||
export NETDISCO_HOME=/opt/netdisco
|
|
||||||
|
|
||||||
Obviously, you'll need to substitute this wherever you see "C<~>" in the
|
|
||||||
installation instructions. The Netdisco application will use this setting
|
|
||||||
itself to locate files and configuration.
|
|
||||||
|
|
||||||
=head1 Pass Options to the Web Frontend Daemon
|
|
||||||
|
|
||||||
Simply add any options after the "C<start>" command. See other sections of
|
|
||||||
this document for some examples.
|
|
||||||
|
|
||||||
=head1 Non-root Hosting
|
|
||||||
|
|
||||||
Netdisco will assume its web site is hosted at the apex of your server - that
|
|
||||||
is, the document root. To relocate the web application, pass the C<--path>
|
|
||||||
parameter to the web startup script:
|
|
||||||
|
|
||||||
~/bin/netdisco-web start --path=/netdisco2
|
|
||||||
|
|
||||||
Alternatively, can set the C<path> configuration option in your
|
|
||||||
C<deployment.yml> file:
|
|
||||||
|
|
||||||
path: '/netdisco2'
|
|
||||||
|
|
||||||
=head1 Listening Port for the Web Frontend
|
|
||||||
|
|
||||||
Pass the C<--port> parameter to any of the web scripts. For example:
|
|
||||||
|
|
||||||
~/bin/netdisco-web start --port=8080
|
|
||||||
|
|
||||||
=head1 Listening Address for the Web Frontend
|
|
||||||
|
|
||||||
Pass the C<--host> parameter to any of the web scripts. For example:
|
|
||||||
|
|
||||||
~/bin/netdisco-web start --host=127.0.0.1
|
|
||||||
|
|
||||||
=head1 Behind a Proxy
|
|
||||||
|
|
||||||
By default the web application daemon starts listening on port 5000 and goes
|
|
||||||
into the background. This is ideal for hosting behind a web proxy (e.g. Apache
|
|
||||||
with C<mod_proxy>).
|
|
||||||
|
|
||||||
After enabling the C<headers>, C<proxy> and C<proxy_http> modules in Apache, a
|
|
||||||
suitable configuration would be:
|
|
||||||
|
|
||||||
ProxyPreserveHost On
|
|
||||||
ProxyPass / http://localhost:5000/ retry=0 timeout=60
|
|
||||||
ProxyPassReverse / http://localhost:5000/
|
|
||||||
|
|
||||||
ProxyRequests Off
|
|
||||||
<Proxy *>
|
|
||||||
Order allow,deny
|
|
||||||
Allow from all
|
|
||||||
</Proxy>
|
|
||||||
|
|
||||||
To combine this with Non-root Hosting as above, simply change the paths
|
|
||||||
referenced in the configuration, and set C<path> in your C<deployment.yml> as
|
|
||||||
discussed above. Note there is no trailing slash in the Apache config:
|
|
||||||
|
|
||||||
ProxyPass /netdisco2 http://localhost:5000/netdisco2 retry=0 timeout=60
|
|
||||||
ProxyPassReverse /netdisco2 http://localhost:5000/netdisco2
|
|
||||||
|
|
||||||
To delegate user authentication to Apache, use the C<trust_remote_user> or
|
|
||||||
C<trust_x_remote_user> settings. See L<App::Netdisco::Manual::Configuration>
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
=head1 SSL Support
|
|
||||||
|
|
||||||
There is no SSL support in the built-in web server. This is because it's not
|
|
||||||
straightforward to support all the SSL options, and using port 443 requires
|
|
||||||
root privilege, which the Netdisco application should not have.
|
|
||||||
|
|
||||||
You are instead recommended to run C<netdisco-web> behind a reverse proxy as
|
|
||||||
described elsewhere in this document. Apache can easily act as an SSL reverse
|
|
||||||
proxy.
|
|
||||||
|
|
||||||
=head1 Database Backups
|
|
||||||
|
|
||||||
We recommend you backup the Netdisco database regularly. You could put the
|
|
||||||
following commands into a shell script and call it nightly from C<cron>:
|
|
||||||
|
|
||||||
DATE=`date +%Y%m%d`
|
|
||||||
/usr/bin/pg_dump -F c --create -f /path/to/backups/netdisco-pgsql-$DATE.dump netdisco
|
|
||||||
gzip -9f /path/to/backups/netdisco-pgsql-$DATE.dump
|
|
||||||
/usr/bin/find /path/to/backups/ -type f -ctime +30 -exec rm {} \;
|
|
||||||
|
|
||||||
This will keep 30 days of backups. You don't need to stop Netdisco during the
|
|
||||||
backup.
|
|
||||||
|
|
||||||
=head1 Display all Table Rows as Default
|
|
||||||
|
|
||||||
Add the following to your configuration:
|
|
||||||
|
|
||||||
table_pagesize: -1
|
|
||||||
|
|
||||||
=head1 Further Reading...
|
|
||||||
|
|
||||||
Other ways to run and host the web application can be found in the
|
|
||||||
L<Dancer::Deployment> page. See also the L<plackup> and L<starman>
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
@@ -1,501 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::Developing - Notes for contributors
|
|
||||||
|
|
||||||
=head1 DEVELOPER NOTES
|
|
||||||
|
|
||||||
This document aims to help developers understand the intent and design of the
|
|
||||||
code within Netdisco. Patches and feedback are always welcome :-)
|
|
||||||
|
|
||||||
=head1 TLDR; I want to clone git and run the web server.
|
|
||||||
|
|
||||||
First do a normal App::Netdisco install into a dedicated user's home, as per
|
|
||||||
the L<documentation|App::Netdisco>. Then:
|
|
||||||
|
|
||||||
su - netdisco && cd $HOME
|
|
||||||
mkdir git && cd git
|
|
||||||
|
|
||||||
git clone git://git.code.sf.net/p/netdisco/netdisco-ng netdisco-ng
|
|
||||||
cd netdisco-ng/Netdisco
|
|
||||||
|
|
||||||
DBIC_TRACE=1 ~/bin/localenv plackup -R share,lib -p 5001 bin/netdisco-web-fg
|
|
||||||
|
|
||||||
The above creates you a git clone (change the URL if you're a Netdisco
|
|
||||||
Developer) and runs the web server:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
In the foreground
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Using a single process only (no forking)
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
With L<DBIx::Class> tracing
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
On port 5001 so it won't conflict with any already-running web frontend
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Restarts the web server when you save a file in the C<share> or C<lib>
|
|
||||||
directory
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
You might also want to set C<check_userlog> to C<false> in your config to
|
|
||||||
quieten some of the web client callbacks.
|
|
||||||
|
|
||||||
For the backend daemon, it's very similar:
|
|
||||||
|
|
||||||
DBIC_TRACE=1 ~/bin/localenv bin/netdisco-backend-fg
|
|
||||||
|
|
||||||
You can point at a different database without editing C<deployment.yml>:
|
|
||||||
|
|
||||||
NETDISCO_DBNAME=testdb DBIC_TRACE=1 ~/bin/localenv plackup -R share,lib -p 5001 bin/netdisco-web-fg
|
|
||||||
NETDISCO_DBNAME=testdb DBIC_TRACE=1 ~/bin/localenv bin/netdisco-backend-fg
|
|
||||||
|
|
||||||
It's recommended to delete the "C<~/perl5/lib/perl5/App/Netdisco>"
|
|
||||||
directory to avoid accidentally picking up old Netdisco code. For working on
|
|
||||||
L<SNMP::Info> you can similarly delete "C<~/perl5/lib/perl5/SNMP/Info*>" and
|
|
||||||
then symlink from "C<Info.pm>" and "C<Info>" to your git repo. If you pull
|
|
||||||
from upstream and the dependencies have changed, you can install them without
|
|
||||||
re-installing Netdisco itself:
|
|
||||||
|
|
||||||
cd netdisco-ng/Netdisco
|
|
||||||
~/bin/localenv cpanm --installdeps .
|
|
||||||
|
|
||||||
Happy hacking!
|
|
||||||
|
|
||||||
=head1 Introduction
|
|
||||||
|
|
||||||
This release of Netdisco is built as a L<Dancer> application, and uses many
|
|
||||||
modern technologies and techniques. Hopefully this will make the code easier
|
|
||||||
to manage and maintain in the long term.
|
|
||||||
|
|
||||||
Although Dancer is a web application framework, it provides very useful tools
|
|
||||||
for command line applications as well, namely configuration file management
|
|
||||||
and database connection management. We make use of these features in the
|
|
||||||
daemon and deployment scripts.
|
|
||||||
|
|
||||||
Overall the application tries to be as self-contained as possible without also
|
|
||||||
needing an excessive number of CPAN modules to be installed. However, Modern
|
|
||||||
Perl techniques have made dependency management almost a non-issue, and
|
|
||||||
Netdisco can be installed by and run completely within an unprivileged user's
|
|
||||||
account, apart from the PostgreSQL database setup.
|
|
||||||
|
|
||||||
Finally the other core component of Netdisco is now a L<DBIx::Class> layer for
|
|
||||||
database access. This means there is no SQL anywhere in the code, but more
|
|
||||||
important, we can re-use the same complex queries in different parts of
|
|
||||||
Netdisco.
|
|
||||||
|
|
||||||
The rest of this document discusses each "interesting" area of the Netdisco
|
|
||||||
codebase, hopefully in enough detail that you can get hacking yourself :-)
|
|
||||||
|
|
||||||
=head1 Versioning
|
|
||||||
|
|
||||||
This is Netdisco major version 2. The minor version has six digits, which are
|
|
||||||
split into two components of three digits each. It's unlikely that the major
|
|
||||||
version number (2) will increment. Each "significant" release to CPAN will
|
|
||||||
increment the first three digits of the minor version. Each "trivial" release
|
|
||||||
will increment the second three digits of the minor version.
|
|
||||||
|
|
||||||
Beta releases will have a a suffix with an underscore, to prevent CPAN
|
|
||||||
indexing the distribution. Some examples:
|
|
||||||
|
|
||||||
2.002002 - "significant" release 2, second "trivial" release
|
|
||||||
2.002003 - a bug was found and fixed, hence "trivial" release 3
|
|
||||||
2.003000_001 - first beta for the next "significant" release
|
|
||||||
2.003000_002 - second beta
|
|
||||||
2.004000 - the next "significant" release
|
|
||||||
|
|
||||||
The words "significant" and "trivial" are entirely subjective, of course.
|
|
||||||
|
|
||||||
=head1 Global Configuration
|
|
||||||
|
|
||||||
Dancer uses YAML as its standard configuration file format, which is flexible
|
|
||||||
enough for our needs, yet still simple to edit for the user. We no longer need
|
|
||||||
a parser as in the old version of Netdisco.
|
|
||||||
|
|
||||||
At the top of scripts you'll usually see something like:
|
|
||||||
|
|
||||||
use App::Netdisco;
|
|
||||||
use Dancer ':script';
|
|
||||||
|
|
||||||
First, this uses C<App::Netdisco>, which is almost nothing more than a
|
|
||||||
placeholder module (contains no actual application code). What it does is set
|
|
||||||
several environment variables in order to locate the configuration files.
|
|
||||||
|
|
||||||
Then, when we call "C<use Dancer>" these environment variables are used to
|
|
||||||
load two YAML files: C<config.yml> and C<< <environment>.yml >> where
|
|
||||||
C<< <environment> >> is typically either C<deployment> or C<development>.
|
|
||||||
|
|
||||||
The concept of "environments" allows us to have some shared "master" config
|
|
||||||
between all instances of the application (C<config.yml>), and then settings
|
|
||||||
for specific circumstances. Typically this might be logging levels, for
|
|
||||||
example. The default file which C<App::Netdisco> loads is C<deployment.yml>
|
|
||||||
but you can override it by setting the "C<DANCER_ENVIRONMENT>" environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
The file is located in an C<environments> folder which defaults to being in
|
|
||||||
the user's home directory. The name (or full path) of the folder can be
|
|
||||||
overriden using the "C<DANCER_ENVDIR>" environment variable. The location of
|
|
||||||
the folder alone can be overridden using the "C<NETDISCO_HOME>" environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
Dancer loads the config using YAML, merging data from the two files. Config is
|
|
||||||
made available via Dancer's C<setting('foo')> subroutine, which is exported.
|
|
||||||
So now the C<foo> setting in either config file is easily accessed.
|
|
||||||
|
|
||||||
Another line commonly seen in scripts is this:
|
|
||||||
|
|
||||||
use Dancer::Plugin::DBIC 'schema';
|
|
||||||
|
|
||||||
This plugin saves a lot of effort by taking some database connection
|
|
||||||
parameters from the configuration file, and instantiating DBIx::Class database
|
|
||||||
connections with them. The connections are managed transparently so all we
|
|
||||||
need to do to access the Netdisco database, with no additional setup, is:
|
|
||||||
|
|
||||||
schema('netdisco')->resultset(...)->search({...});
|
|
||||||
|
|
||||||
=head1 DBIx::Class Layer
|
|
||||||
|
|
||||||
DBIx::Class, or DBIC for short, is an Object-Relational Mapper. This means it
|
|
||||||
abstracts away the SQL of database calls, presenting a Perl object for each
|
|
||||||
table, set of results from a query, table row, etc. The advantage is that it
|
|
||||||
can generate really smart SQL queries, and these queries can be re-used
|
|
||||||
throughout the application.
|
|
||||||
|
|
||||||
The DBIC layer for Netdisco is based at L<App::Netdisco::DB>. This is the
|
|
||||||
global schema class and below that, under L<App::Netdisco::DB::Result> is a
|
|
||||||
class for each table in the database. These contain metadata on the columns
|
|
||||||
but also several handy "helper" queries which can be called. There are also
|
|
||||||
C<ResultSet> classes which provide additional "pre-canned" queries.
|
|
||||||
|
|
||||||
Netdisco's DBIx::Class layer has excellent documentation which you are
|
|
||||||
encouraged to read, particularly if you find it difficult to sleep.
|
|
||||||
|
|
||||||
=head2 Results and ResultSets
|
|
||||||
|
|
||||||
In DBIC a C<Result> is a table and a C<ResultSet> is a set of rows retrieved
|
|
||||||
from the table as a result of a query (which might be all the rows, of
|
|
||||||
course). This is why we have two types of DBIC class.
|
|
||||||
Items in the C<Result> generally relate to the single table
|
|
||||||
directly, and simply. In the C<ResultSet> class are more complex search
|
|
||||||
modifiers which might synthesize new "columns" of data (e.g. formatting a
|
|
||||||
timestamp) or subroutines which accept parameters to customize the query.
|
|
||||||
|
|
||||||
However, regardless of the actual class name, you access them in the same way.
|
|
||||||
For example the C<device> table has an L<App::Netdisco::DB::Result::Device>
|
|
||||||
class and also an L<App::Netdisco::DB::ResultSet::Device> class. DBIC merges
|
|
||||||
the two:
|
|
||||||
|
|
||||||
schema('netdisco')->resultset('Device')->get_models;
|
|
||||||
|
|
||||||
=head2 Virtual Tables (VIEWs)
|
|
||||||
|
|
||||||
Where we want to simplify our application code even further we can either
|
|
||||||
install a VIEW in PostgreSQL, or use DBIx::Class to synthesize the view
|
|
||||||
on-the-fly. Put simply, it uses the VIEW definition as the basis of an SQL
|
|
||||||
query, yet in the application we treat it as a real table like any other.
|
|
||||||
|
|
||||||
Some good examples are a fake table of only the active Nodes (as opposed to
|
|
||||||
all nodes), or the more complex list of all ports which are connected together
|
|
||||||
(C<DeviceLink>).
|
|
||||||
|
|
||||||
All these tables live under the
|
|
||||||
L<App::Netdisco::DB::Result::Virtual> namespace, and so you
|
|
||||||
access them like so (for the C<ActiveNode> example):
|
|
||||||
|
|
||||||
schema('netdisco')->resultset('Virtual::ActiveNode')->count;
|
|
||||||
|
|
||||||
=head2 Versioning and Deployment
|
|
||||||
|
|
||||||
To manage the Netdisco schema in PostgreSQL we use DBIx::Class's deployment
|
|
||||||
feature. This attaches a version to the schema and provides all the code to
|
|
||||||
check the current version and do whatever is necessary to upgrade.
|
|
||||||
The schema version is stored in a new table called
|
|
||||||
C<dbix_class_schema_versions>, although you should never touch it.
|
|
||||||
|
|
||||||
The C<netdisco-db-deploy> script included in the distribution performs the
|
|
||||||
following services:
|
|
||||||
|
|
||||||
* Installs the dbix_class_schema_versions table
|
|
||||||
* Upgrades the schema to the current distribtion's version
|
|
||||||
|
|
||||||
This works both on an empty, new database, and a legacy database from the
|
|
||||||
existing Netdisco release, in a non-destructive way. For further information
|
|
||||||
see L<DBIx::Class::Schema::Versioned> and the C<netdisco-db-deploy> script.
|
|
||||||
|
|
||||||
The files used for the upgrades are shipped with this distribution and stored
|
|
||||||
in the C<.../App/Netdisco/DB/schema_versions> directory. They are generated
|
|
||||||
using the C<nd-dbic-versions> script which also ships with the distribution.
|
|
||||||
|
|
||||||
=head2 Foreign Key Constraints
|
|
||||||
|
|
||||||
We have not deployed any FK constraints into the Netdisco schema. This is
|
|
||||||
partly because the current poller inserts and deletes entries from the
|
|
||||||
database in an order which would violate such constraints, but also because
|
|
||||||
some of the archiving features of Netdisco might not be compatible anyway.
|
|
||||||
|
|
||||||
=head1 Web Application
|
|
||||||
|
|
||||||
The Netdisco web app is a "classic" Dancer app, using most of the bundled
|
|
||||||
features which make development really easy. Dancer is based on Ruby's Sinatra
|
|
||||||
framework. Its style is for many "helper" subroutines to be exported into the
|
|
||||||
application namespace, to do things such as access request parameters,
|
|
||||||
navigate around the "handler" subroutines, manage response headers, and so on.
|
|
||||||
|
|
||||||
Pretty much anything you want to do in a web application has been wrapped up
|
|
||||||
by Dancer into a neat helper routine that does the heavy lifting. This
|
|
||||||
includes configuration and database connection management, as was discussed
|
|
||||||
above. Also, templates can be executed and Netdisco uses the venerable
|
|
||||||
L<Template::Toolkit> engine for this.
|
|
||||||
|
|
||||||
Like most web frameworks Dancer has a concept of "handlers" which are
|
|
||||||
subroutines to which a specific web request is routed. For example if the user
|
|
||||||
asks for "C</device>" with some parameters, the request ends up at the
|
|
||||||
L<App::Netdisco::Web::Device> package's "C<get '/device'>" handler. All this
|
|
||||||
is done automatically by Dancer according to some simple rules. There are also
|
|
||||||
"wrapper" subroutines which we use to do tasks such as setting up data lookup
|
|
||||||
tables, and handling authentication.
|
|
||||||
|
|
||||||
Dancer also supports AJAX very well, and it is used to retrieve most of the
|
|
||||||
data in the Netdisco web application in a dynamic way, to respond to search
|
|
||||||
queries and avoid lengthy page reloads. You will see the handlers for AJAX
|
|
||||||
look similar to those for GET requests but do not use Template::Toolkit
|
|
||||||
templates.
|
|
||||||
|
|
||||||
Compared to the current Netdisco, the handler routines are very small. This is
|
|
||||||
because (a) they don't include any HTML - this is delegated to a template, and
|
|
||||||
(b) they don't include an SQL - this is delegated to DBIx::Class. Small
|
|
||||||
routines are more manageable, and easier to maintain. You'll also notice use
|
|
||||||
of modules such as L<NetAddr::MAC> and L<NetAddr::IP::Lite> to simplify and make
|
|
||||||
more robust the handling of data.
|
|
||||||
|
|
||||||
In fact, many sections of the web application have been factored out into
|
|
||||||
separate Plugin modules. For more information see the
|
|
||||||
L<App::Netdisco::Web::Plugin> manual page.
|
|
||||||
|
|
||||||
=head2 Running the Web App
|
|
||||||
|
|
||||||
Dancer apps conform to the "PSGI" standard interface for web applications,
|
|
||||||
which makes for easy deployment under many stacks such as Apache, FCGI, etc.
|
|
||||||
See L<Dancer::Deployment> for more detail.
|
|
||||||
|
|
||||||
At a minimum Netdisco can run from within its own user area as an unprivileged
|
|
||||||
user, and actually ships with a fast, preforking web server engine. The
|
|
||||||
C<netdisco-web> script uses L<Daemon::Control> to daemonize this simple web
|
|
||||||
server so you can fire-and-forget the Netdisco web app without much trouble at
|
|
||||||
all. This script in turn calls C<netdisco-web-fg> which is the real Dancer
|
|
||||||
application, that runs in the foreground if called on its own.
|
|
||||||
|
|
||||||
=head2 Authentication
|
|
||||||
|
|
||||||
Session and authentication code lives in L<App::Netdisco::Web::AuthN>. It is
|
|
||||||
fully backwards compatible with the existing Netdisco user management, making
|
|
||||||
use of the database users and their MD5 passwords.
|
|
||||||
|
|
||||||
There is also support for unauthenticated access to the web app (for instance
|
|
||||||
if you have some kind of external authentication, or simply trust everyone).
|
|
||||||
See L<App::Netdisco::Manual::Configuration> for further details.
|
|
||||||
|
|
||||||
=head2 Authorization
|
|
||||||
|
|
||||||
Every Dancer route handler must have proper role based access control enabled,
|
|
||||||
to prevent unauthorized access to Netdisco's data, or admin features. This is
|
|
||||||
done with the L<Dancer::Plugin::Auth::Extensible> module. It handles both the
|
|
||||||
authentication using Netdisco's database, and then protects each route
|
|
||||||
handler. See L<App::Netdisco::Manual::WritingWebPlugins> for details.
|
|
||||||
|
|
||||||
=head2 Templates
|
|
||||||
|
|
||||||
In the C<share/views> folder of this distribution you'll find all the
|
|
||||||
Template::Toolkit template files, with C<.tt> extensions. Dancer first loads
|
|
||||||
C<share/views/layouts/main.tt> which is the main page wrapper, that has the HTML
|
|
||||||
header and so on. It then loads other templates for sections of the page body.
|
|
||||||
This is a typical Template::Toolkit "wrapper" configuration, as noted by the
|
|
||||||
C<[% content %]> call within C<main.tt> that loads the template you actually
|
|
||||||
specified in your Dancer handler.
|
|
||||||
|
|
||||||
All templates (and Javascript and Stylesheets) are shipped in the
|
|
||||||
L<App::Netdisco> distribution and located automatically by the application
|
|
||||||
(using the environment variables which App::Netdisco set up). The user doesn't
|
|
||||||
have to copy or install any files.
|
|
||||||
|
|
||||||
There's a template for the homepage called C<index.tt>, then separate
|
|
||||||
templates for searching, displaying device details, and showing inventory.
|
|
||||||
These are, pretty much, all that Netdisco ever does.
|
|
||||||
|
|
||||||
Each of these pages is designed in a deliberately similar way, with re-used
|
|
||||||
features. They each can have a "sidebar" with a search form (or additional
|
|
||||||
search parameters). They also can have a tabbed interface for sub-topics.
|
|
||||||
|
|
||||||
Here's where it gets interesting. Up till now the page content has been your
|
|
||||||
typical synchronous page load (a single page comprised of many templates) in
|
|
||||||
response to a GET request. However the content of the tabs is not within this.
|
|
||||||
Each tab has its content dynamically retrieved via an AJAX request back to the
|
|
||||||
web application. Javscript triggers this automatically on page load.
|
|
||||||
|
|
||||||
This feature allows the user to search and search again, each time refreshing
|
|
||||||
the data they see in the tab but without reloading the complete page with all
|
|
||||||
its static furniture. AJAX can, of course, return any MIME type, not only JSON
|
|
||||||
but also HTML content as in this case. The templates for the tabs are
|
|
||||||
organised below C<share/views/ajax/...> in the distribution.
|
|
||||||
|
|
||||||
=head2 Stylesheets
|
|
||||||
|
|
||||||
The main style for Netdisco uses Twitter Bootstrap, which is a modern library
|
|
||||||
of CSS and javascript used on many websites. It does a lot of heavy lifting,
|
|
||||||
providing simple CSS classes for all of the standard web page furniture
|
|
||||||
(forms, tables, etc). Check out the documetation at the Twitter Bootstrap web
|
|
||||||
site for more information.
|
|
||||||
|
|
||||||
These stylesheets are of course customised with our own C<netdisco.css>. We
|
|
||||||
try to name all CSS classes with a prefix "C<nd_>" so as to be distinct from
|
|
||||||
Twitter Bootstrap and any other active styles.
|
|
||||||
|
|
||||||
All stylesheets are located in the C<share/public/css> folder of the
|
|
||||||
distribution and, like the templates, are automatically located and served by
|
|
||||||
the Netdisco application. You can also choose to serve this content statically
|
|
||||||
via Apache/etc for high traffic sites.
|
|
||||||
|
|
||||||
Although Twitter Bootstrap ships with its own set of icons, we use an
|
|
||||||
alternative library called Fontawesome. This plugs in easily to Bootstrap and
|
|
||||||
provides a wider range of scaleable vectored icons which are easy to use.
|
|
||||||
|
|
||||||
=head2 Javascript
|
|
||||||
|
|
||||||
Of course many parts of the Netdisco site use Javascript, beginning with
|
|
||||||
retrieving the page tab content itself. The standard library in use is jQuery,
|
|
||||||
and the latest version is shipped with this distribution.
|
|
||||||
|
|
||||||
Many parts of the Netdisco site have small Javscript routines. The code for
|
|
||||||
these, using jQuery as mentioned, lives in two places. The main C<netdisco.js>
|
|
||||||
file is loaded once in the page HTML header, and lives in
|
|
||||||
C<share/public/javascripts/netdisco.js>. There's also a
|
|
||||||
C<netdisco_portcontrol.js> which is included only if the current user has Port
|
|
||||||
Control rights.
|
|
||||||
|
|
||||||
Netdisco also has Javascript routines specific to the device search or device
|
|
||||||
details pages, and these files are located in C<share/views/js/...> because
|
|
||||||
they're loaded within the page body by the templates. These files contain a
|
|
||||||
function C<inner_view_processing> which is called each time AJAX delivers new
|
|
||||||
content into a tab in the page (think of it like a callback, perhaps).
|
|
||||||
|
|
||||||
=head1 Job Daemon
|
|
||||||
|
|
||||||
The old Netdisco has a job control daemon which processes "port control"
|
|
||||||
actions and also manual requests for device polling. The new Netdisco also has
|
|
||||||
a daemon, although it is a true separate process and set of libraries from the
|
|
||||||
web application. However, it still makes use of the Dancer configuration and
|
|
||||||
database connection management features mentioned above.
|
|
||||||
|
|
||||||
The job daemon is backwards compatible with the old Netdisco database job
|
|
||||||
requests table. All code for the job daemon lives under the
|
|
||||||
L<App::Netdisco::Backend> namespace and like the rest of Netdisco is broken
|
|
||||||
down into manageable chunks.
|
|
||||||
|
|
||||||
=head2 Running the Job Daemon
|
|
||||||
|
|
||||||
Like the web application, the job daemon is fully self contained and runs via
|
|
||||||
two simple scripts shipped with the distribution - one for foreground and one
|
|
||||||
for background execution (see the user docs for instructions).
|
|
||||||
|
|
||||||
The C<netdisco-backend> script uses L<Daemon::Control> to daemonize so you can
|
|
||||||
fire-and-forget the Netdisco job daemon without much trouble at all. This
|
|
||||||
script in turn calls C<netdisco-backend-fg> which is the real application,
|
|
||||||
that runs in the foreground if called on its own.
|
|
||||||
|
|
||||||
=head2 Daemon Engineering
|
|
||||||
|
|
||||||
The job daemon is based on the L<MCE> library, which handles the forking and
|
|
||||||
management of child processes doing the actual work. This actually runs in the
|
|
||||||
foreground unless wrapped with Daemon::Control, as mentioned above. MCE
|
|
||||||
handles four flavours of "worker" for different tasks.
|
|
||||||
|
|
||||||
One goal that we had designing the daemon was that sites should be able to run
|
|
||||||
many instances on different servers, with different processing capacities.
|
|
||||||
This is both to take advantage of more processor capability, but also to deal
|
|
||||||
with security zones where you might only be able to manage a subset of devices
|
|
||||||
from certain locations. Netdisco has always coped well with this via its
|
|
||||||
C<discover_*> and similar configuration, and the separate poller process.
|
|
||||||
|
|
||||||
So, the single Manager "worker" in the daemon is responsible for contacting
|
|
||||||
the central Netdisco database and booking out jobs which it's able to service
|
|
||||||
according to the local configuration settings. Jobs are "locked" in the
|
|
||||||
central queue and then copied to a local job queue within the daemon.
|
|
||||||
|
|
||||||
There is support in the daemon for the workers to pick more than one job at a
|
|
||||||
time from the local queue, in case we decide this is worth doing. However the
|
|
||||||
Manager won't ever book out more jobs from the central Netdisco job queue than
|
|
||||||
it has workers available (so as not to hog jobs for itself against other
|
|
||||||
daemons on other servers). The user is free to configure the number of
|
|
||||||
workers in their C<config.yml> file (zero or more).
|
|
||||||
|
|
||||||
The fourth kind of worker is called the Scheduler and takes care of adding
|
|
||||||
discover, macsuck, arpnip, and nbtstat jobs to the queue (which are in turn
|
|
||||||
handled by the Poller worker). This worker is automatically started only if
|
|
||||||
the user has enabled the "C<schedule>" section of their
|
|
||||||
C<deployment.yml> site config.
|
|
||||||
|
|
||||||
=head2 SNMP::Info
|
|
||||||
|
|
||||||
The daemon obviously needs to use L<SNMP::Info> for device control. All the
|
|
||||||
code for this has been factored out into the L<App::Netdisco::Util> namespace.
|
|
||||||
|
|
||||||
The L<App::Netdisco::Util::SNMP> package provides for the creation of
|
|
||||||
SNMP::Info objects along with connection tests. So far, SNMPv3 is not
|
|
||||||
supported. To enable trace logging of the SNMP::Info object simply set the
|
|
||||||
C<INFO_TRACE> environment variable to a true value. The Connect library also
|
|
||||||
provides routines to map interface and PoE IDs.
|
|
||||||
|
|
||||||
Configuration for SNMP::Info comes from the YAML files, of course. This means
|
|
||||||
that our C<mibhome> and C<mibdirs> settings are now in YAML format. In
|
|
||||||
particular, the C<mibdirs> list is a real list within the configuration.
|
|
||||||
|
|
||||||
=head1 Other Noteable Technology
|
|
||||||
|
|
||||||
=head2 C<local::lib>
|
|
||||||
|
|
||||||
This is the system used to install Netdisco and all its Perl dependencies into
|
|
||||||
a folder independent of the system's Perl libraries. It means Netdisco can be
|
|
||||||
self-contaned and at the same time relocated anywhere. The L<local::lib>
|
|
||||||
module is responsible for re-setting Perl's environment to point at the new
|
|
||||||
library.
|
|
||||||
|
|
||||||
=head2 C<App::cpanminus>
|
|
||||||
|
|
||||||
This is simply a sane replacement for the CPAN shell. Don't ever bother with
|
|
||||||
the CPAN shell again, just use the L<cpanm> client which comes with this
|
|
||||||
distribution. We install Netdisco using C<cpanm>.
|
|
||||||
|
|
||||||
=head2 C<App::local::lib::helper>
|
|
||||||
|
|
||||||
This is a companion to C<local::lib> which provides the C<localenv> script you
|
|
||||||
see referenced in the documentation. It's run automatically by Netdisco to
|
|
||||||
locate its C<local::lib> folder (that is, works around the bootstrapping
|
|
||||||
problem where the shipped app doesn't know to where it is relocated). We can
|
|
||||||
help things along by setting the C<NETDISCO_HOME> environment variable.
|
|
||||||
|
|
||||||
=head2 C<Try::Tiny>
|
|
||||||
|
|
||||||
A replacement for C<eval> which provides proper C<try/catch> semantics. You
|
|
||||||
have to take a bit of care unfortunately over things like C<return> statements
|
|
||||||
though. However it's a lot cleaner than C<eval> in many cases. See the
|
|
||||||
L<documentation|Try::Tiny> for further details.
|
|
||||||
|
|
||||||
=head2 C<Role::Tiny>
|
|
||||||
|
|
||||||
Anyone familiar with the concept of an I<interface> from other programming
|
|
||||||
languages might understand what a role is. It's class functionality, often
|
|
||||||
also called a "trait", which is composed into a class at run-time. This module
|
|
||||||
allows the Daemon workers to dynamically assume different roles according to
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
@@ -1,513 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::ReleaseNotes - Release Notes
|
|
||||||
|
|
||||||
=head1 Introduction
|
|
||||||
|
|
||||||
This document will list only the most significant changes with each release of
|
|
||||||
Netdisco. You are B<STRONGLY> recommended to read this document each time you
|
|
||||||
install and upgrade. Also see the Changes file, for more information.
|
|
||||||
|
|
||||||
=head1 Migrating from Netdisco 1.x
|
|
||||||
|
|
||||||
This distribution (App::Netdisco) is a complete rewrite of the Netdisco
|
|
||||||
application. Users often ask whether they can run both versions at the same
|
|
||||||
time, and whether the database must be copied. Here are the guidelines for
|
|
||||||
migrating from Netdisco 1.x:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
You can run both Netdisco 1.x and App::Netdisco web frontends at the same
|
|
||||||
time, using the same database (if "C<safe_password_store>" is set to
|
|
||||||
"C<false>" in the config file).
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
You can share a single database between Netdisco 1.x and App::Netdisco. The
|
|
||||||
deploy script for App::Netdisco will make some schema changes to the database,
|
|
||||||
but they are backwards compatible.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Only enable the backend daemon and discovery jobs from I<either> Netdisco 1.x
|
|
||||||
I<or> App::Netdisco.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 2.036002
|
|
||||||
|
|
||||||
This is a bug fix release since 2.036000. Please also read the 2.036000
|
|
||||||
release notes below, in full. Notable changes:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Device Port report is much faster when displaying nodes
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
C<netdisco-do psql> now supports C<NETDISCO_DBNAME> environment variable
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
C<snmp_auth> configuration now supports C<only> and C<no> ACLs per stanza
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
New Duplicate Devices Report in case you get these appearing
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Neighbor L2 topology map will show sysName if DNS is not available
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Speed up ACLs featuring regualr expressions
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Plus lots more mentioned in the Changes file.
|
|
||||||
|
|
||||||
=head1 2.036000
|
|
||||||
|
|
||||||
This release has many significant new features and changes. Please read all
|
|
||||||
the release notes before upgrading.
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
A new setting C<host_groups> allows for creating named Access Control Lists
|
|
||||||
which can be referred to in other host groups or in any of the settings taking
|
|
||||||
an ACL.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
The new setting C<device_identity> allows configuring rules to select the
|
|
||||||
interface to use as a canonical (friendly) identity of a device in Netdisco.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
The new settings C<devices_no> and C<devices_only> are shorthand for setting
|
|
||||||
C<discover_*>, C<macsuck_*>, C<arpnip_*>, and C<nbtstat_*> at once.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Netdisco now tracks SNMP connect failures and after 10 failed attempts will
|
|
||||||
pause trying to connect, for one week (see the C<max_deferrals> and
|
|
||||||
C<retry_after> settings). See also the "SNMP Connect Failures" admin report.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Documentation and support for access control lists has been overhauled. Most
|
|
||||||
"C<*_no>", "C<*_only>", and "C<only>" settings will accept ACLs as single
|
|
||||||
items or lists. ACLs now support negation and OR/AND modifier options.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
A new setting C<site_local_files> is a shorthand for confguring paths in which
|
|
||||||
to install local Perl, template, javascript, and images files for overriding
|
|
||||||
or enhancing Netdisco.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
The topology import script (C<nd-import-topology>) will now queue a "discover"
|
|
||||||
job for each new device it imports.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
The C<netdisco-daemon> and C<netdisco-daemon-fg> scripts have
|
|
||||||
been renamed to C<netdisco-backend> and C<netdisco-backend-fg> respectively.
|
|
||||||
|
|
||||||
The old commands will still work but we recommend packagers to use the new
|
|
||||||
names to remain consistent with documentation. Run the following on upgrade:
|
|
||||||
|
|
||||||
ln -s ~/perl5/bin/{localenv,netdisco-*} ~/bin/
|
|
||||||
~/bin/netdisco-daemon stop
|
|
||||||
~/bin/netdisco-backend restart
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
SSL library headers are required to build Netdisco now that we retrieve
|
|
||||||
support files via HTTPS.
|
|
||||||
|
|
||||||
On Ubuntu/Debian:
|
|
||||||
|
|
||||||
root:~# apt-get install libssl-dev
|
|
||||||
|
|
||||||
On Fedora/Red-Hat:
|
|
||||||
|
|
||||||
root:~# yum install openssl-devel
|
|
||||||
|
|
||||||
On BSD these headers are usually installed with the openssl port itself.
|
|
||||||
|
|
||||||
Netdisco will otherwise fail to upgrade/install (it will fail building
|
|
||||||
L<IO::Socket::SSL> or L<Net::SSLeay>). If you get stuck or confused, you are
|
|
||||||
looking for the package including the file C<openssl/err.h>.
|
|
||||||
|
|
||||||
=head1 2.034000
|
|
||||||
|
|
||||||
This release changes the way the application tracks web sessions for logged-in
|
|
||||||
users, from on-disk files, to encrypted browser cookies. As a result, on
|
|
||||||
upgrade (after running C<netdisco-deploy> and restarting C<netdisco-web>), all
|
|
||||||
users will need to log in again.
|
|
||||||
|
|
||||||
There may be a pause after restarting C<netdisco-web> as old web session files
|
|
||||||
on disk are purged.
|
|
||||||
|
|
||||||
=head1 2.032003
|
|
||||||
|
|
||||||
The algorithm for selecting the canonical IP/name of a device has changed in
|
|
||||||
this release. No longer is the OSPF Router ID taken into account. The default
|
|
||||||
IP/name of a device will be either the IP specified for manual discovery, or
|
|
||||||
the IP reported to a neighbor port during automatic discovery. For the latter
|
|
||||||
you can often influence this through device configuration (LLDP advertise...).
|
|
||||||
|
|
||||||
=head1 2.032000
|
|
||||||
|
|
||||||
The identification of IP Phone hansets and Wireless APs is now configurable,
|
|
||||||
using the CDP/LLDP information from the device. See
|
|
||||||
L<documentation|App::Netdisco::Manual::Configuration> for:
|
|
||||||
|
|
||||||
phone_capabilities
|
|
||||||
phone_platforms
|
|
||||||
wap_capabilities
|
|
||||||
wap_platforms
|
|
||||||
|
|
||||||
=head1 2.031006
|
|
||||||
|
|
||||||
When displaying device ports, Netdisco will now avoid showing VLAN Membership
|
|
||||||
if it looks like there are a large number of VLANs on many ports. This is an
|
|
||||||
average of the VLANs per port, configurable in C<devport_vlan_limit>. The
|
|
||||||
default is 150.
|
|
||||||
|
|
||||||
=head1 2.031005
|
|
||||||
|
|
||||||
The C<netdisco-do> command's C<delete> option now uses the C<-p> parameter to
|
|
||||||
set node archive mode (previously it was a hack on C<-e>). For example:
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-do delete -d 192.0.2.1 -e 'older than the sun' -p yes
|
|
||||||
|
|
||||||
=head1 2.031003
|
|
||||||
|
|
||||||
=head2 Health Advice
|
|
||||||
|
|
||||||
This release will I<once again> remove from the database spurious Node
|
|
||||||
(workstation, printer, etc) entries on vlan 0, which were causing dupliate
|
|
||||||
entries in the web interface. We advise that you back up the database prior to
|
|
||||||
upgrade:
|
|
||||||
|
|
||||||
/usr/bin/pg_dump -F c --create -f netdisco-pgsql.dump netdisco
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
The database schema can be fully redeployed (even over an existing
|
|
||||||
installation, in a safe way) using the following command:
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-db-deploy --redeploy-all
|
|
||||||
|
|
||||||
=head1 2.031002
|
|
||||||
|
|
||||||
Netdisco web and backend daemons will now rotate their log files
|
|
||||||
("C<~netdisco/logs/netdisco-{web,daemon}.log>"). This happens when they reach
|
|
||||||
about 10MB in size and seven historical log files will be maintained in the
|
|
||||||
same directory. The first time this happens you may notice the daemons
|
|
||||||
restarting due to having to deal with the large initial logfile.
|
|
||||||
|
|
||||||
Two missing features from Netdisco 1 have been implemented: CLI device delete
|
|
||||||
and renumber (canonical IP change). They are available using the
|
|
||||||
C<netdisco-do> utility.
|
|
||||||
|
|
||||||
The Device Port Log comment feature from 2.030000 has been disabled as it is
|
|
||||||
incomplete, pending a review of how to handle authorization to the feature.
|
|
||||||
|
|
||||||
=head1 2.029014
|
|
||||||
|
|
||||||
The node archiving behaviour of Netdisco 2 has until now been accidentally
|
|
||||||
different to that in Netdisco 1. This has now been fixed. See the new
|
|
||||||
"C<node_freshness>" configuration setting if you wish to revert or tune this
|
|
||||||
behaviour.
|
|
||||||
|
|
||||||
=head1 2.029010
|
|
||||||
|
|
||||||
When upgrading you will encounter a current incompatibility between Netdisco
|
|
||||||
and one of its components. To work around this, issue the following command:
|
|
||||||
|
|
||||||
~/bin/localenv cpanm --notest --force Dancer@1.3126 DBIx::Class@0.08270
|
|
||||||
|
|
||||||
=head1 2.029008
|
|
||||||
|
|
||||||
When upgrading you will encounter a current incompatibility between Netdisco
|
|
||||||
and one of its components. To work around this, issue the following command:
|
|
||||||
|
|
||||||
~/bin/localenv cpanm --notest --force Dancer@1.3126
|
|
||||||
|
|
||||||
=head1 2.029002
|
|
||||||
|
|
||||||
The backend polling daemon has been rewritten and as a result your
|
|
||||||
configuration can be simplified. Some keys have also been renamed. Our advice
|
|
||||||
is to remove (or comment out) the complete C<workers> configuration which
|
|
||||||
enables auto-tuning. If you do wish to control the number of worker
|
|
||||||
processes, follow this pattern:
|
|
||||||
|
|
||||||
workers:
|
|
||||||
tasks: 'AUTO * 2' # this is the default, twice the number of CPUs
|
|
||||||
|
|
||||||
=head1 2.029001
|
|
||||||
|
|
||||||
=head2 Health Advice
|
|
||||||
|
|
||||||
This release will remove from the database spurious Node (workstation,
|
|
||||||
printer, etc) entries on vlan 0, which were causing dupliate entries in the
|
|
||||||
web interface. We advise that you back up the database prior to upgrade:
|
|
||||||
|
|
||||||
/usr/bin/pg_dump -F c --create -f netdisco-pgsql.dump netdisco
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
The configuration item C<reports> is now a list (used to be a dictionary).
|
|
||||||
Each item in the list must have a C<tag> entry which was previously the
|
|
||||||
dictionary key. For example, now use:
|
|
||||||
|
|
||||||
reports:
|
|
||||||
- tag: power_inventory
|
|
||||||
category: Device
|
|
||||||
label: 'Power Supply Inventory'
|
|
||||||
columns:
|
|
||||||
- {name: 'Name'}
|
|
||||||
- {ps1_type: 'PS1 Type'}
|
|
||||||
- {ps1_status: 'PS1 Status'}
|
|
||||||
query: |
|
|
||||||
SELECT d.name, d.ps1_type, d.ps1_status
|
|
||||||
FROM device d
|
|
||||||
WHERE d.ps1_type IS NOT NULL
|
|
||||||
ORDER BY name
|
|
||||||
|
|
||||||
Old configuration will be continue to work, but we recommend you reconfigure
|
|
||||||
anyway.
|
|
||||||
|
|
||||||
=head1 2.028000
|
|
||||||
|
|
||||||
=head2 Incompatible Changes
|
|
||||||
|
|
||||||
The daemons can be started from init scripts, as root. They will drop back
|
|
||||||
from the root user to C<netdisco> before opening logs. However a limitation is
|
|
||||||
that the web frontend might temporarily keep root status to bind to a specific
|
|
||||||
port (e.g. 80) - the logs will then be created as root user. Sorry about that.
|
|
||||||
|
|
||||||
You might also find when upgrading that previous logs were owned by root and
|
|
||||||
Netdisco now wants to write to them as non-root (C<netdisco>) user. Please
|
|
||||||
either remove the logs before restarting, or alter their ownership.
|
|
||||||
|
|
||||||
Logs can be found in the C<logs> subdirectory of Netdisco's home area.
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
The configuration item C<housekeeping> has been renamed to C<schedule>. Old
|
|
||||||
configuration will continue to work, but we recommend you now rename this key
|
|
||||||
in your configuration anyway.
|
|
||||||
|
|
||||||
=head1 2.025001
|
|
||||||
|
|
||||||
The Web and Backend daemons (C<netdisco-web> and C<netdisco-daemon>
|
|
||||||
respectively) will now watch your C<deployment.yml> configuration file, and
|
|
||||||
restart themselves whenever it is changed.
|
|
||||||
|
|
||||||
The Web and Backend daemons will also now drop privilege to the same user and
|
|
||||||
group as their files on disk. This allows use of run control (init) scripts
|
|
||||||
whilst maintaining non-root privilege status (see
|
|
||||||
L<Deployment|App::Netdisco::Manual::Deployment> documentation for details).
|
|
||||||
|
|
||||||
The housekeeping task C<expiry> has been renamed to C<expire>. Old
|
|
||||||
configuration will continue to work, but we recommend you rename this part of
|
|
||||||
your C<housekeeping> configuration anyway.
|
|
||||||
|
|
||||||
=head1 2.023000
|
|
||||||
|
|
||||||
=head2 Incompatible Changes
|
|
||||||
|
|
||||||
This release will automatically migrate user passwords to have stronger
|
|
||||||
hashing in the database (a good thing!). This is incompatible with Netdisco
|
|
||||||
1.x web frontend, so if you must maintain backward-compatibility, set the
|
|
||||||
following in your C<deployment.yml> file:
|
|
||||||
|
|
||||||
safe_password_store: false
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
The number of parallel DNS queries running during node discovery has been
|
|
||||||
reduced to 10 for maximum safety, but resulting in lower macsuck performance.
|
|
||||||
If you have a robust DNS infrastructure, you can probably put it back up to
|
|
||||||
something like 50 or 100:
|
|
||||||
|
|
||||||
dns:
|
|
||||||
max_outstanding: 100
|
|
||||||
|
|
||||||
=head1 2.021000
|
|
||||||
|
|
||||||
=head2 Incompatible Changes
|
|
||||||
|
|
||||||
SNMP community strings provided in the C<community_rw> configuration setting
|
|
||||||
will I<no longer> be used for I<read> actions on a device (despite having
|
|
||||||
"C<rw>" in the setting name).
|
|
||||||
|
|
||||||
If you have the same community string for read and write access, then you must
|
|
||||||
set both C<community> and C<community_rw> in your C<deployment.yml> file. In
|
|
||||||
any case, we recommend using the new C<snmp_auth> configuration format which
|
|
||||||
supercedes both these settings.
|
|
||||||
|
|
||||||
=head2 Health Advice
|
|
||||||
|
|
||||||
This release includes support for Device and Node expiry from your database.
|
|
||||||
This is an important part of housekeeping for your installation, and our
|
|
||||||
recommendation is to enable this feature such that suitably old Devices and
|
|
||||||
Nodes are expired nightly.
|
|
||||||
|
|
||||||
Add the following to your "C<housekeeping>" configuration in
|
|
||||||
C<deployment.yml>, to have a nightly check at 11:20pm:
|
|
||||||
|
|
||||||
housekeeping:
|
|
||||||
expire:
|
|
||||||
when: '20 23 * * *'
|
|
||||||
|
|
||||||
You should also configure one or more of C<expire_devices>, C<expire_nodes>,
|
|
||||||
and C<expire_nodes_archive> to a number of days. See the
|
|
||||||
L<Configuration|App::Netdisco::Manual::Configuration> documentation for
|
|
||||||
further details.
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
If you use an Apache reverse proxy, we recomment increasing the timeout from
|
|
||||||
our previous example of 5 seconds to, perhaps 60. This is because some reports
|
|
||||||
do take more time to run their queries on the database. See
|
|
||||||
L<Deployment|App::Netdisco::Manual::Deployment> documentation for details.
|
|
||||||
|
|
||||||
=head1 2.020000
|
|
||||||
|
|
||||||
If you were using the C<X::Observium> plugin, you'll now need to install
|
|
||||||
the separate distribution L<App::NetdiscoX::Web::Plugin::Observium>.
|
|
||||||
|
|
||||||
=head1 2.019000
|
|
||||||
|
|
||||||
This release fixes a number of issues with the poller, and is a recommended
|
|
||||||
upgrade.
|
|
||||||
|
|
||||||
During Arpnip, Node IPs are resolved to DNS names in parallel. See the C<dns>
|
|
||||||
configuration option for details. Note that the C<nodenames> configuration
|
|
||||||
items from release C<2.018000> are no longer available.
|
|
||||||
|
|
||||||
This release includes new support for SNMPv3 via the C<snmp_auth>
|
|
||||||
configuration option. Please provide feedback to the developers on your
|
|
||||||
experience.
|
|
||||||
|
|
||||||
=head1 2.018000
|
|
||||||
|
|
||||||
The previous mentioned bug in Macsuck is now fixed.
|
|
||||||
|
|
||||||
=head1 2.017000
|
|
||||||
|
|
||||||
There is a bug in Macsuck whereby in rare circumstances some invalid SQL is
|
|
||||||
generated. The root cause is known but we want to take more time to get the
|
|
||||||
fix right. It should only be a few more days.
|
|
||||||
|
|
||||||
The C<no_port_control> configuration setting is now called C<check_userlog>
|
|
||||||
and its logic is inverted. Don't worry if this is not familiar to you - the
|
|
||||||
option is only used by Netdisco Developers.
|
|
||||||
|
|
||||||
=head1 2.016000
|
|
||||||
|
|
||||||
The dangerous action log messages are now saved to the database. In a future
|
|
||||||
version there will be a way to display them in the web interface.
|
|
||||||
|
|
||||||
=head1 2.015000
|
|
||||||
|
|
||||||
Some of the "dangerous action" confirmation dialogs offer to take a log
|
|
||||||
message (e.g. Port Control, Device Delete). Currently the log messages are
|
|
||||||
B<not saved>. This feature will be added in the next release.
|
|
||||||
|
|
||||||
=head1 2.014000
|
|
||||||
|
|
||||||
The backend poller daemon is now considered stable. You can uncomment the
|
|
||||||
C<housekeeping> section of the example configuration and thereby enable
|
|
||||||
regular device (re-)discovery, arpnip and macsuck.
|
|
||||||
|
|
||||||
=head1 2.013000
|
|
||||||
|
|
||||||
You can now configure LDAP authentication for users.
|
|
||||||
|
|
||||||
=head1 2.012000
|
|
||||||
|
|
||||||
The read-write SNMP community is now stored in the database, when used for the
|
|
||||||
first time on a device. If you don't want the web frontend to be able to
|
|
||||||
access this, you need to:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Have separate C<deployment.yml> files for web frontend and daemon, such that
|
|
||||||
only the daemon config contains any community strings.
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Use separate PostgreSQL users for web frontend and daemon, such that the web
|
|
||||||
frontend user cannot SELECT from the C<community> DB table.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 2.011000
|
|
||||||
|
|
||||||
Users can be managed through the web interface (by admins only).
|
|
||||||
|
|
||||||
=head1 2.010000
|
|
||||||
|
|
||||||
You can now simplify database configuration to just the following, instead of
|
|
||||||
the more verbose C<plugins/DBIC> setting which was there before:
|
|
||||||
|
|
||||||
database:
|
|
||||||
name: 'netdisco'
|
|
||||||
host: 'localhost'
|
|
||||||
user: 'someuser'
|
|
||||||
pass: 'somepass'
|
|
||||||
|
|
||||||
Also, the C<REMOTE_USER> environment variable and C<X-REMOTE_USER> HTTP Header
|
|
||||||
are now supported for delegating authentication to another web server. See the
|
|
||||||
Deployment and Configuration documentation for further details.
|
|
||||||
|
|
||||||
=head1 2.008000
|
|
||||||
|
|
||||||
=head2 Health Advice
|
|
||||||
|
|
||||||
This release contains the first version of our new poller, which handles
|
|
||||||
device and node discovery. Please make sure to backup any existing Netdisco
|
|
||||||
database before trying it out.
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
You can remove any settings from C<~/environments/deployment.yml> which you
|
|
||||||
didn't edit or add to the file yourself. All defaults are now properly
|
|
||||||
embedded within the application. See the new C<deployment.yml> sample which
|
|
||||||
ships with this distribution for an example.
|
|
||||||
|
|
||||||
=head1 2.006000
|
|
||||||
|
|
||||||
=head2 Incompatible Changes
|
|
||||||
|
|
||||||
The default environment configuration file C<develpment.yml> has been renamed
|
|
||||||
to C<deployment.yml>. This better reflects that users are not developers, and
|
|
||||||
also fits with the default for PSGI compatible cloud deployment services.
|
|
||||||
|
|
||||||
Please B<rename or copy> your environment file:
|
|
||||||
|
|
||||||
mv ~/environments/development.yml ~/environments/deployment.yml
|
|
||||||
|
|
||||||
=head2 General Notices
|
|
||||||
|
|
||||||
The installation is now relocateable outside of a user's home directory by
|
|
||||||
setting the C<NETDISCO_HOME> environment variable. This defaults to your own
|
|
||||||
home directory.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::Systemd - Systemd install tips
|
|
||||||
|
|
||||||
=head1 Introduction
|
|
||||||
|
|
||||||
This page documents Netdisco running under systemd. Thanks to Aurelien Guerson
|
|
||||||
and Stuart Kendrick for offering this solution. Please check these
|
|
||||||
instructions apply to your local installation and use at your own risk.
|
|
||||||
|
|
||||||
=head1 Files
|
|
||||||
|
|
||||||
=head2 C<< /etc/systemd/system/netdisco-backend.service >>
|
|
||||||
|
|
||||||
This should be set mode 644 and owned by user and group C<root>.
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Netdisco Backend Service
|
|
||||||
AssertFileIsExecutable=/home/netdisco/bin/netdisco-backend
|
|
||||||
After=syslog.target network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=forking
|
|
||||||
User=netdisco
|
|
||||||
Group=netdisco
|
|
||||||
ExecStart=/home/netdisco/bin/netdisco-backend start
|
|
||||||
ExecStop=/home/netdisco/bin/netdisco-backend stop
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=60
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
=head2 C<< /etc/systemd/system/netdisco-web.service >>
|
|
||||||
|
|
||||||
This should be set mode 644 and owned by user and group C<root>.
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Netdisco Web Service
|
|
||||||
AssertFileIsExecutable=/home/netdisco/bin/netdisco-web
|
|
||||||
After=syslog.target network-online.target netdisco-backend.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=forking
|
|
||||||
User=netdisco
|
|
||||||
Group=netdisco
|
|
||||||
ExecStart=/home/netdisco/bin/netdisco-web start
|
|
||||||
ExecStop=/home/netdisco/bin/netdisco-web stop
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=60
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
=head1 Commands
|
|
||||||
|
|
||||||
To enable Netdisco in systemd:
|
|
||||||
|
|
||||||
systemctl enable netdisco-backend.service
|
|
||||||
systemctl enable netdisco-web.service
|
|
||||||
|
|
||||||
To start Netdisco:
|
|
||||||
|
|
||||||
systemctl start netdisco-backend.service
|
|
||||||
systemctl start netdisco-web.service
|
|
||||||
|
|
||||||
May also need to run C<systemctl netdisco-backend reload> depending on the
|
|
||||||
order you do these steps.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::Troubleshooting - Tips and Tricks for Troubleshooting
|
|
||||||
|
|
||||||
=head1 Understanding Nodes and Devices
|
|
||||||
|
|
||||||
The two basic components in Netdisco's world are Nodes and Devices. Devices
|
|
||||||
are your network hardware, such as routers, switches, and firewalls. Nodes are
|
|
||||||
the end-stations connected to Devices, such as workstations, servers,
|
|
||||||
printers, and telephones.
|
|
||||||
|
|
||||||
Devices respond to SNMP, and therefore can report useful information about
|
|
||||||
themselves such as interfaces, operating system, IP addresses, as well as
|
|
||||||
knowledge of other systems via MAC address and ARP tables. Devices are
|
|
||||||
actively contacted by Netdisco during a discover (and other polling jobs such
|
|
||||||
as macsuck, arpnip).
|
|
||||||
|
|
||||||
Netdisco discovers Devices using "neighbor protocols" such as CDP and LLDP. We
|
|
||||||
assume your Devices are running these protocols and learning about their
|
|
||||||
connections to each other. If they aren't, you'll need to configure manual
|
|
||||||
topology within the web interface (or simply have standalone Devices).
|
|
||||||
|
|
||||||
Nodes, on the other hand, are passive as far as Netdisco is concerned. The
|
|
||||||
only job that contacts a Node is nbtstat, which makes NetBIOS queries. Nodes
|
|
||||||
are learned about via the MAC and ARP tables on upstream Devices.
|
|
||||||
|
|
||||||
Because Netdisco only learns about Devices through a neighbor protocol, it's
|
|
||||||
possible to run an SNMP agent on a Node. Only if the Node is also advertising
|
|
||||||
itself via a neighbor protocol will Netdisco treat it as a Device. This can
|
|
||||||
account for undesired behaviour, such as treating a server (Node) as a Device,
|
|
||||||
or vice versa only recognising a switch (Device) as a Node.
|
|
||||||
|
|
||||||
To prevent discovery of devices, use the C<devices_no> configuration setting.
|
|
||||||
If you don't see links between Devices in Netdisco, it might be because
|
|
||||||
they're not running a neighbor protocol, or for some reason not reporting the
|
|
||||||
relationships to Netdisco. Use the C<show> command to troubleshoot this:
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-do show -d 192.0.2.1 -e c_id
|
|
||||||
|
|
||||||
=head1 Understanding Netdisco Jobs
|
|
||||||
|
|
||||||
Please read the section above, if you've not yet done so.
|
|
||||||
|
|
||||||
Netdisco has four principal job types:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item discover
|
|
||||||
|
|
||||||
Gather information about a Device, including interfaces, vlans, PoE status,
|
|
||||||
and chassis components (modules). Also learns about potential new Devices via
|
|
||||||
neighbor protocols and adds jobs for their discovery to the queue.
|
|
||||||
|
|
||||||
=item macsuck
|
|
||||||
|
|
||||||
Gather MAC to port mappings from known Devices reporting Layer 2 capability.
|
|
||||||
Wireless client information is also gathered from Devices supporting the
|
|
||||||
802.11 MIBs.
|
|
||||||
|
|
||||||
=item arpnip
|
|
||||||
|
|
||||||
Gather MAC to IP mappings from known Devices reporting layer 3 capability.
|
|
||||||
|
|
||||||
=item nbtstat
|
|
||||||
|
|
||||||
Poll a Node to obtain its NetBIOS name.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
The actions as named above will operate on one device only. Complimentary job
|
|
||||||
types C<discoverall>, C<macwalk>, C<arpwalk>, and C<nbtwalk> will enqueue one
|
|
||||||
corresponding single-device job for each known device. The Netdisco backend
|
|
||||||
daemon will then process the queue (in a random order).
|
|
||||||
|
|
||||||
=head1 My Device details look all wrong!
|
|
||||||
|
|
||||||
See the tips at L<Vendors Guide|App::Netdisco::Manual::Vendors>, or else
|
|
||||||
contact the L<community email
|
|
||||||
list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
|
||||||
|
|
||||||
=head1 Devices are not being discovered
|
|
||||||
|
|
||||||
Besides reading the whole of this manual page for general tips, take a look at
|
|
||||||
the "SNMP Connect Failures" report under the Admin menu. Any devices listed
|
|
||||||
have had multiple SNMP connect failures, indicating a possible configuration
|
|
||||||
error on the device or in Netdisco's configuration.
|
|
||||||
|
|
||||||
=head1 Devices have the wrong names
|
|
||||||
|
|
||||||
Netdisco uses neighbor protocols to discover devices and will use as the
|
|
||||||
default identity for a device the interface IP advertised over those neighbor
|
|
||||||
protocols. You can use the C<device_identity> configuration setting to steer
|
|
||||||
Netdisco towards using a different interface for the canonical device name.
|
|
||||||
|
|
||||||
=head1 After OS update or upgrade, Netdisco fails
|
|
||||||
|
|
||||||
If you upgrade the operating system then your system libraries will change and
|
|
||||||
Netdisco needs to be rebuilt (specifically, C library bindings).
|
|
||||||
|
|
||||||
The safest way to do this is set up a new user and follow the same install
|
|
||||||
instructions, connecting to the same database. Stop the web and backend daemon
|
|
||||||
for the old user, and start them for the new user. Then delete the old user
|
|
||||||
account.
|
|
||||||
|
|
||||||
Alternatively, if you do not mind the downtime: stop the web and backend
|
|
||||||
daemons then delete the C<~netdisco/perl5> directory and reinstall from
|
|
||||||
scratch. The configuration file, database, and MIBs can all be reused
|
|
||||||
in-place.
|
|
||||||
|
|
||||||
=head1 Run a C<netdisco-do> Task with Debugging
|
|
||||||
|
|
||||||
The C<netdisco-do> command has several debug flags which will show what's
|
|
||||||
going on internally. Usually you always add C<-D> for general Netdisco
|
|
||||||
debugging, then C<-I> for L<SNMP::Info> logging and C<-Q> for SQL tracing. For
|
|
||||||
example:
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-do discover -d 192.0.2.1 -DIQ
|
|
||||||
|
|
||||||
You will see that SNMP community strings and users are hidden by default, to
|
|
||||||
make the output safe for sending to Netdisco developers. To show the community
|
|
||||||
string and SNMPv3 protocols, set the C<SHOW_COMMUNITY> environment variable:
|
|
||||||
|
|
||||||
SHOW_COMMUNITY=1 ~netdisco/bin/netdisco-do discover -d 192.0.2.1 -DIQ
|
|
||||||
|
|
||||||
=head1 Dump an SNMP object for a Device
|
|
||||||
|
|
||||||
This is useful when trying to work out why some information isn't displaying
|
|
||||||
correctly (or at all) in Netdisco. It may be that the SNMP response isn't
|
|
||||||
understood. Netdisco can dump any leaf or table, by name:
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-do show -d 192.0.2.1 -e interfaces
|
|
||||||
~netdisco/bin/netdisco-do show -d 192.0.2.1 -e Layer2::HP::interfaces
|
|
||||||
|
|
||||||
You can combine this with SNMP::Info debugging, shown above (C<-I>).
|
|
||||||
|
|
||||||
=head1 Interactive SQL terminal on the Netdisco Database
|
|
||||||
|
|
||||||
Start an interactive terminal with the Netdisco PostgreSQL database. If you
|
|
||||||
pass an SQL statement in the "-e" option then it will be executed.
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-do psql
|
|
||||||
~netdisco/bin/netdisco-do psql -e 'SELECT ip, dns FROM device'
|
|
||||||
~netdisco/bin/netdisco-do psql -e 'COPY (SELECT ip, dns FROM device) TO STDOUT WITH CSV HEADER'
|
|
||||||
|
|
||||||
The last example above is useful for sending data to Netdisco developers, as
|
|
||||||
it's more compact and readable than the standard tabular output (second
|
|
||||||
example).
|
|
||||||
|
|
||||||
=head1 Database Schema Redeployment
|
|
||||||
|
|
||||||
The database schema can be fully redeployed (even over an existing
|
|
||||||
installation), in a safe way, using the following command:
|
|
||||||
|
|
||||||
~netdisco/bin/netdisco-db-deploy --redeploy-all
|
|
||||||
|
|
||||||
=head1 Debug HTTP Requests and Configuration
|
|
||||||
|
|
||||||
You can see HTTP Headers received by Netdisco, and other information such as
|
|
||||||
how it's parsing the config file, by enabling the Dancer debug plugin. First
|
|
||||||
download the plugin:
|
|
||||||
|
|
||||||
~netdisco/bin/localenv cpanm --notest Dancer::Debug
|
|
||||||
|
|
||||||
Then run the web daemon with the environment variable to enable the feature:
|
|
||||||
|
|
||||||
DANCER_DEBUG=1 ~/bin/netdisco-web restart
|
|
||||||
|
|
||||||
A side panel appears in the web page with debug information. Be sure to turn
|
|
||||||
this off when you're done (stop and start without the environment variable)
|
|
||||||
otherwise secrets could be leaked to end users.
|
|
||||||
|
|
||||||
=head1 Change the SNMP commnuity string for a Device
|
|
||||||
|
|
||||||
If you change the SNMP community string in use on a Device, and update
|
|
||||||
Netdisco's configuration to match, then everything will continue to work fine.
|
|
||||||
|
|
||||||
However, if the Device happens to support two community strings then Netdisco
|
|
||||||
can become "stuck" on the wrong one, as it caches the last-known-good
|
|
||||||
community string to improve performance. To work around this, delete the
|
|
||||||
device (either in the web GUI or using C<netdisco-do> at the command line),
|
|
||||||
and then re-discover it.
|
|
||||||
|
|
||||||
=head1 Installation on SLES 11 SP4
|
|
||||||
|
|
||||||
Try running the following command for installation:
|
|
||||||
|
|
||||||
curl -L http://cpanmin.us/ | CFLAGS="-DPERL_ARGS_ASSERT_CROAK_XS_USAGE" perl - --notest --local-lib ~/perl5 App::Netdisco
|
|
||||||
|
|
||||||
=cut
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::Vendors - Tips and Tricks for Vendor Platforms
|
|
||||||
|
|
||||||
=head1 Neighbor Relations on Juniper EX
|
|
||||||
|
|
||||||
The LLDP configuration should look like:
|
|
||||||
|
|
||||||
lldp {
|
|
||||||
management-address 10.0.0.1;
|
|
||||||
port-id-subtype interface-name;
|
|
||||||
interface all;
|
|
||||||
}
|
|
||||||
|
|
||||||
=head1 Neighbor Relations on D-Link
|
|
||||||
|
|
||||||
Add the following to your devices (changing the port numbers appropriately):
|
|
||||||
|
|
||||||
config lldp ports 1-28 mgt_addr ipv4 enable
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
config lldp ports 1-28 mgt_addr ipv4 1.2.3.4 enable
|
|
||||||
|
|
||||||
Which you use will depend on the device OS version.
|
|
||||||
|
|
||||||
=head1 VRFs and NXOS
|
|
||||||
|
|
||||||
Netdsico at this time does not support VRFs. In particular, overlapping IP
|
|
||||||
address spaces will not be shown in the interface.
|
|
||||||
|
|
||||||
However if you're running Cisco NXOS and do not have overlapping IP address
|
|
||||||
space, then you can use the NXOS SSHCollector profile for that platform.
|
|
||||||
|
|
||||||
=head1 Report Cisco as Single Device Instead of Stacked (37xx/29xx/etc)
|
|
||||||
|
|
||||||
Add this to your device config:
|
|
||||||
|
|
||||||
no snmp-server sysobjectid type stack-oid
|
|
||||||
|
|
||||||
=head1 SNMP Support on Huawei Quidway and CloudEngine
|
|
||||||
|
|
||||||
Where C<mycommunity> is your community string. Note C<iso> means I<everything>
|
|
||||||
is visible to readers!
|
|
||||||
|
|
||||||
snmp-agent mib-view included all iso
|
|
||||||
snmp-agent community read cipher mycommunity mib-view all
|
|
||||||
snmp-agent packet max-size 17940
|
|
||||||
snmp-agent extend error-code enable
|
|
||||||
|
|
||||||
=head1 SNMP Support on Linksys and Cisco Linksys
|
|
||||||
|
|
||||||
Where C<mycommunity> is your community string. Note this results in I<everything>
|
|
||||||
being visible to readers!
|
|
||||||
|
|
||||||
snmp-server view test iso included
|
|
||||||
snmp-server view test system included
|
|
||||||
snmp-server view test interfaces included
|
|
||||||
snmp-server view test ip included
|
|
||||||
snmp-server view test icmp included
|
|
||||||
snmp-server view test tcp included
|
|
||||||
snmp-server view test udp included
|
|
||||||
snmp-server view test transmission included
|
|
||||||
snmp-server view test snmp included
|
|
||||||
snmp-server view test rmon included
|
|
||||||
snmp-server view test dot1dBridge included
|
|
||||||
snmp-server view test ifMIB included
|
|
||||||
snmp-server view test dns included
|
|
||||||
snmp-server view test radiusMIB included
|
|
||||||
snmp-server view test traceRouteMIB included
|
|
||||||
snmp-server view test powerEthernetMIB included
|
|
||||||
snmp-server community mycommunity ro view test
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SNMPv3 Support on Cisco IOS
|
|
||||||
|
|
||||||
To access per-VLAN MAC address tables we use SNMPv3 contexts. In Cisco IOS
|
|
||||||
the access control is per-context so for each context (VLAN) you need to permit
|
|
||||||
access from the poller.
|
|
||||||
|
|
||||||
You should already have something like the following to enable SNMPv3 from Netdisco at 192.0.2.1:
|
|
||||||
|
|
||||||
snmp-server view myv3view iso included
|
|
||||||
snmp-server group myv3group v3 priv read myv3view
|
|
||||||
snmp-server user myv3user myv3group v3 auth md5 PASSWORD priv des PASSWORD
|
|
||||||
snmp-server host 192.0.2.1 version 3 auth myv3user
|
|
||||||
|
|
||||||
Then set the authorization:
|
|
||||||
|
|
||||||
snmp-server group myv3group v3 auth
|
|
||||||
snmp-server group myv3group v3 auth context vlan- match prefix
|
|
||||||
|
|
||||||
If the second command above is rejected, you have an older version of IOS and must
|
|
||||||
enter a statement for each active VLAN on the device:
|
|
||||||
|
|
||||||
snmp-server group myv3group v3 priv context vlan-1
|
|
||||||
snmp-server group myv3group v3 priv context vlan-2
|
|
||||||
snmp-server group myv3group v3 priv context vlan-3
|
|
||||||
... etc
|
|
||||||
|
|
||||||
=head1 Linux SNMP Service (Agent)
|
|
||||||
|
|
||||||
Install the C<snmpd> (SNMP agent) and C<lldpd> (neighbor discovery) packages.
|
|
||||||
|
|
||||||
Edit the C</etc/snmp/snmpd.conf> file:
|
|
||||||
|
|
||||||
# AGENT BEHAVIOUR
|
|
||||||
# comment out: agentAddress udp:127.0.0.1:161
|
|
||||||
agentAddress udp:161,udp6:[::1]:161
|
|
||||||
|
|
||||||
# ACCESS CONTROL
|
|
||||||
rocommunity <your-secret> <management-device-IP/net>
|
|
||||||
|
|
||||||
# SYSTEM INFORMATION
|
|
||||||
sysServices 76
|
|
||||||
# (default is 72, 74 is layer2 bridge/switch, 76 for layer3 router/gateway)
|
|
||||||
|
|
||||||
If running a firewall, allow SNMP traffic in on UDP port 161.
|
|
||||||
|
|
||||||
Edit the C</etc/default/lldpd> file:
|
|
||||||
|
|
||||||
DAEMON_ARGS="-k -x -l -m <Mgmt-IP>"
|
|
||||||
# <Mgmt-IP> is the IP to advertise for Netdisco to connect
|
|
||||||
|
|
||||||
Restart C<snmpd> and C<lldpd> services when you have configured them.
|
|
||||||
|
|
||||||
This assumes you're using LLDP on your network. If you use CDP then the
|
|
||||||
C<lldpd> daemon can support that protocol - see the manual page for details.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
@@ -1,521 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::WritingWebPlugins - Documentation on Web Plugins for Developers
|
|
||||||
|
|
||||||
=head1 Introduction
|
|
||||||
|
|
||||||
L<App::Netdisco>'s plugin subsystem allows developers to write and test web
|
|
||||||
user interface (UI) components without needing to patch the main Netdisco
|
|
||||||
application. It also allows the end-user more control over the UI components
|
|
||||||
displayed in their browser.
|
|
||||||
|
|
||||||
See L<App::Netdisco::Web::Plugin> for more general information about plugins.
|
|
||||||
|
|
||||||
=head1 Developing Plugins
|
|
||||||
|
|
||||||
A plugin is simply a Perl module which is loaded. Therefore it can do anything
|
|
||||||
you like, but most usefully for the App::Netdisco web application the module
|
|
||||||
will install a L<Dancer> route handler subroutine, and link this to a web user
|
|
||||||
interface (UI) component.
|
|
||||||
|
|
||||||
Explaining how to write Dancer route handlers is beyond the scope of this
|
|
||||||
document, but by examining the source to the plugins in App::Netdisco you'll
|
|
||||||
probably get enough of an idea to begin on your own.
|
|
||||||
|
|
||||||
App::Netdisco plugins should load the L<App::Netdisco::Web::Plugin> module.
|
|
||||||
This exports a set of helper subroutines to register the new UI components.
|
|
||||||
Here's the boilerplate code for our example plugin module:
|
|
||||||
|
|
||||||
package App::Netdisco::Web::Plugin::MyNewFeature;
|
|
||||||
|
|
||||||
use Dancer ':syntax';
|
|
||||||
use Dancer::Plugin::DBIC;
|
|
||||||
use Dancer::Plugin::Auth::Extensible;
|
|
||||||
|
|
||||||
use App::Netdisco::Web::Plugin;
|
|
||||||
|
|
||||||
# plugin registration code goes here, ** see below **
|
|
||||||
|
|
||||||
# your Dancer route handler
|
|
||||||
get '/mynewfeature' => require_login sub {
|
|
||||||
# ...lorem ipsum...
|
|
||||||
};
|
|
||||||
|
|
||||||
true;
|
|
||||||
|
|
||||||
=head1 Navigation Bar items
|
|
||||||
|
|
||||||
These components appear in the black navigation bar at the top of each page,
|
|
||||||
as individual items (i.e. not in a menu). The canonical example of this is the
|
|
||||||
Inventory link.
|
|
||||||
|
|
||||||
To register an item for display in the navigation bar, use the following code:
|
|
||||||
|
|
||||||
register_navbar_item({
|
|
||||||
tag => 'newfeature',
|
|
||||||
path => '/mynewfeature',
|
|
||||||
label => 'My New Feature',
|
|
||||||
});
|
|
||||||
|
|
||||||
This causes an item to appear in the Navigation Bar with a visible text of "My
|
|
||||||
New Feature" which when clicked sends the user to the C</mynewfeature> page.
|
|
||||||
Note that this won't work for any target link - the path must be an
|
|
||||||
App::Netdisco Dancer route handler. Please bug the App::Netdisco devs if you
|
|
||||||
want arbitrary links supported.
|
|
||||||
|
|
||||||
=head1 Search and Device page Tabs
|
|
||||||
|
|
||||||
These components appear as tabs in the interface when the user reaches the
|
|
||||||
Search page or Device details page. Note that Tab plugins usually live in
|
|
||||||
the C<App::Netdisco::Web::Plugin::Device> or
|
|
||||||
C<App::Netdisco::Web::Plugin::Search> namespace.
|
|
||||||
|
|
||||||
To register a handler for display as a Search page Tab, use the following
|
|
||||||
code:
|
|
||||||
|
|
||||||
register_search_tab({tag => 'newfeature', label => 'My New Feature'});
|
|
||||||
|
|
||||||
This causes a tab to appear with the label "My New Feature". So how does
|
|
||||||
App::Netdisco know what the link should be? Well, as the
|
|
||||||
L<App::Netdisco::Developing> documentation says, tab content is retrieved by
|
|
||||||
an AJAX call back to the web server. This uses a predictable URL path format:
|
|
||||||
|
|
||||||
/ajax/content/<search or device>/<feature tag>
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
/ajax/content/search/newfeature
|
|
||||||
|
|
||||||
Therefore your plugin module should look like the following:
|
|
||||||
|
|
||||||
package App::Netdisco::Web::Plugin::Search::MyNewFeature
|
|
||||||
|
|
||||||
use Dancer ':syntax';
|
|
||||||
use Dancer::Plugin::DBIC;
|
|
||||||
use Dancer::Plugin::Auth::Extensible;
|
|
||||||
|
|
||||||
use App::Netdisco::Web::Plugin;
|
|
||||||
|
|
||||||
register_search_tab({tag => 'newfeature', label => 'My New Feature'});
|
|
||||||
|
|
||||||
get '/ajax/content/search/newfeature' => require_login sub {
|
|
||||||
# ...lorem ipsum...
|
|
||||||
|
|
||||||
# return some HTML content here, probably using a template
|
|
||||||
};
|
|
||||||
|
|
||||||
true;
|
|
||||||
|
|
||||||
If this all sounds a bit daunting, take a look at the
|
|
||||||
L<App::Netdisco::Web::Plugin::Search::Port> module which is fairly
|
|
||||||
straightforward.
|
|
||||||
|
|
||||||
To register a handler for display as a Device page Tab, the only difference is
|
|
||||||
the name of the registration helper sub:
|
|
||||||
|
|
||||||
register_device_tab({tag => 'newfeature', label => 'My New Feature'});
|
|
||||||
|
|
||||||
=head1 Reports
|
|
||||||
|
|
||||||
Report components contain pre-canned searches which the user community have
|
|
||||||
found to be useful. Before you go further, it might be the case that Netdisco
|
|
||||||
can generate the report for you without any Perl or HTML: see the L<Reports
|
|
||||||
Configuration|App::Netdisco::Manual::Configuration/reports> for details.
|
|
||||||
|
|
||||||
Otherwise, the typical implementation is very similar to one of the Search
|
|
||||||
and Device page Tabs, so please read that documentation above, first.
|
|
||||||
|
|
||||||
Report plugins usually live in the C<App::Netdisco::Web::Plugin::Report>
|
|
||||||
namespace. To register a handler for display as a Report, you need to pick the
|
|
||||||
I<category> of the report. Here are the pre-defined categories:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Device
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Port
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
IP
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Node
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
VLAN
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Network
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
Wireless
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Once your category is selected, use the following registration code:
|
|
||||||
|
|
||||||
register_report({
|
|
||||||
category => 'Port', # pick one from the list
|
|
||||||
tag => 'newreport',
|
|
||||||
label => 'My New Report',
|
|
||||||
});
|
|
||||||
|
|
||||||
You will note that like Device and Search page Tabs, there's no path
|
|
||||||
specified in the registration. The reports engine will make an AJAX request to
|
|
||||||
the following URL:
|
|
||||||
|
|
||||||
/ajax/content/report/<report tag>
|
|
||||||
|
|
||||||
Therefore you should implement in your plugin a route handler for this path.
|
|
||||||
The handler must return the HTML content for the report. It can also process
|
|
||||||
any query parameters which might customize the report search.
|
|
||||||
|
|
||||||
See the L<App::Netdisco::Web::Plugin::Report::DuplexMismatch> module for a
|
|
||||||
simple example of how to implement the handler.
|
|
||||||
|
|
||||||
An additional feature allows you to create Reports which do not appear in the
|
|
||||||
Navbar menu. This is useful if the page is only linked directly from another
|
|
||||||
(for example Port Log). To enable this feature add the C<hidden> key:
|
|
||||||
|
|
||||||
register_report({
|
|
||||||
tag => 'newfeature',
|
|
||||||
label => 'My New Feature',
|
|
||||||
hidden => true,
|
|
||||||
});
|
|
||||||
|
|
||||||
=head1 CSV Response
|
|
||||||
|
|
||||||
Most pages in Netdisco are a table with data. It's possible to have the
|
|
||||||
application add a link to download a CSV version of the same data. To do this,
|
|
||||||
include the following option in your call to C<register_search_tab>,
|
|
||||||
C<register_device_tab>, or C<register_report>:
|
|
||||||
|
|
||||||
provides_csv => 1
|
|
||||||
|
|
||||||
The other thing you need to do is adjust your Dancer route handler to return
|
|
||||||
either HTML or CSV data. Here's the typical way to do it:
|
|
||||||
|
|
||||||
get '/ajax/content/search/newfeature' => require_login sub {
|
|
||||||
# build some kind of dataset here (e.g. a DBIx::Class query)
|
|
||||||
|
|
||||||
if (request->is_ajax) {
|
|
||||||
template 'mytemplate', { data => $mydataset }, { layout => undef };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
|
||||||
template 'mytemplate_csv', { data => $mydataset }, { layout => undef };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Note that the C<is_ajax> call is part of the standard Dancer featureset.
|
|
||||||
|
|
||||||
=head1 Admin Tasks
|
|
||||||
|
|
||||||
These components appear in the black navigation bar under an Admin menu, but only
|
|
||||||
if the logged in user has Administrator rights in Netdisco.
|
|
||||||
|
|
||||||
To register an item for display in the Admin menu, use the following code:
|
|
||||||
|
|
||||||
register_admin_task({
|
|
||||||
tag => 'newfeature',
|
|
||||||
label => 'My New Feature',
|
|
||||||
});
|
|
||||||
|
|
||||||
This causes an item to appear in the Admin menu with a visible text of "My New
|
|
||||||
Feature" which when clicked sends the user to the C</admin/mynewfeature> page.
|
|
||||||
Note that this won't work for any target link - the path must be an
|
|
||||||
App::Netdisco Dancer route handler. Please bug the App::Netdisco devs if you
|
|
||||||
want arbitrary links supported.
|
|
||||||
|
|
||||||
An additional feature allows you to create Admin Tasks which do not appear in
|
|
||||||
the Navbar menu. This is useful if the page is only linked directly from
|
|
||||||
another. To enable this feature add the C<hidden> key:
|
|
||||||
|
|
||||||
register_admin_task({
|
|
||||||
tag => 'newfeature',
|
|
||||||
label => 'My New Feature',
|
|
||||||
hidden => true,
|
|
||||||
});
|
|
||||||
|
|
||||||
=head1 Device Port Columns
|
|
||||||
|
|
||||||
You can also add columns to the Device Ports page. The canonical example of
|
|
||||||
this is to add hyperlinks (or embedded images) of traffic graphs for each
|
|
||||||
port, however the plugin is a regular Template::Toolkit template so can be any
|
|
||||||
HTML output.
|
|
||||||
|
|
||||||
The column plugin has a name (used internally to locate files on disk), label
|
|
||||||
(the heading for the column in the table or CSV output), position in the table
|
|
||||||
(three options: left, mid, right), and finally a flag for whether the column
|
|
||||||
is displayed by default.
|
|
||||||
|
|
||||||
To register the column call the following helper routine:
|
|
||||||
|
|
||||||
register_device_port_column({
|
|
||||||
name => 'myportcolumnplugin',
|
|
||||||
label => 'My Port Column Heading',
|
|
||||||
position => 'left', # or "mid" or "right"
|
|
||||||
default => 'on', # or undef
|
|
||||||
});
|
|
||||||
|
|
||||||
App::Netdisco searches for Template::Toolkit files in the regular template
|
|
||||||
include paths: either its internal locations, or those configured with the
|
|
||||||
C<site_local_files> setting or the C<register_template_path> helper (see
|
|
||||||
below). The template must be called "C<device_port_column.tt>" on disk and
|
|
||||||
live in the directory:
|
|
||||||
|
|
||||||
plugin/myportcolumnplugin/device_port_column.tt
|
|
||||||
|
|
||||||
For a good example of this, see the L<App::NetdiscoX::Web::Plugin::Observium>
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
=head1 Device Details
|
|
||||||
|
|
||||||
You can add items to the Device Details tab as well. A good example of this is
|
|
||||||
to add a link to the RANCID backup of the device in a WebSVN app somewhere.
|
|
||||||
Like Device Port Columns plugins, the plugin is a regular Template::Toolkit
|
|
||||||
snippet so can be any HTML output.
|
|
||||||
|
|
||||||
The details plugin has a name (used internally to locate files on disk) and
|
|
||||||
label (the heading for the row in the table).
|
|
||||||
|
|
||||||
To register the column call the following helper routine:
|
|
||||||
|
|
||||||
register_device_details({
|
|
||||||
name => 'mydevicedetailsplugin',
|
|
||||||
label => 'My Device Details Heading',
|
|
||||||
});
|
|
||||||
|
|
||||||
App::Netdisco searches for Template::Toolkit files in the regular template
|
|
||||||
include paths: either its internal locations, or those configured with the
|
|
||||||
C<site_local_files> setting or the C<register_template_path> helper (see
|
|
||||||
below). The template must be called "C<device_port_column.tt>" on disk and
|
|
||||||
live in the directory:
|
|
||||||
|
|
||||||
plugin/mydevicedetailsplugin/device_details.tt
|
|
||||||
|
|
||||||
For a good example of this, see the L<App::NetdiscoX::Web::Plugin::RANCID>
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
=head1 User Authorization
|
|
||||||
|
|
||||||
All Dancer route handlers must have proper authorization configured. This is
|
|
||||||
not difficult. Make sure that your module loads the
|
|
||||||
L<Dancer::Plugin::Auth::Extensible> module (as shown above).
|
|
||||||
|
|
||||||
For each route handler you either simply require that a user be logged in, or
|
|
||||||
that the user is an administrator.
|
|
||||||
|
|
||||||
To require a logged in user, include the C<require_login> wrapper:
|
|
||||||
|
|
||||||
get '/ajax/content/search/newfeature' => require_login sub {
|
|
||||||
# etc .....
|
|
||||||
|
|
||||||
To require an administrator, specify their role:
|
|
||||||
|
|
||||||
get '/ajax/control/admin/newfeature' => require_role admin => sub {
|
|
||||||
# etc .....
|
|
||||||
|
|
||||||
Finally in case you need it, the other role a user can have is
|
|
||||||
C<port_control>:
|
|
||||||
|
|
||||||
ajax '/ajax/portcontrol' => require_role port_control => sub {
|
|
||||||
# etc .....
|
|
||||||
|
|
||||||
Take care over the subtle differences in syntax, especially the placement of
|
|
||||||
the fat comma ("C<< => >>").
|
|
||||||
|
|
||||||
=head1 Database Connections
|
|
||||||
|
|
||||||
The Netdisco database is available via the C<netdisco> schema key, as below.
|
|
||||||
You can also use the C<external_databases> configuration item to set up
|
|
||||||
connections to other databases.
|
|
||||||
|
|
||||||
# possibly install another database driver
|
|
||||||
~netdisco/bin/localenv cpanm --notest DBD::mysql
|
|
||||||
|
|
||||||
# deployment.yml
|
|
||||||
external_databases:
|
|
||||||
- tag: externaldb
|
|
||||||
dsn: 'dbi:mysql:dbname=myexternaldb;host=192.0.2.1'
|
|
||||||
user: oliver
|
|
||||||
password: letmein
|
|
||||||
|
|
||||||
# plugin code
|
|
||||||
use Dancer::Plugin::DBIC;
|
|
||||||
|
|
||||||
schema('netdisco')->resultset('Devices')->search({vendor => 'cisco'});
|
|
||||||
schema('externaldb')->resultset('MyTable')->search({field => 'foobar'});
|
|
||||||
|
|
||||||
You'll need to install a L<DBIx::Class> Schema and also set C<schema_class> to
|
|
||||||
its name within the C<external_databases> setting, for the second example
|
|
||||||
above.
|
|
||||||
|
|
||||||
=head1 Templates
|
|
||||||
|
|
||||||
All of Netdisco's web page templates are stashed away in its distribution,
|
|
||||||
probably installed in your system's or user's Perl directory. It's not
|
|
||||||
recommended that you mess about with those files.
|
|
||||||
|
|
||||||
So in order to replace a template with your own version, or to reference a
|
|
||||||
template file of your own in your plugin, you need a new path.
|
|
||||||
|
|
||||||
If you don't plan on redistributing the plugin via CPAN, then configuring the
|
|
||||||
"C<site_local_files>" setting to be true will enable "C</nd-site-local/lib>"
|
|
||||||
for Perl code and "C</nd-site-local/share>" for tmplates in your Netdisco home
|
|
||||||
location. You will need to create these directories.
|
|
||||||
|
|
||||||
Alternatively, shipping templates within a CPAN distribution, the following
|
|
||||||
code would be appropriate:
|
|
||||||
|
|
||||||
package App::Netdisco::Web::Plugin::Search::MyNewFeature
|
|
||||||
|
|
||||||
use File::ShareDir 'dist_dir';
|
|
||||||
register_template_path(
|
|
||||||
dist_dir( 'App-Netdisco-Web-Plugin-Search-MyNewFeature' ));
|
|
||||||
|
|
||||||
The "C<views>" subdirectory of the registered path will be searched before the
|
|
||||||
built-in C<App::Netdisco> path. We recommend use of the L<File::ShareDir>
|
|
||||||
module to package and ship templates along with your plugin, as shown.
|
|
||||||
|
|
||||||
Each path added using C<register_template_path> is searched I<before> any
|
|
||||||
existing paths in the template config. See the
|
|
||||||
L<App::NetdiscoX::Web::Plugin::Observium> distribution for a working example.
|
|
||||||
|
|
||||||
=head2 Template Variables
|
|
||||||
|
|
||||||
Some useful variables are made available in your templates automatically by
|
|
||||||
App::Netdisco:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item C<search_node>
|
|
||||||
|
|
||||||
A path and query string which links to the Node tab of the Search page,
|
|
||||||
together with the correct default search options set.
|
|
||||||
|
|
||||||
=item C<search_device>
|
|
||||||
|
|
||||||
A path and query string which links to the Device tab of the Search page,
|
|
||||||
together with the correct default search options set.
|
|
||||||
|
|
||||||
=item C<device_ports>
|
|
||||||
|
|
||||||
A path and query sting which links to the Ports tab of the Device page,
|
|
||||||
together with the correct default column view options set.
|
|
||||||
|
|
||||||
=item C<uri_base>
|
|
||||||
|
|
||||||
Used for linking to static content within App::Netdisco safely if the base of
|
|
||||||
the app is relocated, for example:
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/toastr.css"/>
|
|
||||||
|
|
||||||
=item C<uri_for>
|
|
||||||
|
|
||||||
Simply the Dancer C<uri_for> method. Allows you to do things like this in the
|
|
||||||
template safely if the base of the app is relocated:
|
|
||||||
|
|
||||||
<a href="[% uri_for('/search') %]" ...>
|
|
||||||
|
|
||||||
=item C<self_options>
|
|
||||||
|
|
||||||
Available in the Device tabs, use this if you need to refer back to the
|
|
||||||
current page with some additional parameters, for example:
|
|
||||||
|
|
||||||
<a href="[% uri_for('/device', self_options) %]&foo=bar" ...>
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 Javascript and Stylesheets
|
|
||||||
|
|
||||||
A simple mechanism exists for loading additional Javascript and CSS documents.
|
|
||||||
This is done in the C<< <head> >> section of the web page.
|
|
||||||
|
|
||||||
Netdisco searches all template include paths, both those built into the
|
|
||||||
application and those configured in your plugin(s) with "C<site_local_files>"
|
|
||||||
or C<register_template_path>.
|
|
||||||
|
|
||||||
Within the template location, create a directory called "C<plugin>" and within
|
|
||||||
that another directory named after your plugin (e.g. "C<mynewfeature>"). The
|
|
||||||
Javascript and/or CSS files must then be named "C<mynewfeature.js>" and
|
|
||||||
"C<mynewfeature.css>" respectively. For example:
|
|
||||||
|
|
||||||
plugin/mynewfeature/mynewfeature.js
|
|
||||||
plugin/mynewfeature/mynewfeature.css
|
|
||||||
|
|
||||||
Tell App::Netdisco that you wish to load one or the other using the following
|
|
||||||
helper routines:
|
|
||||||
|
|
||||||
register_javascript('mynewfeature');
|
|
||||||
register_css('mynewfeature');
|
|
||||||
|
|
||||||
=head1 Naming and File Location
|
|
||||||
|
|
||||||
There are several options for how you name, distribute and install your
|
|
||||||
App::Netdisco plugin.
|
|
||||||
|
|
||||||
=head2 Namespaces
|
|
||||||
|
|
||||||
As mentioned in L<App::Netdisco::Web::Plugin>, official Netdisco plugins live
|
|
||||||
in the C<App::Netdisco::Web::Plugin::> namespace. You can use this namespace
|
|
||||||
and submit the product to the Netdisco developer team for consideration for
|
|
||||||
inclusion in the official distribution.
|
|
||||||
|
|
||||||
Alternatively you can release the plugin to CPAN under your own account. In
|
|
||||||
that case we request that you instead use the C<App::NetdiscoX::Web::Plugin::>
|
|
||||||
namespace (note the "X"). Users can load such modules by using the
|
|
||||||
abbreviated form "X::MyPluginName" which is then expanded to the full package.
|
|
||||||
|
|
||||||
=head2 File Location
|
|
||||||
|
|
||||||
If writing your own plugins that are not for redistribution or packaging on
|
|
||||||
CPAN, Netdisco can enable local include paths for Perl, templates, and static
|
|
||||||
content such as javascript and images.
|
|
||||||
|
|
||||||
Configuring the "C<site_local_files>" to be "true" enables:
|
|
||||||
|
|
||||||
# perl code
|
|
||||||
$ENV{NETDISCO_HOME}/nd-site-local/lib
|
|
||||||
|
|
||||||
# templates and static content
|
|
||||||
$ENV{NETDISCO_HOME}/nd-site-local/share
|
|
||||||
|
|
||||||
Note that you still need to create the directories yourself, and templates may
|
|
||||||
need to have a further "C<views>" subdirectory created within "C<share>".
|
|
||||||
|
|
||||||
As an example, if your plugin is called
|
|
||||||
"App::NetdiscoX::Web::Plugin::MyPluginName" then it could live at:
|
|
||||||
|
|
||||||
~netdisco/nd-site-local/lib/App/NetdiscoX/Web/Plugin/MyPluginName.pm
|
|
||||||
|
|
||||||
=head1 Plugin Configuration
|
|
||||||
|
|
||||||
You can support new configuration items which the user should add to their
|
|
||||||
C<~/environments/deployment.yml> file. Please use a single Hash-Ref option
|
|
||||||
named "C<plugin_mypluginname>" (if your plugin's called C<mypluginname>). For
|
|
||||||
example:
|
|
||||||
|
|
||||||
plugin_observium:
|
|
||||||
webhost: "web-server.example.com"
|
|
||||||
open_in_new_window: true
|
|
||||||
|
|
||||||
You can then refer to this configuration in your plugin module:
|
|
||||||
|
|
||||||
my $webhost = setting('plugin_observium')->{'webhost'};
|
|
||||||
|
|
||||||
Or in templates via Dancer's C<settings> key:
|
|
||||||
|
|
||||||
<a href="http://[% settings.plugin_observium.webhost | uri %]/>Observium</a>
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
=head1 NAME
|
|
||||||
|
|
||||||
App::Netdisco::Manual::WritingWorkers - Developer Documentation on Worker Plugins
|
|
||||||
|
|
||||||
=head1 Introduction
|
|
||||||
|
|
||||||
L<App::Netdisco>'s plugin system allows users to write I<workers> to gather
|
|
||||||
information from network devices using different I<transports> and store
|
|
||||||
results in the database.
|
|
||||||
|
|
||||||
For example, transports might be SNMP, SSH, or HTTPS. Workers might be
|
|
||||||
combining those transports with application protocols such as SNMP, NETCONF
|
|
||||||
(OpenConfig with XML), RESTCONF (OpenConfig with JSON), eAPI, or even CLI
|
|
||||||
scraping. The combination of transport and protocol is known as a I<driver>.
|
|
||||||
|
|
||||||
Workers can be restricted to certain vendor platforms using familiar ACL
|
|
||||||
syntax. They are also attached to specific actions in Netdisco's backend
|
|
||||||
operation (discover, macsuck, etc).
|
|
||||||
|
|
||||||
See L<App::Netdisco::Worker::Plugin> for more information about worker
|
|
||||||
plugins.
|
|
||||||
|
|
||||||
=head1 Developing Workers
|
|
||||||
|
|
||||||
A worker is Perl code which is run. Therefore it can do anything you like, but
|
|
||||||
typically it will make a connection to a device, gather some data, and store
|
|
||||||
it in Netdisco's database.
|
|
||||||
|
|
||||||
App::Netdisco plugins must load the L<App::Netdisco::Worker::Plugin> module.
|
|
||||||
This exports a helper subroutine to register the worker. Here's the
|
|
||||||
boilerplate code for our example plugin module:
|
|
||||||
|
|
||||||
package App::Netdisco::Worker::Plugin::Discover::Wireless::UniFi;
|
|
||||||
|
|
||||||
use Dancer ':syntax';
|
|
||||||
use App::Netdisco::Worker::Plugin;
|
|
||||||
use aliased 'App::Netdisco::Worker::Status';
|
|
||||||
|
|
||||||
# worker registration code goes here, ** see below **
|
|
||||||
|
|
||||||
true;
|
|
||||||
|
|
||||||
=head1 Registering a Worker
|
|
||||||
|
|
||||||
Use the C<register_worker> helper from L<App::Netdisco::Worker::Plugin> to
|
|
||||||
register a worker:
|
|
||||||
|
|
||||||
register_worker( $coderef );
|
|
||||||
# or
|
|
||||||
register_worker( \%workerconf, $coderef );
|
|
||||||
|
|
||||||
For example (using the second form):
|
|
||||||
|
|
||||||
register_worker({
|
|
||||||
driver => 'unifiapi',
|
|
||||||
}, sub { "worker code here" });
|
|
||||||
|
|
||||||
The C<%workerconf> hashref is optional, and described below. The C<$coderef>
|
|
||||||
is the main body of your worker. Your worker is run in a L<Try::Tiny>
|
|
||||||
statement to catch errors, and passed the following arguments:
|
|
||||||
|
|
||||||
$coderef->($job, \%workerconf);
|
|
||||||
|
|
||||||
The C<$job> is an instance of L<App::Netdisco::Backend::Job>. Note that this
|
|
||||||
class has a C<device> slot which may be filled, depending on the action, and
|
|
||||||
if the device is not yet discovered then the row will not yet be in storage.
|
|
||||||
The C<\%workerconf> hashref is the set of configuration parameters you used
|
|
||||||
to declare the worker (documented below).
|
|
||||||
|
|
||||||
=head2 Package Naming Convention
|
|
||||||
|
|
||||||
The package name used where the worker is declared is significant. Let's look
|
|
||||||
at the boilerplate example again:
|
|
||||||
|
|
||||||
package App::Netdisco::Worker::Plugin::Discover::Wireless::UniFi;
|
|
||||||
|
|
||||||
The package name B<must> contain C<Plugin::> and the namespace component after
|
|
||||||
that becomes the action. For example workers registered in the above package
|
|
||||||
will be run during the I<discover> backend action (that is, during a
|
|
||||||
C<discover> job). You can replace C<Discover> with other actions such as
|
|
||||||
C<Macsuck>, C<Arpnip>, C<Expire>, and C<Nbtstat>, or create your own.
|
|
||||||
|
|
||||||
The component after the action is known as the I<phase> (C<Wireless> in this
|
|
||||||
example), and is the way to override a Netdisco built-in worker, by using the
|
|
||||||
same name (plus an entry in C<%workerconf>, see below). Otherwise you can use
|
|
||||||
any valid Perl bareword for the phase.
|
|
||||||
|
|
||||||
Workers may also be registered directly to the action (C<Discover>, in this
|
|
||||||
example), without any phase. This is used for very early bootstrapping code
|
|
||||||
(such as first inserting a device into the database so it can be used by
|
|
||||||
subsequent phases) or for very simple, generic actions (such as C<netdisco-do
|
|
||||||
psql>).
|
|
||||||
|
|
||||||
=head2 C<%workerconf> Options
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item ACL Options
|
|
||||||
|
|
||||||
Workers may have C<only> and C<no> parameters configured which use the
|
|
||||||
standard ACL syntax described in L<the settings
|
|
||||||
guide|App::Netdisco::Manual::Configuration>. The C<only> directive is
|
|
||||||
especially useful as it can restrict a worker to a given device platform or
|
|
||||||
operating system (for example Cisco IOS XR for the C<restconf> driver).
|
|
||||||
|
|
||||||
=item C<driver> (string)
|
|
||||||
|
|
||||||
The driver is a label associated with a group of workers and typically refers
|
|
||||||
to the combination of transport and application protocol. Examples include
|
|
||||||
C<snmp>, C<netconf>, C<restconf>, C<eapi>, and C<cli>. The convention is for
|
|
||||||
driver names to be lowercase.
|
|
||||||
|
|
||||||
Users will bind authentication configuration settings to drivers in their
|
|
||||||
configuration. If no driver is specified when registering a worker, it will be
|
|
||||||
run for every device and phase (such as during Expire jobs).
|
|
||||||
|
|
||||||
=item C<primary> (boolean)
|
|
||||||
|
|
||||||
When multiple workers are registered for the same phase, they will all be run.
|
|
||||||
However there is a special "I<primary>" slot for each phase in which only one
|
|
||||||
worker (the first that succeeds) is used. Most of Netdisco's built-in worker
|
|
||||||
code is registered in this way, so to override it you can use the same package
|
|
||||||
namespace and set C<primary> to be C<true>.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 Worker Execution and Return Code
|
|
||||||
|
|
||||||
Workers are configured as an ordered list. They are grouped by C<action> and
|
|
||||||
C<phase> (as in Package Naming Convention, above).
|
|
||||||
|
|
||||||
Workers defined in C<extra_worker_plugins> are run before those in
|
|
||||||
C<worker_plugins> so you have an opportunity to override built-in workers by
|
|
||||||
adding them to C<extra_worker_plugins> and setting C<primary> to C<true> in
|
|
||||||
the worker configuration.
|
|
||||||
|
|
||||||
The return code of the worker is significant for those configured with
|
|
||||||
C<primary> as C<true>: when the worker returns true, no other C<primary> hooks
|
|
||||||
are run for that phase. You should always use the aliased
|
|
||||||
L<App::Netdisco::Worker::Status> helper (loaded as in the boilerplate code
|
|
||||||
above) when returning a value, such as:
|
|
||||||
|
|
||||||
return Status->done('everything is good');
|
|
||||||
# or
|
|
||||||
return Status->error('something went wrong');
|
|
||||||
# or
|
|
||||||
return Status->defer('this device cannot be processed right now');
|
|
||||||
|
|
||||||
Remember that a worker is only run if it matches the hardware platform of the
|
|
||||||
target device and the user's configuration, and is not also excluded by the
|
|
||||||
user's configuration. This filtering takes place before inspecting C<primary>.
|
|
||||||
|
|
||||||
=head1 Accessing Transports
|
|
||||||
|
|
||||||
From your worker you will want to connect to a device to gather data. This is
|
|
||||||
done using a transport protocol session (SNMP, SSH, etc). Transports are
|
|
||||||
singleton objects instantiated on demand, so they can be shared among a set of
|
|
||||||
workers that are accessing the same device.
|
|
||||||
|
|
||||||
See the documentation for each transport to find out how to access it:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
L<App::Netdisco::Transport::SNMP>
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 Database Connections
|
|
||||||
|
|
||||||
The Netdisco database is available via the C<netdisco> schema key, as below.
|
|
||||||
You can also use the C<external_databases> configuration item to set up
|
|
||||||
connections to other databases.
|
|
||||||
|
|
||||||
# plugin package
|
|
||||||
use Dancer::Plugin::DBIC;
|
|
||||||
my $set =
|
|
||||||
schema('netdisco')->resultset('Devices')
|
|
||||||
->search({vendor => 'cisco'});
|
|
||||||
|
|
||||||
=head1 Review of Terminology
|
|
||||||
|
|
||||||
In summary, Worker code is defined in a package namespace specifying the
|
|
||||||
Action and Phase, and registered as a plugin with configuration which may
|
|
||||||
specify the Driver and whether it is in the Primary slot. Access Control Lists
|
|
||||||
determine which Workers are permitted to run, and when. Here are more complete
|
|
||||||
definitions:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item C<action>
|
|
||||||
|
|
||||||
The highest level grouping of workers, corresponding to a Netdisco command
|
|
||||||
such as C<discover> or C<macsuck>. Workers can be registered at this level to
|
|
||||||
do really early bootstrapping work.
|
|
||||||
|
|
||||||
=item C<phase>
|
|
||||||
|
|
||||||
The next level down from C<action> for grouping workers. Phases have arbitrary
|
|
||||||
names and are visited in the order defined in the C<extra_worker_plugins>
|
|
||||||
setting list, followed by the C<worker_plugins> setting list. Workers are
|
|
||||||
usually registered at this level.
|
|
||||||
|
|
||||||
=item C<worker>
|
|
||||||
|
|
||||||
A lump of code you write which does a single clearly defined task. The package
|
|
||||||
namespace of the worker identifies the action and optionally the phase.
|
|
||||||
Workers are typically registered with some configuration settings.
|
|
||||||
|
|
||||||
=item C<driver>
|
|
||||||
|
|
||||||
A label associated with a group of workers which refers to a combination of
|
|
||||||
transport and application protocol used to connect to and communicate with the
|
|
||||||
target device. Users attach authentication configuration to specific drivers.
|
|
||||||
|
|
||||||
=item C<primary> (defaults to C<false>)
|
|
||||||
|
|
||||||
Indicates that the worker will only be run if no other C<primary> worker for
|
|
||||||
this phase has already succeeded. In this way, you can override Netdisco code
|
|
||||||
by setting this option and returning true from your worker.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
@@ -232,65 +232,7 @@ Admin Menu function (job control, manual topology, pseudo devices)
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
This document explains how to configure which plugins are loaded. See
|
See L<https://github.com/netdisco/netdisco/wiki/Web-Plugins> for details.
|
||||||
L<App::Netdisco::Manual::WritingWebPlugins> if you want to develop new
|
|
||||||
plugins.
|
|
||||||
|
|
||||||
=head1 Application Configuration
|
|
||||||
|
|
||||||
Netdisco configuration supports a C<web_plugins> directive along with the
|
|
||||||
similar C<extra_web_plugins>. These list, in YAML format, the set of Perl
|
|
||||||
module names which are the plugins to be loaded. Each item injects one part of
|
|
||||||
the Netdisco web user interface.
|
|
||||||
|
|
||||||
You can override these settings to add, change, or remove entries from the
|
|
||||||
default lists. Here is an example of the C<web_plugins> list:
|
|
||||||
|
|
||||||
web_plugins:
|
|
||||||
- Inventory
|
|
||||||
- Report::DuplexMismatch
|
|
||||||
- Search::Device
|
|
||||||
- Search::Node
|
|
||||||
- Search::Port
|
|
||||||
- Device::Details
|
|
||||||
- Device::Ports
|
|
||||||
|
|
||||||
Any change should go into your local C<deployment.yml> configuration file. If
|
|
||||||
you want to view the default settings, see the C<share/config.yml> file in the
|
|
||||||
C<App::Netdisco> distribution.
|
|
||||||
|
|
||||||
=head1 How to Configure
|
|
||||||
|
|
||||||
The C<extra_web_plugins> setting is empty, and used only if you want to add
|
|
||||||
new plugins but not change the set enabled by default. If you do want to add
|
|
||||||
to or remove from the default set, then create a version of C<web_plugins>
|
|
||||||
instead.
|
|
||||||
|
|
||||||
Netdisco prepends "C<App::Netdisco::Web::Plugin::>" to any entry in the list.
|
|
||||||
For example, "C<Inventory>" will load the
|
|
||||||
C<App::Netdisco::Web::Plugin::Inventory> module.
|
|
||||||
|
|
||||||
Such plugin modules can either ship with the App::Netdisco distribution
|
|
||||||
itself, or be installed separately. Perl uses the standard C<@INC> path
|
|
||||||
searching mechanism to load the plugin modules.
|
|
||||||
|
|
||||||
If an entry in the list starts with a "C<+>" (plus) sign then Netdisco attemps
|
|
||||||
to load the module as-is, without prepending anything to the name. This allows
|
|
||||||
you to have App::Netdiso web UI plugins in other namespaces:
|
|
||||||
|
|
||||||
web_plugins:
|
|
||||||
- Inventory
|
|
||||||
- Search::Device
|
|
||||||
- Device::Details
|
|
||||||
- +My::Other::Netdisco::Web::Component
|
|
||||||
|
|
||||||
The order of the entries is significant. Unsurprisingly, the modules are
|
|
||||||
loaded in order. Therefore Navigation Bar items appear in the order listed,
|
|
||||||
and Tabs appear on the Search and Device pages in the order listed, and so on.
|
|
||||||
|
|
||||||
Finally, you can also prepend module names with "C<X::>", to support the
|
|
||||||
"Netdisco extension" namespace. For example, "C<X::Observium>" will load the
|
|
||||||
L<App::NetdiscoX::Web::Plugin::Observium> module.
|
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
|||||||
@@ -115,50 +115,7 @@ Workers can be restricted to certain vendor platforms using familiar ACL
|
|||||||
syntax. They are also attached to specific actions in Netdisco's backend
|
syntax. They are also attached to specific actions in Netdisco's backend
|
||||||
operation (discover, macsuck, etc).
|
operation (discover, macsuck, etc).
|
||||||
|
|
||||||
=head1 Application Configuration
|
See L<https://github.com/netdisco/netdisco/wiki/Backend-Plugins> for details.
|
||||||
|
|
||||||
The C<worker_plugins> and C<extra_worker_plugins> settings list in YAML format
|
|
||||||
the set of Perl module names which are the plugins to be loaded.
|
|
||||||
|
|
||||||
Any change should go into your local C<deployment.yml> configuration file. If
|
|
||||||
you want to view the default settings, see the C<share/config.yml> file in the
|
|
||||||
C<App::Netdisco> distribution.
|
|
||||||
|
|
||||||
=head1 How to Configure
|
|
||||||
|
|
||||||
The C<extra_worker_plugins> setting is empty, and used when you want to add
|
|
||||||
new plugins and not change the set enabled by default. If you do want to add
|
|
||||||
to or remove from the default set, then create a version of C<worker_plugins>
|
|
||||||
instead.
|
|
||||||
|
|
||||||
Netdisco prepends "C<App::Netdisco::Worker::Plugin::>" to any entry in the
|
|
||||||
list. For example, "C<Discover::Wireless::UniFi>" will load the
|
|
||||||
C<App::Netdisco::Worker::Plugin::Discover::Wireless::UniFi> package.
|
|
||||||
|
|
||||||
You can prepend module names with "C<X::>" as shorthand for the "Netdisco
|
|
||||||
extension" namespace. For example, "C<X::Macsuck::WirelessNodes::UniFi>" will
|
|
||||||
load the L<App::NetdiscoX::Worker::Plugin::Macsuck::WirelessNodes::UniFi>
|
|
||||||
module.
|
|
||||||
|
|
||||||
If an entry in the list starts with a "C<+>" (plus) sign then Netdisco attemps
|
|
||||||
to load the module as-is, without prepending anything to the name. This allows
|
|
||||||
you to have worker plugins in any namespace.
|
|
||||||
|
|
||||||
Plugin modules can either ship with the App::Netdisco distribution itself, or
|
|
||||||
be installed separately. Perl uses the standard C<@INC> path searching
|
|
||||||
mechanism to load the plugin modules. See the C<include_paths> and
|
|
||||||
C<site_local_files> settings in order to modify C<@INC> for loading local
|
|
||||||
plugins.
|
|
||||||
|
|
||||||
As an example, if you set C<site_local_files> to be true, set
|
|
||||||
C<extra_worker_plugins> to be C<'X::MyPluginName'> (the plugin package is
|
|
||||||
"App::NetdiscoX::Worker::Plugin::MyPluginName") then your plugin lives at:
|
|
||||||
|
|
||||||
~netdisco/nd-site-local/lib/App/NetdiscoX/Worker/Plugin/MyPluginName.pm
|
|
||||||
|
|
||||||
The order of the entries is significant, workers being executed in the order
|
|
||||||
which they appear in C<extra_worker_plugins> followed by C<worker_plugins>.
|
|
||||||
|
|
||||||
See L<App::Netdisco::Manual::WritingWorkers> for further details.
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user