App-Netdisco
view release on metacpan or search on metacpan
lib/App/Netdisco/Worker/Plugin/Macsuck/Nodes.pm view on Meta::CPAN
package App::Netdisco::Worker::Plugin::Macsuck::Nodes;
use Dancer ':syntax';
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::Permission 'acl_matches';
use App::Netdisco::Util::PortMAC 'get_port_macs';
use App::Netdisco::Util::Device 'match_to_setting';
use App::Netdisco::Util::Node 'check_mac';
use App::Netdisco::Util::SNMP 'snmp_comm_reindex';
use App::Netdisco::Util::Web 'sort_port';
use Dancer::Plugin::DBIC 'schema';
use Time::HiRes 'gettimeofday';
use Scope::Guard 'guard';
use Regexp::Common 'net';
use NetAddr::MAC ();
use List::MoreUtils ();
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->{'fwtable'} = {};
# cache the device ports to save hitting the database for many single rows
vars->{'device_ports'} = {map {($_->port => $_)}
$device->ports(undef, {prefetch => ['properties',
{neighbor_alias => 'device'}]})->all};
});
register_worker({ phase => 'main', driver => 'direct',
title => 'gather macs from file' }, sub {
my ($job, $workerconf) = @_;
my $device = $job->device;
return Status->info('skip: fwtable data supplied by other source')
unless $job->is_offline;
#Â load cache from file or copy from job param
my $data = $job->extra;
my @fwtable = (length $data ? @{ from_json($data) } : ());
return $job->cancel('data provided but 0 fwd entries found')
unless scalar @fwtable;
debug sprintf ' [%s] macsuck - %s forwarding table entries provided',
$device->ip, scalar @fwtable;
#Â rebuild fwtable in format for filtering more easily
foreach my $node (@fwtable) {
my $mac = NetAddr::MAC->new(mac => ($node->{'mac'} || ''));
next unless $node->{'port'} and $mac;
next if (($mac->as_ieee eq '00:00:00:00:00:00') or ($mac->as_ieee !~ m{^$RE{net}{MAC}$}i));
vars->{'fwtable'}->{ $node->{'vlan'} || 0 }
->{ $node->{'port'} }
->{ $mac->as_ieee } += 1;
}
return Status->done("Received MAC addresses for $device");
});
register_worker({ phase => 'main', driver => 'cli',
title => 'gather macs from CLI'}, sub {
my ($job, $workerconf) = @_;
my $device = $job->device;
my $cli = App::Netdisco::Transport::SSH->session_for($device)
or return Status->defer("macsuck failed: could not SSH connect to $device");
# Retrieve data through SSH connection
my $macs = $cli->macsuck;
my $nodecount = 0;
foreach my $vlan (keys %{ $macs }) {
( run in 1.229 second using v1.01-cache-2.11-cpan-39bf76dae61 )