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
|
||||
|
||||
We have several other pages with tips for
|
||||
L<alternate deployment scenarios|App::Netdisco::Manual::Deployment>,
|
||||
L<understanding and troubleshooting Netdisco|App::Netdisco::Manual::Troubleshooting>,
|
||||
L<tips and tricks for specific platforms|App::Netdisco::Manual::Vendors>,
|
||||
and L<all the configuration options|App::Netdisco::Manual::Configuration>.
|
||||
L<alternate deployment scenarios|https://github.com/netdisco/netdisco/wiki/Install-Tips>,
|
||||
L<understanding and troubleshooting Netdisco|https://github.com/netdisco/netdisco/wiki/Troubleshooting>,
|
||||
L<tips and tricks for specific platforms|https://github.com/netdisco/netdisco/wiki/Vendor-Tips>,
|
||||
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
|
||||
the L<community email list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
an on-line installation, and have the application run self-contained from
|
||||
within that user's home. There are alternatives: see the
|
||||
L<Deployment|App::Netdisco::Manual::Deployment> documentation for further
|
||||
details.
|
||||
L<Deployment|https://github.com/netdisco/netdisco/wiki/Install-Tips>
|
||||
documentation for further details.
|
||||
|
||||
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
|
||||
@@ -160,7 +160,7 @@ uncomment the C<schedule> setting to enable SNMP data gathering from
|
||||
devices (this replaces cron jobs in Netdisco 1).
|
||||
|
||||
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.
|
||||
|
||||
=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
|
||||
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
|
||||
|
||||
@@ -196,15 +196,15 @@ C<~netdisco/perl5> directory and re-run the C<curl> command above, to update
|
||||
Netdisco's C library bindings.
|
||||
|
||||
We have several other pages with tips for
|
||||
L<alternate deployment scenarios|App::Netdisco::Manual::Deployment>,
|
||||
L<understanding and troubleshooting Netdisco|App::Netdisco::Manual::Troubleshooting>,
|
||||
L<tips and tricks for specific platforms|App::Netdisco::Manual::Vendors>,
|
||||
and L<all the configuration options|App::Netdisco::Manual::Configuration>.
|
||||
L<alternate deployment scenarios|https://github.com/netdisco/netdisco/wiki/Install-Tips>,
|
||||
L<understanding and troubleshooting Netdisco|https://github.com/netdisco/netdisco/wiki/Troubleshooting>,
|
||||
L<tips and tricks for specific platforms|https://github.com/netdisco/netdisco/wiki/Vendor-Tips>,
|
||||
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
|
||||
the L<community email list|https://lists.sourceforge.net/lists/listinfo/netdisco-users>.
|
||||
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
|
||||
|
||||
@@ -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
|
||||
version 2.x only.
|
||||
|
||||
Before upgrading please review the latest L<Release
|
||||
Notes|App::Netdisco::Manual::ReleaseNotes>. Then the process below should be
|
||||
run for each installation:
|
||||
Before upgrading please review the latest L<Release Notes|https://github.com/netdisco/netdisco/wiki/Release-Notes>.
|
||||
Then the process below should be run for each installation:
|
||||
|
||||
# upgrade Netdisco
|
||||
~/bin/localenv cpanm --notest App::Netdisco
|
||||
@@ -262,18 +261,20 @@ run:
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
=head2 Plugins
|
||||
|
||||
Netdisco includes a Plugin subsystem for customizing the web user interface.
|
||||
See L<App::Netdisco::Web::Plugin> for further information.
|
||||
Netdisco includes a Plugin subsystem for customizing the web user interface and backend daemon.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
This document explains how to configure which plugins are loaded. See
|
||||
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.
|
||||
See L<https://github.com/netdisco/netdisco/wiki/Web-Plugins> for details.
|
||||
|
||||
=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
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user