From 12b3a4b35877243b97e2d79aa30e1dea86b4138a Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Wed, 12 Dec 2012 22:32:26 +0000 Subject: [PATCH] refactor to use role for the worker --- Netdisco/bin/netdisco-daemon | 115 ++---------------- .../lib/Netdisco/Daemon/Worker/Interactive.pm | 105 ++++++++++++++++ .../Interactive/DeviceActions.pm} | 6 +- .../Interactive/PortActions.pm} | 6 +- .../{Actions => Worker/Interactive}/Util.pm | 2 +- README.pod | 2 +- 6 files changed, 122 insertions(+), 114 deletions(-) create mode 100755 Netdisco/lib/Netdisco/Daemon/Worker/Interactive.pm rename Netdisco/lib/Netdisco/Daemon/{Actions/Device.pm => Worker/Interactive/DeviceActions.pm} (89%) rename Netdisco/lib/Netdisco/Daemon/{Actions/Port.pm => Worker/Interactive/PortActions.pm} (96%) rename Netdisco/lib/Netdisco/Daemon/{Actions => Worker/Interactive}/Util.pm (82%) diff --git a/Netdisco/bin/netdisco-daemon b/Netdisco/bin/netdisco-daemon index 47e2b927..a6487237 100755 --- a/Netdisco/bin/netdisco-daemon +++ b/Netdisco/bin/netdisco-daemon @@ -5,14 +5,7 @@ use Dancer::Plugin::DBIC 'schema'; use Daemon::Generic::While1; use Parallel::Prefork; -use Netdisco::Util::DeviceProperties 'is_discoverable'; -use Try::Tiny; -use Moo; -use MooX::Types::MooseLike::Base qw(InstanceOf); - -# add dispatch methods for each port control action -with "Netdisco::Daemon::Actions::$_" - for (qw/Device Port/); +use Role::Tiny; my $pp = Parallel::Prefork->new( max_workers => 2, @@ -58,107 +51,17 @@ sub gd_run_body { $pp->{_no_adjust_until} = 0; # BUG in Prefork.pm } - # check for new jobs - # take one if available - - # don't block waiting for a needed worker - if ($pp->num_workers >= $pp->max_workers) { - $self->gd_sleep( setting('daemon_sleep_time') || 5 ); - return; + if ($pp->num_workers < $pp->max_workers) { + $pp->start and return; + with 'Netdisco::Daemon::Worker::Interactive'; + $self->worker_body; + $pp->finish; } - $pp->start and return; - try { $self->worker_body } catch { print "$_\n" }; - $pp->finish; -} + # check for new jobs, take one if available + $self->manager_body; -sub worker_body { - my $self = shift; - - # get all pending jobs - my $rs = schema('netdisco')->resultset('Admin')->search({ - action => [qw/location contact portcontrol portname vlan power/], - status => 'queued', - }); - - while (1) { - while (my $job = $rs->next) { - my $target = 'set_'. $job->action; - next unless $self->can($target); - - # filter for discover_* - next unless is_discoverable($job->device); - - # mark job as running - next unless $self->lock_job($job); - - # do job - my ($status, $log); - try { - ($status, $log) = $self->$target($job); - } - catch { warn "error running job: $_\n" }; - - # revert to queued status if we failed to action the job - if (not $status) { - $self->revert_job($job->job); - } - else { - # update job state to done/error with log - $self->close_job($job->job, $status, $log); - } - } - $rs->reset; - $self->gd_sleep( setting('daemon_sleep_time') || 5 ); - } -} - -sub lock_job { - my ($self, $job) = @_; - - # lock db table, check job state is still queued, update to running - try { - my $status_updated = schema('netdisco')->txn_do(sub { - my $row = schema('netdisco')->resultset('Admin')->find( - {job => $job->job}, - {for => 'update'} - ); - - return 0 if $row->status ne 'queued'; - $row->update({status => 'running', started => \'now()'}); - return 1; - }); - - return 0 if not $status_updated; - } - catch { - warn "error locking job: $_\n"; - return 0; - }; - - return 1; -} - -sub revert_job { - my ($self, $id) = @_; - - try { - schema('netdisco')->resultset('Admin') - ->find($id) - ->update({status => 'queued', started => undef}); - } - catch { warn "error reverting job: $_\n" }; -} - -sub close_job { - my ($self, $id, $status, $log) = @_; - - try { - schema('netdisco')->resultset('Admin') - ->find($id) - ->update({status => $status, log => $log, finished => \'now()'}); - } - catch { warn "error closing job: $_\n" }; + $self->gd_sleep( setting('daemon_sleep_time') || 5 ); } # do not remove - must be redefined for Daemon::Generic diff --git a/Netdisco/lib/Netdisco/Daemon/Worker/Interactive.pm b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive.pm new file mode 100755 index 00000000..dc25de74 --- /dev/null +++ b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive.pm @@ -0,0 +1,105 @@ +package Netdisco::Daemon::Worker::Interactive; + +use Dancer qw/:moose :syntax :script/; +use Dancer::Plugin::DBIC 'schema'; + +use Netdisco::Util::DeviceProperties 'is_discoverable'; +use Try::Tiny; + +use Role::Tiny; +use namespace::clean; + +# add dispatch methods for interactive actions +with 'Netdisco::Daemon::Worker::Interactive::DeviceActions', + 'Netdisco::Daemon::Worker::Interactive::PortActions'; + +sub worker_body { + my $self = shift; + + # get all pending jobs + my $rs = schema('netdisco')->resultset('Admin')->search({ + action => [qw/location contact portcontrol portname vlan power/], + status => 'queued', + }); + + while (1) { + while (my $job = $rs->next) { + my $target = 'set_'. $job->action; + next unless $self->can($target); + + # filter for discover_* + next unless is_discoverable($job->device); + + # mark job as running + next unless $self->lock_job($job); + + # do job + my ($status, $log); + try { + ($status, $log) = $self->$target($job); + } + catch { warn "error running job: $_\n" }; + + # revert to queued status if we failed to action the job + if (not $status) { + $self->revert_job($job->job); + } + else { + # update job state to done/error with log + $self->close_job($job->job, $status, $log); + } + } + $rs->reset; + $self->gd_sleep( setting('daemon_sleep_time') || 5 ); + } +} + +sub lock_job { + my ($self, $job) = @_; + + # lock db table, check job state is still queued, update to running + try { + my $status_updated = schema('netdisco')->txn_do(sub { + my $row = schema('netdisco')->resultset('Admin')->find( + {job => $job->job}, + {for => 'update'} + ); + + return 0 if $row->status ne 'queued'; + $row->update({status => 'running', started => \'now()'}); + return 1; + }); + + return 0 if not $status_updated; + } + catch { + warn "error locking job: $_\n"; + return 0; + }; + + return 1; +} + +sub revert_job { + my ($self, $id) = @_; + + try { + schema('netdisco')->resultset('Admin') + ->find($id) + ->update({status => 'queued', started => undef}); + } + catch { warn "error reverting job: $_\n" }; +} + +sub close_job { + my ($self, $id, $status, $log) = @_; + + try { + schema('netdisco')->resultset('Admin') + ->find($id) + ->update({status => $status, log => $log, finished => \'now()'}); + } + catch { warn "error closing job: $_\n" }; +} + +1; diff --git a/Netdisco/lib/Netdisco/Daemon/Actions/Device.pm b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive/DeviceActions.pm similarity index 89% rename from Netdisco/lib/Netdisco/Daemon/Actions/Device.pm rename to Netdisco/lib/Netdisco/Daemon/Worker/Interactive/DeviceActions.pm index 1e887bc2..01e36c1a 100644 --- a/Netdisco/lib/Netdisco/Daemon/Actions/Device.pm +++ b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive/DeviceActions.pm @@ -1,10 +1,10 @@ -package Netdisco::Daemon::Actions::Device; +package Netdisco::Daemon::Worker::Interactive::DeviceActions; use Netdisco::Util::Connect qw/snmp_connect get_device/; -use Netdisco::Daemon::Actions::Util ':all'; +use Netdisco::Daemon::Worker::Interactive::Util ':all'; +use Role::Tiny; use namespace::clean; -use Moo::Role; sub set_location { my ($self, $job) = @_; diff --git a/Netdisco/lib/Netdisco/Daemon/Actions/Port.pm b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive/PortActions.pm similarity index 96% rename from Netdisco/lib/Netdisco/Daemon/Actions/Port.pm rename to Netdisco/lib/Netdisco/Daemon/Worker/Interactive/PortActions.pm index 200190e5..25a0ad54 100644 --- a/Netdisco/lib/Netdisco/Daemon/Actions/Port.pm +++ b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive/PortActions.pm @@ -1,11 +1,11 @@ -package Netdisco::Daemon::Actions::Port; +package Netdisco::Daemon::Worker::Interactive::PortActions; use Netdisco::Util::Connect ':all'; use Netdisco::Util::Permissions ':all'; -use Netdisco::Daemon::Actions::Util ':all'; +use Netdisco::Daemon::Worker::Interactive::Util ':all'; +use Role::Tiny; use namespace::clean; -use Moo::Role; sub set_portname { my ($self, $job) = @_; diff --git a/Netdisco/lib/Netdisco/Daemon/Actions/Util.pm b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive/Util.pm similarity index 82% rename from Netdisco/lib/Netdisco/Daemon/Actions/Util.pm rename to Netdisco/lib/Netdisco/Daemon/Worker/Interactive/Util.pm index d6322cb9..273e4a12 100644 --- a/Netdisco/lib/Netdisco/Daemon/Actions/Util.pm +++ b/Netdisco/lib/Netdisco/Daemon/Worker/Interactive/Util.pm @@ -1,4 +1,4 @@ -package Netdisco::Daemon::Actions::Util; +package Netdisco::Daemon::Worker::Interactive::Util; # support utilities for Daemon Actions diff --git a/README.pod b/README.pod index d1a0546d..a0b4c205 100644 --- a/README.pod +++ b/README.pod @@ -44,7 +44,7 @@ install Perl dependencies into a custom library path: NetAddr::IP \ Net::MAC \ namespace::clean \ - Moo \ + Role::Tiny \ List::MoreUtils \ Socket6 \ HTML::Entities \