From 88371026d5b35d8cee55f073e0456417f94521a8 Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Fri, 24 May 2013 14:34:58 +0100 Subject: [PATCH] start on macsuck; tweak update locking --- Netdisco/lib/App/Netdisco/Util/Arpnip.pm | 39 ++++--------- .../lib/App/Netdisco/Util/DiscoverAndStore.pm | 4 +- Netdisco/lib/App/Netdisco/Util/Macsuck.pm | 57 +++++++++++++++++++ Netdisco/lib/App/Netdisco/Util/PortMAC.pm | 56 ++++++++++++++++++ 4 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 Netdisco/lib/App/Netdisco/Util/Macsuck.pm create mode 100644 Netdisco/lib/App/Netdisco/Util/PortMAC.pm diff --git a/Netdisco/lib/App/Netdisco/Util/Arpnip.pm b/Netdisco/lib/App/Netdisco/Util/Arpnip.pm index 71a4736c..2d8d869b 100644 --- a/Netdisco/lib/App/Netdisco/Util/Arpnip.pm +++ b/Netdisco/lib/App/Netdisco/Util/Arpnip.pm @@ -4,6 +4,7 @@ use Dancer qw/:syntax :script/; use Dancer::Plugin::DBIC 'schema'; use App::Netdisco::DB::ExplicitLocking ':modes'; +use App::Netdisco::Util::PortMAC ':all'; use App::Netdisco::Util::DNS ':all'; use NetAddr::IP::Lite ':lower'; use Time::HiRes 'gettimeofday'; @@ -27,11 +28,13 @@ subroutines. =head1 EXPORT_OK -=head2 arpnip( $device, $snmp ) +=head2 do_arpnip( $device, $snmp ) Given a Device database object, and a working SNMP connection, connect to a device and discover its ARP cache for IPv4 and Neighbor cache for IPv6. +Will also discover subnets in use on the device and update the Subnets table. + =cut sub do_arpnip { @@ -43,7 +46,7 @@ sub do_arpnip { } my (@v4, @v6); - my $port_macs = _get_port_macs($device, $snmp); + my $port_macs = get_port_macs($device); # get v4 arp table push @v4, _get_arps($device, $port_macs, $snmp->at_paddr, $snmp->at_netaddr); @@ -77,14 +80,13 @@ sub do_arpnip { # update subnets with new networks foreach my $cidr (@subnets) { schema('netdisco')->txn_do(sub { - # update_or_create doesn't seem to lock the row - schema('netdisco')->resultset('Subnet')->find( - {net => $cidr}, {for => 'update'}, - ); - schema('netdisco')->resultset('Subnet')->update_or_create({ + schema('netdisco')->resultset('Subnet')->update_or_create( + { net => $cidr, last_discover => \"to_timestamp($now)", - }); + }, + # update_or_create doesn't seem to lock the row + { for => 'update'}); }); } debug sprintf ' [%s] arpnip - processed %s Subnet entries', @@ -200,25 +202,4 @@ sub _gather_subnets { return @subnets; } -# returns table of MACs used by device's interfaces so that we don't bother to -# macsuck them. -sub _get_port_macs { - my ($device, $snmp) = @_; - my $port_macs; - - my $dp_macs = schema('netdisco')->resultset('DevicePort') - ->search({ mac => { '!=' => undef} }); - while (my $r = $dp_macs->next) { - $port_macs->{ $r->mac } = $r->ip; - } - - my $d_macs = schema('netdisco')->resultset('Device') - ->search({ mac => { '!=' => undef} }); - while (my $r = $d_macs->next) { - $port_macs->{ $r->mac } = $r->ip; - } - - return $port_macs; -} - 1; diff --git a/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm b/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm index 3b613c4a..d3700048 100644 --- a/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm +++ b/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm @@ -106,7 +106,7 @@ sub store_device { my $gone = $device->device_ips->delete; debug sprintf ' [%s] device - removed %s aliases', $device->ip, $gone; - $device->update_or_insert; + $device->update_or_insert({}, {for => 'update'}); $device->device_ips->populate(\@aliases); debug sprintf ' [%s] device - added %d new aliases', $device->ip, scalar @aliases; @@ -253,7 +253,7 @@ sub store_interfaces { my $gone = $device->ports->delete; debug sprintf ' [%s] interfaces - removed %s interfaces', $device->ip, $gone; - $device->update_or_insert; + $device->update_or_insert({}, {for => 'update'}); $device->ports->populate(\@interfaces); debug sprintf ' [%s] interfaces - added %d new interfaces', $device->ip, scalar @interfaces; diff --git a/Netdisco/lib/App/Netdisco/Util/Macsuck.pm b/Netdisco/lib/App/Netdisco/Util/Macsuck.pm new file mode 100644 index 00000000..d523cc7b --- /dev/null +++ b/Netdisco/lib/App/Netdisco/Util/Macsuck.pm @@ -0,0 +1,57 @@ +package App::Netdisco::Util::Macsuck; + +use Dancer qw/:syntax :script/; +use Dancer::Plugin::DBIC 'schema'; + +use App::Netdisco::DB::ExplicitLocking ':modes'; +use App::Netdisco::Util::PortMAC ':all'; +use NetAddr::IP::Lite ':lower'; +use Time::HiRes 'gettimeofday'; +use Net::MAC; + +use base 'Exporter'; +our @EXPORT = (); +our @EXPORT_OK = qw/ do_macsuck /; +our %EXPORT_TAGS = (all => \@EXPORT_OK); + +=head1 NAME + +App::Netdisco::Util::Macsuck + +=head1 DESCRIPTION + +Helper subroutine to support parts of the Netdisco application. + +There are no default exports, however the C<:all> tag will export all +subroutines. + +=head1 EXPORT_OK + +=head2 do_macsuck( $device, $snmp ) + +Given a Device database object, and a working SNMP connection, connect to a +device and discover the MAC addresses listed against each physical port +without a neighbor. + +If the device has VLANs, C will walk each VALN to get the MAC +addresses from there. + +It will also gather wireless client information if C +configuration setting is enabled. + +=cut + +sub do_macsuck { + my ($device, $snmp) = @_; + + unless ($device->in_storage) { + debug sprintf ' [%s] macsuck - skipping device not yet discovered', $device->ip; + return; + } + + my $port_macs = get_port_macs($device); + my $ports = $device->ports; + +} + +1; diff --git a/Netdisco/lib/App/Netdisco/Util/PortMAC.pm b/Netdisco/lib/App/Netdisco/Util/PortMAC.pm new file mode 100644 index 00000000..4ec33a53 --- /dev/null +++ b/Netdisco/lib/App/Netdisco/Util/PortMAC.pm @@ -0,0 +1,56 @@ +package App::Netdisco::Util::PortMAC; + +use Dancer qw/:syntax :script/; +use Dancer::Plugin::DBIC 'schema'; + +use base 'Exporter'; +our @EXPORT = (); +our @EXPORT_OK = qw/ get_port_macs /; +our %EXPORT_TAGS = (all => \@EXPORT_OK); + +=head1 NAME + +App::Netdisco::Util::PortMAC + +=head1 DESCRIPTION + +Helper subroutine to support parts of the Netdisco application. + +There are no default exports, however the C<:all> tag will export all +subroutines. + +=head1 EXPORT_OK + +=head2 get_port_macs( $device ) + +Returns a Hash reference of C<< { MAC => IP } >> for all interface MAC +addresses on a device. + +=cut + +sub get_port_macs { + my $device = shift; + my $port_macs = {}; + + unless ($device->in_storage) { + debug sprintf ' [%s] get_port_macs - skipping device not yet discovered', + $device->ip; + return $port_macs; + } + + my $dp_macs = schema('netdisco')->resultset('DevicePort') + ->search({ mac => { '!=' => undef} }); + while (my $r = $dp_macs->next) { + $port_macs->{ $r->mac } = $r->ip; + } + + my $d_macs = schema('netdisco')->resultset('Device') + ->search({ mac => { '!=' => undef} }); + while (my $r = $d_macs->next) { + $port_macs->{ $r->mac } = $r->ip; + } + + return $port_macs; +} + +1;