add manager and full worker support

This commit is contained in:
Oliver Gorwits
2012-12-15 00:52:42 +00:00
parent f9f7a223b8
commit 6d802f9b85
5 changed files with 230 additions and 49 deletions

View File

@@ -0,0 +1,23 @@
use utf8;
package Netdisco::Daemon::DB;
use strict;
use warnings;
use base 'DBIx::Class::Schema';
__PACKAGE__->load_namespaces;
our $VERSION = 1; # schema version used for upgrades, keep as integer
use Path::Class;
use File::Basename;
my (undef, $libpath, undef) = fileparse( $INC{ 'Netdisco/Daemon/DB.pm' } );
our $schema_versions_dir = Path::Class::Dir->new($libpath)
->subdir("DB", "schema_versions")->stringify;
__PACKAGE__->load_components(qw/Schema::Versioned/);
__PACKAGE__->upgrade_directory($schema_versions_dir);
1;

View File

@@ -0,0 +1,37 @@
use utf8;
package Netdisco::Daemon::DB::Result::Admin;
use strict;
use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->table("admin");
__PACKAGE__->add_columns(
"job",
{
data_type => "integer",
is_nullable => 0,
},
"started",
{ data_type => "timestamp", is_nullable => 1 },
"finished",
{ data_type => "timestamp", is_nullable => 1 },
"device",
{ data_type => "inet", is_nullable => 1 },
"port",
{ data_type => "text", is_nullable => 1 },
"action",
{ data_type => "text", is_nullable => 1 },
"subaction",
{ data_type => "text", is_nullable => 1 },
"status",
{ data_type => "text", is_nullable => 1 },
"log",
{ data_type => "text", is_nullable => 1 },
"debug",
{ data_type => "boolean", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("job");
1;

38
Netdisco/lib/Netdisco/Daemon/Worker/Interactive.pm Executable file → Normal file
View File

@@ -2,8 +2,6 @@ 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;
@@ -17,7 +15,7 @@ sub worker_body {
my $self = shift;
# get all pending jobs
my $rs = schema('netdisco')->resultset('Admin')->search({
my $rs = schema('daemon')->resultset('Admin')->search({
action => [qw/location contact portcontrol portname vlan power/],
status => 'queued',
});
@@ -27,9 +25,6 @@ sub worker_body {
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);
@@ -49,6 +44,8 @@ sub worker_body {
$self->close_job($job->job, $status, $log);
}
}
# reset iterator so ->next() triggers another DB query
$rs->reset;
$self->gd_sleep( setting('daemon_sleep_time') || 5 );
}
@@ -56,35 +53,35 @@ sub worker_body {
sub lock_job {
my ($self, $job) = @_;
my $happy = 1;
# 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(
my $status_updated = schema('daemon')->txn_do(sub {
my $row = schema('daemon')->resultset('Admin')->find(
{job => $job->job},
{for => 'update'}
);
return 0 if $row->status ne 'queued';
$row->update({status => 'running', started => \'now()'});
return 1;
$happy = 0 if $row->status ne 'queued';
$row->update({status => "running-$$", started => \"datetime('now')" });
});
return 0 if not $status_updated;
$happy = 0 if not $status_updated;
}
catch {
warn "error locking job: $_\n";
return 0;
$happy = 0;
};
return 1;
return $happy;
}
sub revert_job {
my ($self, $id) = @_;
try {
schema('netdisco')->resultset('Admin')
schema('daemon')->resultset('Admin')
->find($id)
->update({status => 'queued', started => undef});
}
@@ -95,9 +92,18 @@ sub close_job {
my ($self, $id, $status, $log) = @_;
try {
my $local = schema('daemon')->resultset('Admin')->find($id);
schema('netdisco')->resultset('Admin')
->find($id)
->update({status => $status, log => $log, finished => \'now()'});
->update({
status => $status,
log => $log,
started => $local->started,
finished => \'now()',
});
$local->delete;
}
catch { warn "error closing job: $_\n" };
}

View File

@@ -0,0 +1,92 @@
package Netdisco::Daemon::Worker::Manager;
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;
sub worker_body {
my $self = shift;
# get all pending jobs
my $rs = schema('netdisco')->resultset('Admin')
->search({status => 'queued'});
while (1) {
while (my $job = $rs->next) {
# filter for discover_*
next unless is_discoverable($job->device);
# mark job as running
next unless $self->lock_job($job);
# copy job to local queue
$self->copy_job($job)
or $self->revert_job($job->job);
}
# reset iterator so ->next() triggers another DB query
$rs->reset;
$self->gd_sleep( setting('daemon_sleep_time') || 5 );
}
}
sub lock_job {
my ($self, $job) = @_;
my $happy = 1;
# 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'}
);
$happy = 0 if $row->status ne 'queued';
$row->update({
status => "running-$self->{nd_host}",
started => \'now()'
});
});
$happy = 0 if not $status_updated;
}
catch {
warn "error locking job: $_\n";
$happy = 0;
};
return $happy;
}
sub copy_job {
my ($self, $job) = @_;
try {
my %data = $job->get_columns;
delete $data{$_} for qw/entered username userip/;
schema('daemon')->resultset('Admin')->update_or_create({
%data, status => 'queued', started => undef,
});
}
catch { warn "error copying job: $_\n" };
}
sub revert_job {
my ($self, $id) = @_;
try {
schema('netdisco')->resultset('Admin')
->find($id)
->update({status => 'queued', started => undef});
}
catch { warn "error reverting job: $_\n" };
}
1;