App-Netdisco
view release on metacpan or search on metacpan
lib/App/Netdisco/Worker/Plugin/Arpnip/Nodes.pm view on Meta::CPAN
package App::Netdisco::Worker::Plugin::Arpnip::Nodes;
use Dancer ':syntax';
use Dancer::Plugin::DBIC 'schema';
use App::Netdisco::Worker::Plugin;
use aliased 'App::Netdisco::Worker::Status';
use App::Netdisco::Transport::SSH ();
use App::Netdisco::Transport::SNMP ();
use App::Netdisco::Util::Node qw/check_mac memoize_arp store_arp/;
use App::Netdisco::Util::FastResolver 'hostnames_resolve_async';
use NetAddr::IP::Lite ':lower';
use Regexp::Common 'net';
use NetAddr::MAC ();
use Time::HiRes 'gettimeofday';
register_worker({ phase => 'early',
title => 'prepare common data' }, sub {
my ($job, $workerconf) = @_;
my $device = $job->device;
# would be possible just to use LOCALTIMESTAMP on updated records, but by using this
# same value for them all, we can if we want add a job at the end to
# select and do something with the updated set (see set archive, below)
vars->{'timestamp'} = ($job->is_offline and $job->entered)
? (schema('netdisco')->storage->dbh->quote($job->entered) .'::timestamp')
: 'to_timestamp('. (join '.', gettimeofday) .')::timestamp';
#Â initialise the cache
vars->{'arps'} = {};
});
register_worker({ phase => 'store', title => 'store ARP cache' }, sub {
my ($job, $workerconf) = @_;
my $device = $job->device;
#Â convert cache to a list, now that we've gathererd all of them
#Â it just makes the rest of the "store" code easier
vars->{'arps'} = [ values %{ vars->{'arps'} } ];
vars->{'arps'} = [ grep { check_mac(($_->{node} || $_->{mac}), $device) }
@{ vars->{'arps'} } ];
debug sprintf ' resolving %d ARP entries with max %d outstanding requests',
scalar @{ vars->{'arps'} }, $ENV{'PERL_ANYEVENT_MAX_OUTSTANDING_DNS'};
vars->{'arps'} = hostnames_resolve_async( vars->{'arps'} );
my ($v4, $v6) = (0, 0);
foreach my $a_entry (@{ vars->{'arps'} }) {
my $a_ip = NetAddr::IP::Lite->new($a_entry->{ip});
if ($a_ip) {
++$v4 if $a_ip->bits == 32;;
++$v6 if $a_ip->bits == 128;;
}
}
my $now = vars->{'timestamp'};
store_arp(\%$_, $now, $device->ip) for @{ vars->{'arps'} };
debug sprintf ' [%s] arpnip - processed %s ARP Cache entries',
$device->ip, $v4;
debug sprintf ' [%s] arpnip - processed %s IPv6 Neighbor Cache entries',
$device->ip, $v6;
my $status = $job->best_status;
if (Status->$status->level == Status->done->level) {
$device->update({last_arpnip => \$now});
}
return Status->$status("Ended arpnip for $device");
});
register_worker({ phase => 'main', driver => 'snmp' }, sub {
my ($job, $workerconf) = @_;
my $device = $job->device;
my $snmp = App::Netdisco::Transport::SNMP->reader_for($device)
or return Status->defer("arpnip failed: could not SNMP connect to $device");
# cache v4 arp table
map { vars->{'arps'}->{ memoize_arp($_) } = $_ }
get_arps_snmp($device, $snmp->at_paddr, $snmp->at_netaddr);
( run in 0.776 second using v1.01-cache-2.11-cpan-39bf76dae61 )