#1066 implement snmp_try_slow_connect and fast device discover from queue

This commit is contained in:
Oliver Gorwits
2023-07-14 17:37:52 +01:00
parent 2f7e3f80a3
commit eac55a581d
5 changed files with 62 additions and 18 deletions

View File

@@ -246,7 +246,7 @@ sub jq_defer {
# lock db row and update to show job is available # lock db row and update to show job is available
schema(vars->{'tenant'})->resultset('Admin') schema(vars->{'tenant'})->resultset('Admin')
->search({ job => $job->id }, { for => 'update' }) ->search({ job => $job->id }, { for => 'update' })
->update({ status => 'queued', started => undef }); ->update({ status => 'queued', started => undef, log => $job->log });
}); });
$happy = true; $happy = true;
} }

View File

@@ -209,9 +209,37 @@ sub _snmp_connect_generic {
unshift @classes, $device->snmp_class; unshift @classes, $device->snmp_class;
} }
my $info = undef; # first try the communities in a fast pass using best version
my $orig_retries = $snmp_args{Retries};
my $orig_timeout = $snmp_args{Timeout}; VERSION: foreach my $ver (3, 2) {
my %local_args = (%snmp_args,
Version => $ver, Retries => 0, Timeout => 200000);
COMMUNITY: foreach my $comm (@communities) {
next unless $comm;
next if $ver eq 3 and exists $comm->{community};
next if $ver ne 3 and !exists $comm->{community};
my $info = _try_connect($device, $classes[0], $comm, $mode, \%local_args,
($useclass ? 0 : 1) );
# if successful, restore the default/user timeouts and return
if ($info) {
my $class = $info->device_type;
return $class->new(
%snmp_args, Version => $ver,
_mk_info_commargs($comm),
);
}
}
}
# then revert to conservative settings and repeat with all versions
# unless user wants just the fast connections for bulk discovery
# or we are on the first discovery attempt of a new device
return unless setting('snmp_try_slow_connect');
CLASS: foreach my $class (@classes) { CLASS: foreach my $class (@classes) {
next unless $class; next unless $class;
@@ -226,19 +254,14 @@ sub _snmp_connect_generic {
next if $ver eq 3 and exists $comm->{community}; next if $ver eq 3 and exists $comm->{community};
next if $ver ne 3 and !exists $comm->{community}; next if $ver ne 3 and !exists $comm->{community};
# $local_args{Retries} = $comm->{_tried} ? $orig_retries : 0; my $info = _try_connect($device, $class, $comm, $mode, \%local_args,
# $local_args{Timeout} = $comm->{_tried} ? $orig_timeout : 500000;
$info = _try_connect($device, $class, $comm, $mode, \%local_args,
($useclass ? 0 : 1) ); ($useclass ? 0 : 1) );
last CLASS if $info; return $info if $info;
# ++$comm->{_tried};
} }
} }
} }
return $info; return undef;
} }
sub _try_connect { sub _try_connect {

View File

@@ -31,27 +31,28 @@ sub load_workers {
if $plugin !~ m/^\+/; if $plugin !~ m/^\+/;
$plugin =~ s/^\+//; $plugin =~ s/^\+//;
next unless $plugin =~ m/::Plugin::${action}(?:::|$)/i; next unless $plugin =~ m/::Plugin::(?:${action}|Internal)(?:::|$)/i;
$ENV{ND2_LOG_PLUGINS} && debug "loading worker plugin $plugin"; $ENV{ND2_LOG_PLUGINS} && debug "loading worker plugin $plugin";
Module::Load::load $plugin; Module::Load::load $plugin;
} }
# now vars->{workers} is populated, we set the dispatch order # now vars->{workers} is populated, we set the dispatch order
my $workers = vars->{'workers'}->{$action} || {}; my %workers = ( %{ vars->{'workers'}->{$action} || {} },
%{ vars->{'workers'}->{'internal'} || {} } );
my $driverless_main = 0; my $driverless_main = 0;
#use DDP; p vars->{'workers'}; # use DDP; p vars{'workers'}; p %workers;
foreach my $phase (qw/check early main user store late/) { foreach my $phase (qw/check early main user store late/) {
my $pname = "workers_${phase}"; my $pname = "workers_${phase}";
my @wset = (); my @wset = ();
foreach my $namespace (sort keys %{ $workers->{$phase} }) { foreach my $namespace (sort keys %{ $workers{$phase} }) {
foreach my $priority (sort {$b <=> $a} foreach my $priority (sort {$b <=> $a}
keys %{ $workers->{$phase}->{$namespace} }) { keys %{ $workers{$phase}->{$namespace} }) {
++$driverless_main if $phase eq 'main' ++$driverless_main if $phase eq 'main'
and ($priority == 0 or $priority == setting('driver_priority')->{'direct'}); and ($priority == 0 or $priority == setting('driver_priority')->{'direct'});
push @wset, @{ $workers->{$phase}->{$namespace}->{$priority} }; push @wset, @{ $workers{$phase}->{$namespace}->{$priority} };
} }
} }

View File

@@ -0,0 +1,18 @@
package App::Netdisco::Worker::Plugin::Internal::SNMPFastDiscover;
use Dancer ':syntax';
use App::Netdisco::Worker::Plugin;
use aliased 'App::Netdisco::Worker::Status';
register_worker({ phase => 'check', driver => 'direct' }, sub {
my ($job, $workerconf) = @_;
# if the job is a queued job, and discover, and the first one...
if ($job->job and $job->action eq 'discover' and not $job->log) {
config->{'snmp_try_slow_connect'} = false;
debug sprintf '[%s] skipping long SNMP timeouts for initial discover',
$job->device;
}
});
true;

View File

@@ -345,6 +345,7 @@ snmpver: 3
snmptimeout: 3000000 snmptimeout: 3000000
snmpretries: 2 snmpretries: 2
net_snmp_options: {} net_snmp_options: {}
snmp_try_slow_connect: true
snmp_remoteport: {} snmp_remoteport: {}
snmp_field_protection: snmp_field_protection:
device: device:
@@ -527,6 +528,7 @@ worker_plugins:
- 'Hook' - 'Hook'
- 'Hook::Exec' - 'Hook::Exec'
- 'Hook::HTTP' - 'Hook::HTTP'
- 'Internal::SNMPFastDiscover'
- 'LoadMIBs' - 'LoadMIBs'
- 'Location' - 'Location'
- 'Macsuck' - 'Macsuck'