From dc62382112b255e63fce3868812ec386226401e5 Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Thu, 30 May 2013 05:50:34 +0100 Subject: [PATCH] support for arpwalk and macwalk and all jobs via web --- Netdisco/lib/App/Netdisco/Daemon/Queue.pm | 2 +- .../lib/App/Netdisco/Daemon/Worker/Manager.pm | 2 +- .../Netdisco/Daemon/Worker/Poller/Arpnip.pm | 30 +++++++++++ .../Netdisco/Daemon/Worker/Poller/Macsuck.pm | 30 +++++++++++ .../App/Netdisco/Daemon/Worker/Scheduler.pm | 4 +- Netdisco/lib/App/Netdisco/Web/AdminTask.pm | 53 +++++++++++++------ 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/Netdisco/lib/App/Netdisco/Daemon/Queue.pm b/Netdisco/lib/App/Netdisco/Daemon/Queue.pm index c35fc7bf..bbec8db0 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Queue.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Queue.pm @@ -33,7 +33,7 @@ sub capacity_for { debug "checking local capacity for action $action"; my $action_map = { - Poller => [qw/discoverall discover arpnip macsuck/], + Poller => [qw/discoverall discover arpwalk arpnip macwalk macsuck/], Interactive => [qw/location contact portcontrol portname vlan power/], }; diff --git a/Netdisco/lib/App/Netdisco/Daemon/Worker/Manager.pm b/Netdisco/lib/App/Netdisco/Daemon/Worker/Manager.pm index 624a6069..075d09c3 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Worker/Manager.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Worker/Manager.pm @@ -14,7 +14,7 @@ my $fqdn = hostfqdn || 'localhost'; my $role_map = { (map {$_ => 'Poller'} - qw/discoverall discover arpnip macsuck/), + qw/discoverall discover arpwalk arpnip macwalk macsuck/), (map {$_ => 'Interactive'} qw/location contact portcontrol portname vlan power/) }; diff --git a/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Arpnip.pm b/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Arpnip.pm index 7ab7ad0a..c9f98b7b 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Arpnip.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Arpnip.pm @@ -13,6 +13,36 @@ use NetAddr::IP::Lite ':lower'; use Role::Tiny; use namespace::clean; +# queue an arpnip job for all devices known to Netdisco +sub arpwalk { + my ($self, $job) = @_; + + my $devices = schema('netdisco')->resultset('Device')->get_column('ip'); + my $jobqueue = schema('netdisco')->resultset('Admin'); + + schema('netdisco')->txn_do(sub { + # clean up user submitted jobs older than 1min, + # assuming skew between schedulers' clocks is not greater than 1min + $jobqueue->search({ + action => 'arpnip', + status => 'queued', + entered => { '<' => \"(now() - interval '1 minute')" }, + })->delete; + + # is scuppered by any user job submitted in last 1min (bad), or + # any similar job from another scheduler (good) + $jobqueue->populate([ + map {{ + device => $_, + action => 'arpnip', + status => 'queued', + }} ($devices->all) + ]); + }); + + return job_done("Queued arpnip job for all devices"); +} + sub arpnip { my ($self, $job) = @_; diff --git a/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Macsuck.pm b/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Macsuck.pm index 3d5791f8..39c3a4ee 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Macsuck.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Macsuck.pm @@ -13,6 +13,36 @@ use NetAddr::IP::Lite ':lower'; use Role::Tiny; use namespace::clean; +# queue a macsuck job for all devices known to Netdisco +sub macwalk { + my ($self, $job) = @_; + + my $devices = schema('netdisco')->resultset('Device')->get_column('ip'); + my $jobqueue = schema('netdisco')->resultset('Admin'); + + schema('netdisco')->txn_do(sub { + # clean up user submitted jobs older than 1min, + # assuming skew between schedulers' clocks is not greater than 1min + $jobqueue->search({ + action => 'macsuck', + status => 'queued', + entered => { '<' => \"(now() - interval '1 minute')" }, + })->delete; + + # is scuppered by any user job submitted in last 1min (bad), or + # any similar job from another scheduler (good) + $jobqueue->populate([ + map {{ + device => $_, + action => 'macsuck', + status => 'queued', + }} ($devices->all) + ]); + }); + + return job_done("Queued macsuck job for all devices"); +} + sub macsuck { my ($self, $job) = @_; diff --git a/Netdisco/lib/App/Netdisco/Daemon/Worker/Scheduler.pm b/Netdisco/lib/App/Netdisco/Daemon/Worker/Scheduler.pm index 82b72289..b827ed83 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Worker/Scheduler.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Worker/Scheduler.pm @@ -12,10 +12,10 @@ use namespace::clean; my $jobactions = { map {$_ => undef} qw/ discoverall + arpwalk + macwalk / # saveconfigs -# macwalk -# arpwalk # nbtwalk # backup }; diff --git a/Netdisco/lib/App/Netdisco/Web/AdminTask.pm b/Netdisco/lib/App/Netdisco/Web/AdminTask.pm index fbc274f8..736ef0b1 100644 --- a/Netdisco/lib/App/Netdisco/Web/AdminTask.pm +++ b/Netdisco/lib/App/Netdisco/Web/AdminTask.pm @@ -4,32 +4,53 @@ use Dancer ':syntax'; use Dancer::Plugin::Ajax; use Dancer::Plugin::DBIC; -sub add_discover_job { - my $ip = NetAddr::IP::Lite->new(shift); - return unless $ip - and $ip->addr ne '0.0.0.0'; +sub add_job { + my ($jobtype, $device) = @_; + + if ($device) { + $device = NetAddr::IP::Lite->new($device); + return unless $device + and $device->addr ne '0.0.0.0'; + } schema('netdisco')->resultset('Admin')->create({ - device => $ip->addr, - action => 'discover', + ($device ? (device => $device->addr) : ()), + action => $jobtype, status => 'queued', username => session('user'), userip => request->remote_address, }); } -ajax '/ajax/control/admin/discover' => sub { - return unless var('user') and var('user')->admin; - add_discover_job(param('device')); -}; +# we have a separate list for jobs needing a device to avoid queueing +# such a job when there's no device param (it could still be duff, tho). +my %jobs = map { $_ => 1} qw/ + discover + macsuck + arpnip +/; +my %jobs_all = map {$_ => 1} qw/ + discoverall + macwalk + arpwalk +/; -post '/admin/discover' => sub { - return unless var('user') and var('user')->admin; - add_discover_job(param('device')); +foreach my $jobtype (keys %jobs_all, keys %jobs) { + ajax "/ajax/control/admin/$jobtype" => sub { + return unless var('user') and var('user')->admin; + return if exists $jobs{$jobtype} and not param('device'); + add_job($jobtype, param('device')); + }; - status(302); - header(Location => uri_for('/admin/jobqueue')->path_query()); -}; + post "/admin/$jobtype" => sub { + return unless var('user') and var('user')->admin; + return if exists $jobs{$jobtype} and not param('device'); + add_job($jobtype, param('device')); + + status(302); + header(Location => uri_for('/admin/jobqueue')->path_query()); + }; +} get '/admin/*' => sub { my ($tag) = splat;