netdisco-do -d accepts IP prefixes (subnet in CIDR format)

This commit is contained in:
Oliver Gorwits
2015-03-07 13:17:49 +00:00
parent f7bc66ff54
commit b98d75b01c
5 changed files with 83 additions and 59 deletions

View File

@@ -3,6 +3,7 @@
[NEW FEATURES] [NEW FEATURES]
* macsuck_unsupported setting to allow node gathering on delinquent switches * macsuck_unsupported setting to allow node gathering on delinquent switches
* netdisco-do -d accepts IP prefixes (subnet in CIDR format)
[ENHANCEMENTS] [ENHANCEMENTS]

View File

@@ -40,8 +40,12 @@ use Dancer qw/:moose :script/;
info "App::Netdisco version $App::Netdisco::VERSION loaded."; info "App::Netdisco version $App::Netdisco::VERSION loaded.";
use NetAddr::IP ':rfc3021';
use App::Netdisco::Util::Device 'get_device';
use Try::Tiny; use Try::Tiny;
use Pod::Usage; use Pod::Usage;
use Scalar::Util 'blessed';
use Getopt::Long; use Getopt::Long;
Getopt::Long::Configure ("bundling"); Getopt::Long::Configure ("bundling");
@@ -121,12 +125,9 @@ unless ($action) {
} }
sub show { sub show {
my $ip = NetAddr::IP::Lite->new($device) my ($self, $job) = @_;
or return ('error', "Bad host or IP: $device"); my ($device, $port, $extra) = map {$job->$_} qw/device port extra/;
my $dev = get_device($ip->addr); return ('error', 'Missing device (-d).') if !defined $device;
unless (blessed $dev and $dev->in_storage) {
return ('error', "Don't know device: $device");
}
$extra ||= 'interfaces'; my $class = undef; $extra ||= 'interfaces'; my $class = undef;
($class, $extra) = split(/::([^:]+)$/, $extra); ($class, $extra) = split(/::([^:]+)$/, $extra);
@@ -137,59 +138,56 @@ unless ($action) {
$extra = $class; $extra = $class;
undef $class; undef $class;
} }
my $i = App::Netdisco::Util::SNMP::snmp_connect($dev, $class); my $i = App::Netdisco::Util::SNMP::snmp_connect($device, $class);
Data::Printer::p($i->$extra); Data::Printer::p($i->$extra);
return ('done', "Showed $extra response from $device."); return ('done', sprintf "Showed %s response from %s.", $extra, $device->ip);
} }
sub delete { sub delete {
my $ip = NetAddr::IP::Lite->new($device) my ($self, $job) = @_;
or return ('error', "Bad host or IP: $device"); my ($device, $port, $extra) = map {$job->$_} qw/device port extra/;
my $dev = get_device($ip->addr); return ('error', 'Missing device (-d).') if !defined $device;
unless (blessed $dev and $dev->in_storage) {
return ('error', "Don't know device: $device");
}
$port = ($port ? 1 : 0); $port = ($port ? 1 : 0);
delete_device($dev->ip, $port, $extra); delete_device($device, $port, $extra);
return ('done', "Deleted device $device."); return ('done', sprintf "Deleted device %s.", $device->ip);
} }
sub renumber { sub renumber {
my $ip = NetAddr::IP::Lite->new($device) my ($self, $job) = @_;
or return ('error', "Bad host or IP: $device"); my ($device, $port, $extra) = map {$job->$_} qw/device port extra/;
my $dev = get_device($ip->addr); return ('error', 'Missing device (-d).') if !defined $device;
unless (blessed $dev and $dev->in_storage) { my $old_ip = $device->ip;
return ('error', "Don't know device: $device");
}
my $old_ip = $dev->ip;
my $new_ip = NetAddr::IP::Lite->new($extra) my $new_ip = NetAddr::IP::Lite->new($extra)
or return ('error', "Bad host or IP: $extra"); or return ('error', "Bad host or IP: $extra");
my $new_dev = get_device($new_ip->addr); my $new_dev = get_device($new_ip->addr);
unless ($new_dev and not $new_dev->in_storage) { unless ($new_dev and not $new_dev->in_storage) {
return ('error', "Already know new device: $device"); return ('error', sprintf "Already know new device: %s.", $device->ip);
} }
renumber_device($dev->ip, $new_dev->ip); renumber_device($device, $new_dev->ip);
return ('done', sprintf 'Renumbered device %s from %s to %s.', return ('done', sprintf 'Renumbered device %s from %s to %s.',
$device, $old_ip, $new_dev->ip); $device->ip, $old_ip, $new_dev->ip);
} }
sub psql { sub psql {
my ($self, $job) = @_;
my ($device, $port, $extra) = map {$job->$_} qw/device port extra/;
my $name = (setting('database')->{name} || 'netdisco'); my $name = (setting('database')->{name} || 'netdisco');
my $host = setting('database')->{host}; my $host = setting('database')->{host};
my $user = setting('database')->{user}; my $user = setting('database')->{user};
my $pass = setting('database')->{pass}; my $pass = setting('database')->{pass};
my $port = undef; my $portnum = undef;
if ($host =~ m/([^;]+);port=(\d+)/) { if ($host =~ m/([^;]+);port=(\d+)/) {
$host = $1; $host = $1;
$port = $2; $portnum = $2;
} }
$ENV{PGHOST} = $host if $host; $ENV{PGHOST} = $host if $host;
$ENV{PGPORT} = $port if defined $port; $ENV{PGPORT} = $portnum if defined $portnum;
$ENV{PGDATABASE} = $name; $ENV{PGDATABASE} = $name;
$ENV{PGUSER} = $user; $ENV{PGUSER} = $user;
$ENV{PGPASSWORD} = $pass; $ENV{PGPASSWORD} = $pass;
@@ -215,30 +213,48 @@ if (not $worker->can( $action )) {
); );
} }
# what job are we asked to do? my $net = NetAddr::IP->new($device);
my $job = App::Netdisco::Daemon::Job->new({ if ($device and (!$net or $net->num == 0)) {
info sprintf '%s: error - Bad host, IP or prefix: %s', $action, $device;
exit 1;
}
my @hostlist = defined $device ? ($net->hostenum) : (undef);
my $exitstatus = 0;
foreach my $host (@hostlist) {
my $dev = $host ? get_device($host->addr) : undef;
if ($dev and not (blessed $dev and $dev->in_storage) and $action ne 'discover') {
info sprintf "%s: error - Don't know device: %s", $action, $host->addr;
next;
}
# what job are we asked to do?
my $job = App::Netdisco::Daemon::Job->new({
job => 0, job => 0,
action => $action, action => $action,
device => $device, device => $dev,
port => $port, port => $port,
subaction => $extra, subaction => $extra,
}); });
# do job # do job
my ($status, $log); my ($status, $log);
try { try {
info sprintf '%s: started at %s', $action, scalar localtime; info sprintf '%s: started at %s', $action, scalar localtime;
($status, $log) = $worker->$action($job); ($status, $log) = $worker->$action($job);
} }
catch { catch {
$status = 'error'; $status = 'error';
$log = "error running job: $_"; $log = "error running job: $_";
}; };
info sprintf '%s: finished at %s', $action, scalar localtime; info sprintf '%s: finished at %s', $action, scalar localtime;
info sprintf '%s: status %s: %s', $action, $status, $log; info sprintf '%s: status %s: %s', $action, $status, $log;
$exitstatus = 1 if !defined $status or $status eq 'error';
}
exit ($status eq 'done' ? 0 : 1); exit $exitstatus;
=head1 NAME =head1 NAME
@@ -252,6 +268,10 @@ netdisco-do - Run any Netdisco job from the command-line.
This program allows you to run any Netdisco poller job from the command-line. This program allows you to run any Netdisco poller job from the command-line.
The C<-d> option will accept a hostname (that can be resolved to an IP with
DNS), an IP address, or IP prefix (subnets in CIDR format). It can be any
interface on the device known to Netdisco.
Note that some jobs (C<discoverall>, C<macwalk>, C<arpwalk>, C<nbtwalk>) Note that some jobs (C<discoverall>, C<macwalk>, C<arpwalk>, C<nbtwalk>)
simply add entries to the Netdisco job queue for other jobs, so won't seem simply add entries to the Netdisco job queue for other jobs, so won't seem
to do much when you trigger them. to do much when you trigger them.

View File

@@ -46,8 +46,9 @@ sub _single_body {
my $layer_method = $job_type .'_layer'; my $layer_method = $job_type .'_layer';
my $job_layer = $self->$layer_method; my $job_layer = $self->$layer_method;
my $host = NetAddr::IP::Lite->new($job->device); my $device = get_device($job->device)
my $device = get_device($host->addr); or job_error("$job_type failed: unable to interpret device parameter");
my $host = $device->ip;
if ($device->in_storage if ($device->in_storage
and $device->vendor and $device->vendor eq 'netdisco') { and $device->vendor and $device->vendor eq 'netdisco') {
@@ -72,7 +73,7 @@ sub _single_body {
$job_action->($device, $snmp); $job_action->($device, $snmp);
return job_done("Ended $job_type for ". $host->addr); return job_done("Ended $job_type for $host");
} }
sub _single_node_body { sub _single_node_body {

View File

@@ -39,8 +39,9 @@ sub discoverall {
sub discover { sub discover {
my ($self, $job) = @_; my ($self, $job) = @_;
my $host = NetAddr::IP::Lite->new($job->device); my $device = get_device($job->device)
my $device = get_device($host->addr); or job_error("discover failed: unable to interpret device parameter");
my $host = $device->ip;
if ($device->ip eq '0.0.0.0') { if ($device->ip eq '0.0.0.0') {
return job_error("discover failed: no device param (need -d ?)"); return job_error("discover failed: no device param (need -d ?)");
@@ -90,7 +91,7 @@ sub discover {
} }
} }
return job_done("Ended discover for ". $host->addr); return job_done("Ended discover for $host");
} }
1; 1;

View File

@@ -25,8 +25,9 @@ sub nbtwalk { (shift)->_walk_body('nbtstat', @_) }
sub nbtstat { sub nbtstat {
my ($self, $job) = @_; my ($self, $job) = @_;
my $host = NetAddr::IP::Lite->new($job->device); my $device = get_device($job->device)
my $device = get_device($host->addr); or job_error("nbtstat failed: unable to interpret device parameter");
my $host = $device->ip;
unless (is_discoverable($device->ip)) { unless (is_discoverable($device->ip)) {
return job_defer("nbtstat deferred: $host is not discoverable"); return job_defer("nbtstat deferred: $host is not discoverable");
@@ -66,7 +67,7 @@ sub nbtstat {
} }
} }
return job_done("Ended nbtstat for ". $host->addr); return job_done("Ended nbtstat for $host");
} }
1; 1;