start on macsuck; tweak update locking

This commit is contained in:
Oliver Gorwits
2013-05-24 14:34:58 +01:00
parent 6f7c87ac07
commit 88371026d5
4 changed files with 125 additions and 31 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<do_macsuck> will walk each VALN to get the MAC
addresses from there.
It will also gather wireless client information if C<store_wireless_client>
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;

View File

@@ -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;