add arpnip and macsuck hooks and exec hook implementation

This commit is contained in:
Oliver Gorwits
2020-12-30 20:38:45 +00:00
parent 28349eb489
commit 351927d384
9 changed files with 77 additions and 3 deletions

View File

@@ -29,6 +29,7 @@ Module::Build->new(
'Authen::Radius' => '0', 'Authen::Radius' => '0',
'Authen::TacacsPlus' => '0', 'Authen::TacacsPlus' => '0',
'CGI::Expand' => '2.05', 'CGI::Expand' => '2.05',
'Command::Runner' => 0,
'Data::Printer' => '0', 'Data::Printer' => '0',
'Data::Visitor::Tiny' => '0', 'Data::Visitor::Tiny' => '0',
'DBD::Pg' => '0', 'DBD::Pg' => '0',

View File

@@ -270,7 +270,8 @@ sub jq_complete {
log => $job->log, log => $job->log,
started => $job->started, started => $job->started,
finished => $job->finished, finished => $job->finished,
(($job->action eq 'hook') ? (subaction => undef) : ()), (($job->action eq 'hook') ? (subaction => $job->subaction) : ()),
($job->only_namespace ? (action => ($job->action .'::'. $job->only_namespace)) : ()),
}); });
}); });
$happy = true; $happy = true;

View File

@@ -19,6 +19,10 @@ register_worker({ phase => 'check' }, sub {
return Status->info("arpnip skipped: $device is not arpnipable") return Status->info("arpnip skipped: $device is not arpnipable")
unless is_arpnipable_now($device); unless is_arpnipable_now($device);
# support for Hooks
vars->{'hook_data'} = { $device->get_columns };
delete vars->{'hook_data'}->{'snmp_comm'}; # for privacy
return Status->done('arpnip is able to run'); return Status->done('arpnip is able to run');
}); });

View File

@@ -20,7 +20,7 @@ register_worker({ phase => 'late' }, sub {
if ($conf->{'event'} eq 'arpnip') { if ($conf->{'event'} eq 'arpnip') {
$count += queue_hook('arpnip', $conf); $count += queue_hook('arpnip', $conf);
sprintf ' [%s] hooks - %s queued', 'arpnip', $job->device; debug sprintf ' [%s] hooks - %s queued', 'arpnip', $job->device;
} }
} }

View File

@@ -0,0 +1,60 @@
package App::Netdisco::Worker::Plugin::Hook::Exec;
use Dancer ':syntax';
use App::Netdisco::Worker::Plugin;
use aliased 'App::Netdisco::Worker::Status';
use MIME::Base64 'decode_base64';
use Command::Runner;
use Template;
register_worker({ phase => 'main' }, sub {
my ($job, $workerconf) = @_;
my $extra = from_json( decode_base64( $job->extra || '' ) );
my $event_data = $extra->{'event_data'};
my $action_conf = $extra->{'action_conf'};
return Status->error('missing cmd parameter to exec Hook')
if !defined $action_conf->{'cmd'};
my $tt = Template->new({ ENCODING => 'utf8' });
my ($orig_cmd, $cmd) = ($action_conf->{'cmd'}, undef);
$action_conf->{'cmd_is_template'} ||= 1
if !exists $action_conf->{'cmd_is_template'};
if ($action_conf->{'cmd_is_template'}) {
if (ref $orig_cmd) {
foreach my $part (@$orig_cmd) {
my $tmp_part = undef;
$tt->process(\$part, $event_data, \$tmp_part);
push @$cmd, $tmp_part;
}
}
else {
$tt->process(\$orig_cmd, $event_data, \$cmd);
}
}
$cmd ||= $orig_cmd;
my $result = Command::Runner->new(
command => $cmd,
timeout => ($action_conf->{'timeout'} || 60),
env => {
%ENV,
ND_EVENT => $action_conf->{'event'},
ND_DEVICE_IP => $event_data->{'ip'},
},
)->run();
$result->{cmd} = $cmd;
$job->subaction(to_json($result));
if ($action_conf->{'ignore_failure'} or not $result->{'result'}) {
return Status->done(sprintf 'Exec Hook: exit status %s', $result->{'result'});
}
else {
return Status->error(sprintf 'Exec Hook: exit status %s', $result->{'result'});
}
});
true;

View File

@@ -11,6 +11,7 @@ use Template;
register_worker({ phase => 'main' }, sub { register_worker({ phase => 'main' }, sub {
my ($job, $workerconf) = @_; my ($job, $workerconf) = @_;
my $extra = from_json( decode_base64( $job->extra || '' ) ); my $extra = from_json( decode_base64( $job->extra || '' ) );
$job->subaction('');
my $event_data = $extra->{'event_data'}; my $event_data = $extra->{'event_data'};
my $action_conf = $extra->{'action_conf'}; my $action_conf = $extra->{'action_conf'};

View File

@@ -19,6 +19,10 @@ register_worker({ phase => 'check' }, sub {
return Status->info("macsuck skipped: $device is not macsuckable") return Status->info("macsuck skipped: $device is not macsuckable")
unless is_macsuckable_now($device); unless is_macsuckable_now($device);
# support for Hooks
vars->{'hook_data'} = { $device->get_columns };
delete vars->{'hook_data'}->{'snmp_comm'}; # for privacy
return Status->done('Macsuck is able to run.'); return Status->done('Macsuck is able to run.');
}); });

View File

@@ -20,7 +20,7 @@ register_worker({ phase => 'late' }, sub {
if ($conf->{'event'} eq 'macsuck') { if ($conf->{'event'} eq 'macsuck') {
$count += queue_hook('macsuck', $conf); $count += queue_hook('macsuck', $conf);
sprintf ' [%s] hooks - %s queued', 'macsuck', $job->device; debug sprintf ' [%s] hooks - %s queued', 'macsuck', $job->device;
} }
} }

View File

@@ -389,6 +389,7 @@ worker_plugins:
- 'Arpnip' - 'Arpnip'
- 'Arpnip::Nodes' - 'Arpnip::Nodes'
- 'Arpnip::Subnets' - 'Arpnip::Subnets'
- 'Arpnip::Hooks'
- 'Arpwalk' - 'Arpwalk'
- 'Contact' - 'Contact'
- 'Delete' - 'Delete'
@@ -411,11 +412,13 @@ worker_plugins:
- 'ExpireNodes' - 'ExpireNodes'
- 'Graph' - 'Graph'
- 'Hook' - 'Hook'
- 'Hook::Exec'
- 'Hook::HTTP' - 'Hook::HTTP'
- 'Location' - 'Location'
- 'Macsuck' - 'Macsuck'
- 'Macsuck::Nodes' - 'Macsuck::Nodes'
- 'Macsuck::WirelessNodes' - 'Macsuck::WirelessNodes'
- 'Macsuck::Hooks'
- 'Macwalk' - 'Macwalk'
- 'MakeRancidConf' - 'MakeRancidConf'
- 'NodeMonitor' - 'NodeMonitor'