Node DNS names resolved in their own job

This commit is contained in:
Oliver Gorwits
2013-10-07 21:44:40 +01:00
parent e367805e51
commit 1deba8f90c
9 changed files with 146 additions and 14 deletions

View File

@@ -1,10 +1,11 @@
2.017001_001 -
2.017001_002 -
[NEW FEATURES]
* Add VLAN Inventory Report
* Add Wireless SSID Inventory Report
* Add Device Inventory by Location Report
* Node DNS names resolved in their own job - see nodenames_no and nodenames_only
[ENHANCEMENTS]

View File

@@ -10,7 +10,7 @@ use Time::HiRes 'gettimeofday';
use base 'Exporter';
our @EXPORT = ();
our @EXPORT_OK = qw/ do_arpnip store_arp /;
our @EXPORT_OK = qw/ do_arpnip store_arp resolve_node_names /;
our %EXPORT_TAGS = (all => \@EXPORT_OK);
=head1 NAME
@@ -82,16 +82,16 @@ sub _get_arps {
my $ip = $netaddr->{$arp};
next unless defined $ip;
next unless check_mac($device, $node);
push @arps, [$node, $ip, hostname_from_ip($ip)];
push @arps, [$node, $ip];
}
return @arps;
}
=head2 store_arp( $mac, $ip, $name, $now? )
=head2 store_arp( $mac, $ip, $now? )
Stores a new entry to the C<node_ip> table with the given MAC, IP (v4 or v6)
and DNS host name.
Stores a new entry to the C<node_ip> table with the given MAC, and IP (v4 or
v6).
Will mark old entries for this IP as no longer C<active>.
@@ -101,7 +101,7 @@ C<time_last> timestamp, otherwise the current timestamp (C<now()>) is used.
=cut
sub store_arp {
my ($mac, $ip, $name, $now) = @_;
my ($mac, $ip, $now) = @_;
$now ||= 'now()';
schema('netdisco')->txn_do(sub {
@@ -119,7 +119,6 @@ sub store_arp {
->search({'me.mac' => $mac, 'me.ip' => $ip})
->update_or_create(
{
dns => $name,
active => \'true',
time_last => \$now,
},
@@ -172,4 +171,39 @@ sub _store_subnet {
});
}
=head2 resolve_node_names( $device )
Given a Device database object, resolve Node IP (ARP) entries belonging to
this device into DNS names, and store them in the C<node_ip> database table.
This action is usually queued following C<do_arpip> so that it may run
asynchronously, and/or on another daemon worker node.
=cut
sub resolve_node_names {
my ($device) = @_;
schema('netdisco')->txn_do(sub {
my $nodeips = schema('netdisco')
->resultset('NodeIp')->search(
{
-and => [
-bool => 'me.active',
-bool => 'nodes.active',
],
'nodes.switch' => $device->ip,
},
{
join => 'nodes',
for => 'update',
}
);
while (my $nodeip = $nodeips->next) {
$nodeip->update({dns => hostname_from_ip($nodeip->ip)});
}
});
}
1;

View File

@@ -22,7 +22,7 @@ sub capacity_for {
debug "checking local capacity for action $action";
my $action_map = {
Poller => [qw/discoverall discover arpwalk arpnip macwalk macsuck/],
Poller => [qw/discoverall discover arpwalk arpnip nodenames macwalk macsuck/],
Interactive => [qw/location contact portcontrol portname vlan power/],
};

View File

@@ -13,7 +13,7 @@ my $fqdn = hostfqdn || 'localhost';
my $role_map = {
(map {$_ => 'Poller'}
qw/discoverall discover arpwalk arpnip macwalk macsuck/),
qw/discoverall discover arpwalk arpnip nodenames macwalk macsuck/),
(map {$_ => 'Interactive'}
qw/location contact portcontrol portname vlan power/)
};

View File

@@ -1,9 +1,17 @@
package App::Netdisco::Daemon::Worker::Poller::Arpnip;
use Dancer::Plugin::DBIC 'schema';
use App::Netdisco::Core::Arpnip 'do_arpnip';
use App::Netdisco::Util::Device 'is_arpnipable';
use App::Netdisco::Util::Device qw/get_device is_arpnipable can_nodenames/;
use App::Netdisco::Core::Arpnip 'resolve_node_names';
use App::Netdisco::Daemon::Util ':all';
use NetAddr::IP::Lite ':lower';
use Role::Tiny;
use Class::Method::Modifiers;
use namespace::clean;
with 'App::Netdisco::Daemon::Worker::Poller::Common';
@@ -15,4 +23,43 @@ sub arpnip_layer { 3 }
sub arpwalk { (shift)->_walk_body('arpnip', @_) }
sub arpnip { (shift)->_single_body('arpnip', @_) }
after 'arpnip' => sub {
my ($self, $job) = @_;
my $host = NetAddr::IP::Lite->new($job->device);
my $device = get_device($host->addr);
my $jobqueue = schema('netdisco')->resultset('Admin');
schema('netdisco')->txn_do(sub {
$jobqueue->create({
device => $device->ip,
action => 'nodenames',
status => 'queued',
username => $job->username,
userip => $job->userip,
});
});
};
# run a nodenames job for one device
sub nodenames {
my ($self, $job) = @_;
my $host = NetAddr::IP::Lite->new($job->device);
my $device = get_device($host->addr);
my $jobqueue = schema('netdisco')->resultset('Admin');
if ($device->ip eq '0.0.0.0') {
return job_error("nodenames failed: no device param (need -d ?)");
}
unless (can_nodenames($device->ip)) {
return job_defer("nodenames deferred: cannot run for $host");
}
resolve_node_names($device);
return job_done("Ended nodenames for ". $host->addr);
}
1;

View File

@@ -444,6 +444,22 @@ Value: Number. Default: 0.
Sets the minimum amount of time in seconds which must elapse between any two
arpnip jobs for a device.
=head3 C<nodenames_no>
Value: List of Network Identifiers or Device Properties. Default: Empty List.
Devices in the list will not have their Node IPs resolved to names using the
DNS. You can include hostnames, IP addresses and subnets (IPv4 or IPv6) in the
list.
=head3 C<nodenames_only>
Value: List of Network Identifiers or Device Properties. Default: Empty List.
Only thos devices in the list will have their Node IPs resolved to names using
the DNS. You can include hostnames, IP addresses and subnets (IPv4 or IPv6) in
the list.
=head3 C<store_wireless_clients>
Value: Boolean. Default: C<true>.

View File

@@ -35,15 +35,20 @@ but they are backwards compatible.
=back
=head1 2.017001_001
=head1 2.017001_002
=head2 General Notices
The previous mentioned bug in Macsuck is now fixed.
During Arpnip, Node IPs are no longer resolved to DNS hostnames in real-time.
In the next release, another job will be queued to perform this action for the
device.
Another job is queued to perform this action for the device. You can therefore
control using the new C<nodenames_no> and C<nodenames_only> config parameters
which daemons run this job.
The idea here is to support sites where the SNMP polling node has no useful
DNS, but another system can update the DNS entries for nodes (yet do no
polling).
=head1 2.017000

View File

@@ -12,6 +12,7 @@ our @EXPORT_OK = qw/
check_no
is_discoverable
is_arpnipable
can_nodenames
is_macsuckable
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK);
@@ -195,6 +196,32 @@ sub is_arpnipable {
return 1;
}
=head2 can_nodenames( $ip )
Given an IP address, returns C<true> if Netdisco on this host is permitted by
the local configuration to resolve Node IPs to DNS names for the device.
The configuration items C<nodenames_no> and C<nodenames_only> are checked
against the given IP.
Returns false if the host is not permitted to do this job for the target
device.
=cut
sub can_nodenames {
my $ip = shift;
my $device = get_device($ip) or return 0;
return _bail_msg("can_nodenames device matched nodenames_no")
if check_no($device, 'nodenames_no');
return _bail_msg("can_nodenames: device failed to match nodenames_only")
if check_no($device, 'nodenames_only');
return 1;
}
=head2 is_macsuckable( $ip )
Given an IP address, returns C<true> if Netdisco on this host is permitted by

View File

@@ -86,6 +86,8 @@ macsuck_min_age: 0
arpnip_no: []
arpnip_only: []
arpnip_min_age: 0
nodenames_no: []
nodenames_only: []
store_wireless_clients: true
store_modules: true
ignore_interfaces: