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 Dancer::Plugin::DBIC 'schema';
use App::Netdisco::DB::ExplicitLocking ':modes'; use App::Netdisco::DB::ExplicitLocking ':modes';
use App::Netdisco::Util::PortMAC ':all';
use App::Netdisco::Util::DNS ':all'; use App::Netdisco::Util::DNS ':all';
use NetAddr::IP::Lite ':lower'; use NetAddr::IP::Lite ':lower';
use Time::HiRes 'gettimeofday'; use Time::HiRes 'gettimeofday';
@@ -27,11 +28,13 @@ subroutines.
=head1 EXPORT_OK =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 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. 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 =cut
sub do_arpnip { sub do_arpnip {
@@ -43,7 +46,7 @@ sub do_arpnip {
} }
my (@v4, @v6); my (@v4, @v6);
my $port_macs = _get_port_macs($device, $snmp); my $port_macs = get_port_macs($device);
# get v4 arp table # get v4 arp table
push @v4, _get_arps($device, $port_macs, $snmp->at_paddr, $snmp->at_netaddr); 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 # update subnets with new networks
foreach my $cidr (@subnets) { foreach my $cidr (@subnets) {
schema('netdisco')->txn_do(sub { schema('netdisco')->txn_do(sub {
# update_or_create doesn't seem to lock the row schema('netdisco')->resultset('Subnet')->update_or_create(
schema('netdisco')->resultset('Subnet')->find( {
{net => $cidr}, {for => 'update'},
);
schema('netdisco')->resultset('Subnet')->update_or_create({
net => $cidr, net => $cidr,
last_discover => \"to_timestamp($now)", 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', debug sprintf ' [%s] arpnip - processed %s Subnet entries',
@@ -200,25 +202,4 @@ sub _gather_subnets {
return @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; 1;

View File

@@ -106,7 +106,7 @@ sub store_device {
my $gone = $device->device_ips->delete; my $gone = $device->device_ips->delete;
debug sprintf ' [%s] device - removed %s aliases', debug sprintf ' [%s] device - removed %s aliases',
$device->ip, $gone; $device->ip, $gone;
$device->update_or_insert; $device->update_or_insert({}, {for => 'update'});
$device->device_ips->populate(\@aliases); $device->device_ips->populate(\@aliases);
debug sprintf ' [%s] device - added %d new aliases', debug sprintf ' [%s] device - added %d new aliases',
$device->ip, scalar @aliases; $device->ip, scalar @aliases;
@@ -253,7 +253,7 @@ sub store_interfaces {
my $gone = $device->ports->delete; my $gone = $device->ports->delete;
debug sprintf ' [%s] interfaces - removed %s interfaces', debug sprintf ' [%s] interfaces - removed %s interfaces',
$device->ip, $gone; $device->ip, $gone;
$device->update_or_insert; $device->update_or_insert({}, {for => 'update'});
$device->ports->populate(\@interfaces); $device->ports->populate(\@interfaces);
debug sprintf ' [%s] interfaces - added %d new interfaces', debug sprintf ' [%s] interfaces - added %d new interfaces',
$device->ip, scalar @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;