Files
netdisco/lib/App/Netdisco/Manual/Developing.pod
Oliver Gorwits 5ff7d6fe47 Merge the backend worker plugins branch og-coreplugins
Squashed commit of the following:

commit 86d0f61d0b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu Nov 16 22:26:32 2017 +0000

    fix typo

commit 5aff19621c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu Nov 16 22:10:18 2017 +0000

    fix use of snmp_connect_ip which does not work for SNMPv3

commit 68a56d35bb
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu Nov 16 20:50:16 2017 +0000

    no need for Array::Iterator even though it was cute

commit 71ee869c02
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Nov 15 22:14:47 2017 +0000

    additional doc examples

commit 620b3fe544
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Nov 15 22:09:05 2017 +0000

    stash workers within poller instance, and load plugins explicitly

commit 2431365583
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Nov 13 22:17:11 2017 +0000

    better fix for duplicate module entity index

commit a400b26704
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Nov 13 22:14:42 2017 +0000

    add ignore interfaces for HPE routers

commit 1502ec1966
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Nov 13 22:08:02 2017 +0000

    bug fixes after testing on a real network

commit 840b6b4069
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Nov 12 20:38:35 2017 +0000

    add tests

commit 2de36c69ba
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Nov 12 00:14:21 2017 +0000

    some reengineering to support proper testing

commit c5f138fe62
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Nov 11 14:43:53 2017 +0000

    correct algorithm on finalise status, correct logging

commit 98442a2308
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu Nov 9 21:49:45 2017 +0000

    bug fixes

commit e0c6615c87
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Nov 8 20:29:33 2017 +0000

    fix bugs

commit 1eeaba441d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Nov 7 22:30:55 2017 +0000

    finish refactor to new desired behaviour (buggy?)

commit 7edfe88f25
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Nov 6 22:50:51 2017 +0000

    fix to work, and correct namespace check

commit 25907d3544
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Nov 6 21:26:01 2017 +0000

    move status tracking and checking inside job instance

commit 4436150bf4
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Nov 5 20:54:28 2017 +0000

    remove global rubbish

commit 28b016e713
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Nov 4 23:31:51 2017 +0000

    fix docs

commit 650f6c719b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Nov 4 23:22:12 2017 +0000

    tidy line

commit 10f78d5dbe
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Nov 4 23:06:20 2017 +0000

    add priority and namespace to support fancy worker overrides

commit b9f9816d09
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Oct 11 18:33:46 2017 +0100

    release 2.036012_001

commit c33bf204a4
Merge: 5b7ce3f7 d3d81eb6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Oct 11 18:30:23 2017 +0100

    Merge branch 'master' into og-coreplugins

commit 5b7ce3f797
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Oct 9 15:46:09 2017 +0100

    cannot Sereal::Encode DBIC row

commit 0a575f02ba
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Oct 9 14:07:56 2017 +0100

    fix bug in job->device init

commit 207476950d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Oct 9 14:03:37 2017 +0100

    default causes no attr to be created?!

commit 912f2fa91f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Oct 8 18:43:51 2017 +0100

    better debug logging

commit dfeb9d9ddc
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Oct 8 18:40:02 2017 +0100

    make device_auth have driver setting for snmp entries

commit 460c0c0ee9
Merge: 3ccd107b 98423445
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Oct 8 18:08:58 2017 +0100

    Merge branch 'master' into og-coreplugins

commit 3ccd107bd4
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 14:13:58 2017 +0100

    fix bug in device->has_layer

commit a4b9bf2036
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 13:58:52 2017 +0100

    netdisco-do show takes a param for method in -p

commit 4389cd0459
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 13:36:06 2017 +0100

    fix to only check last poll on devices in storage

commit 58d0fbddda
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 13:21:13 2017 +0100

    do not run discover parts if properties failed to complete

commit b52aaaf1a1
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 13:08:46 2017 +0100

    fix typo

commit 41be926921
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 13:04:45 2017 +0100

    run all check workers

commit a41d114965
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 13:02:46 2017 +0100

    fix driver config

commit b10908a138
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 12:43:50 2017 +0100

    use vars() cache between phases

commit 08b34e083d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 11:39:17 2017 +0100

    remove die() calls

commit b8108986fb
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 11:31:59 2017 +0100

    phase fixups

commit 273cbbc11b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 09:42:41 2017 +0100

    change stage to phase

commit 256c10bae5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 09:35:14 2017 +0100

    multi worker actions need not return done from all workers

commit ee38bae48a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 09:05:25 2017 +0100

    store result of worker if best for this phase so far

commit 5bddfc73ba
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Oct 7 08:50:31 2017 +0100

    auto debug-log worker return messages

commit 8b660a89c0
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Oct 6 07:48:58 2017 +0100

    bug fixes

commit b58a5816a9
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Oct 6 07:44:20 2017 +0100

    remove unnecessary check phases

commit e44f06364a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Oct 6 07:18:03 2017 +0100

    fix unknown command check in netdisco-do

commit 3af13f0dfe
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Oct 6 07:15:59 2017 +0100

    introduce noop and refactor checks in all workers

commit 98463c8cad
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Oct 1 10:49:12 2017 +0100

    no need to debug log if there are no hooks in phase

commit 3b32e84312
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Oct 1 08:18:13 2017 +0100

    fiddle about with runner logic to fix exit states

commit 8fdba38ee0
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Sep 29 08:01:42 2017 +0100

    cannot reuse a worker as the job will be already set and the wrong plugins loaded

commit a155d9cb77
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Sep 29 08:01:06 2017 +0100

    should defer when we cannot connect to device

commit 10b5f6cbc4
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Sep 29 08:00:32 2017 +0100

    fix bug in where workerconf acls are checked

commit 2a74e0befa
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Sep 29 07:38:05 2017 +0100

    can pass device instance to check_*

commit 4256b117df
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Sep 29 07:27:14 2017 +0100

    move device_auth build to be with community defaults setting

commit a2de2c1616
Merge: 32be11c3 8dc4b9bc
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri Sep 29 07:21:03 2017 +0100

    Merge branch 'master' into og-coreplugins

commit 32be11c3ff
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu Sep 21 00:09:29 2017 +0100

    move remaining interactive actions to be plugins

commit 3e41c93f5a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 20 21:47:50 2017 +0100

    clean snmp handling

commit 30a2d5dd86
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 20 21:00:29 2017 +0100

    make sure check plugins are loaded/run before phases

commit 3454d95a84
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 20 20:53:52 2017 +0100

    capture result on main phase as well

commit 559fa4f93f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 18 22:46:35 2017 +0100

    build device_auth from communities

commit 1969291719
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 18 22:04:22 2017 +0100

    simplify to remove phases and fewer hooks

commit 6f78032e28
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu Sep 14 21:30:03 2017 +0100

    add phase to test worker

commit 6edd2dc879
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 13 21:51:40 2017 +0100

    no need to list all plugins

commit dfaeb34d8c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 13 20:42:41 2017 +0100

    add reset after messing with snmp context or community index

commit 09214dce92
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 13 20:29:21 2017 +0100

    no need to pass $snmp around

commit 58cd488ccc
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 13 19:22:40 2017 +0100

    refactor layer and pseudo checks

commit 753acc607f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 13 10:53:12 2017 +0100

    use overloaded $device

commit d5d39289d6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 13 10:44:31 2017 +0100

    rename init stage to check

commit 1fdb086183
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 12 08:12:12 2017 +0100

    refactor to remove second loop

commit 64a9491115
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 10 16:09:45 2017 +0100

    change to init, first, second stages

commit 5f2da69697
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 9 22:26:04 2017 +0100

    move discover and discoverall to worker plugins

commit c6ebb7cf07
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 9 16:44:32 2017 +0100

    move arpnip and arpwalk to worker plugins

commit 16a79463cb
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 9 16:27:58 2017 +0100

    set snmp driver on macsuck phase workers

commit 9167e02de5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 9 15:55:53 2017 +0100

    move macsuck and macwalk to worker plugins (macsuck needs snmp scope guard)

commit 68ca85643b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 9 14:56:15 2017 +0100

    move expire and expirenodes to worker plugins

commit 271ef1a25c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 9 14:46:00 2017 +0100

    move nbtstat and nbtwalk to worker plugins

commit e7508a9eca
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 6 21:23:54 2017 +0100

    move all netdisco-do action to worker plugins

commit 707fc82b99
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 6 21:01:37 2017 +0100

    remove psql code from netdisco-do and fix detection of misspelled action

commit 411918e3f8
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 6 20:56:26 2017 +0100

    only load worker plugins for the action

commit 1f9740c0e2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 6 18:30:43 2017 +0100

    shorten hook names

commit a59c23de79
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Sep 6 18:27:34 2017 +0100

    make psql worker primary, add hook debug log

commit 36c70220a2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 22:39:22 2017 +0100

    allow two forms of worker declaration, and update docs

commit a79cb9a9e4
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 22:10:53 2017 +0100

    all the bug fixes and a working plugin!!!!!!!!! :-D

commit 04896202e0
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 21:39:41 2017 +0100

    refine runner

commit 547fce2f3c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 20:56:21 2017 +0100

    hack the status class to regen if needed

commit cd71a0b7a8
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 20:41:05 2017 +0100

    move status update to job class

commit c8e5cea4ed
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 20:37:13 2017 +0100

    objectify the running

commit f48004fffa
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 19:58:28 2017 +0100

    bug squish

commit 46ece568f6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 19:54:57 2017 +0100

    implement runner?!

commit fc9c60f707
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 19:28:38 2017 +0100

    rename ok to is_ok and change slot names to avoid conflict with creators

commit 3ee85383ab
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Sep 5 19:25:41 2017 +0100

    skip worker when action is per-device but no creds

commit 75abdad812
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 4 21:54:37 2017 +0100

    further work on retval handling from workers

commit 4c1fdf4f92
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 4 20:37:53 2017 +0100

    move worker plugin loader to Worker.pm

commit be0c5181a3
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 4 20:35:42 2017 +0100

    move Runner to Worker namespace

commit 1c2cf924bc
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 4 20:33:20 2017 +0100

    worker roles in Role namespace

commit 3099eda393
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Sep 4 20:30:58 2017 +0100

    load workers when runner role is loaded

commit a8c58a7b05
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 22:30:28 2017 +0100

    initial broken implementation of the runner

commit 49b5274c33
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 19:04:20 2017 +0100

    use run() mixin to exec action

commit e0a666668a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 18:54:44 2017 +0100

    fix pod; set status defaults; stub runner mixin

commit 8eaa33770c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 18:45:00 2017 +0100

    rename Core to Worker and move other packages around

commit 4def0af0b0
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 17:58:03 2017 +0100

    better use of new status class

commit 8675bf62c6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 17:27:38 2017 +0100

    fix hook naming and implement primary workers

commit ef1bb81f2b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 17:26:27 2017 +0100

    new backend status class

commit 5f50dfadf1
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 16:51:55 2017 +0100

    new Backend package to load core plugins

commit 3baa7a818a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 16:22:29 2017 +0100

    remove unnecessary Worker::Common role

commit 36b4adcc06
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Sep 3 16:17:29 2017 +0100

    disambiguate util/backend package and remove backend prelaod

commit 98bff731bd
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Sep 2 08:25:06 2017 +0100

    settle on a design for hook override, I think

commit fe5c16a16d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Aug 30 20:37:36 2017 +0100

    rework docs to be more clear and reflect new operation

commit b34ba1977c
Merge: 31d1977f c34ed61d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Aug 21 21:17:46 2017 +0100

    Merge branch 'master' into og-coreplugins

commit 31d1977f1e
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Aug 14 18:11:42 2017 +0100

    Revert "move expire code to be initial plugin pilot (broken)"

    I think we'll only do the new backend code for jobs with a device.

    This reverts commit 07998b72d9.

commit 61dc80aff8
Merge: 07998b72 ade02db1
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Aug 14 18:10:29 2017 +0100

    Merge branch 'master' into og-coreplugins

commit 07998b72d9
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Aug 5 22:15:00 2017 +0100

    move expire code to be initial plugin pilot (broken)

commit 685ec02108
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Aug 5 22:10:58 2017 +0100

    pass $job to the core worker

commit d6523fe543
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Aug 5 22:01:49 2017 +0100

    $job->device is always a DBIC row

commit ee6deea01b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Aug 5 18:12:34 2017 +0100

    load plugins

commit fd80096ca2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Aug 5 16:53:16 2017 +0100

    rename all the things

commit 464c42d1f5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Aug 2 10:19:16 2017 +0100

    use Scope::Guard to reduce device_auth

commit ec041dafd2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Aug 1 15:34:37 2017 +0100

    the other way around

commit 33d2fe13bd
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jul 31 17:57:29 2017 +0100

    fix pod

commit 3faee1cf16
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jul 31 17:55:10 2017 +0100

    remove need for instance() call

commit c6d0f1c035
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Jul 26 13:51:23 2017 +0100

    add doc note on accessing transports

commit dca4b4fc03
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Jul 26 11:50:10 2017 +0100

    add backend driver documentation

commit 052a2acd79
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Jul 26 10:16:58 2017 +0100

    rename web plugins doc

commit 69c9a6393a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Jul 26 10:12:42 2017 +0100

    rename args to driverconf

commit 2586a36f8c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Jul 25 22:41:10 2017 +0100

    new version of core plugin manager with better config and filters

commit 4056831f99
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue Jul 25 20:53:56 2017 +0100

    change SNMP to be a cached transport singleton

commit c31030ef70
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Jul 23 13:46:27 2017 +0100

    fixes because Dancer docs are a mess!

commit f65ef90b86
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Jul 22 08:11:36 2017 +0100

    rename snmp_auth to device_auth and include a little doc on transports

commit d61556e1cf
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Jul 22 07:54:26 2017 +0100

    plugin config added

commit de8de56308
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed Jul 12 21:38:31 2017 +0100

    initial core plugin implementation
2017-11-19 13:34:35 +00:00

502 lines
22 KiB
Plaintext

=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