netdisco-sshcollector script to get ARP data on devices without SNMP

This commit is contained in:
Oliver Gorwits
2014-08-25 10:13:18 +01:00
parent 6695f659a1
commit b59e844d57
8 changed files with 489 additions and 1 deletions

View File

@@ -0,0 +1,87 @@
package App::Netdisco::SSHCollector::Platform::ACE;
# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4:
=head1 NAME
App::Netdisco::SSHCollector::Platform::ACE
=head1 DESCRIPTION
Collect ARP entries from Cisco ACE load balancers. ACEs have multiple
virtual contexts with individual ARP tables. Contexts are enumerated
with C<show context>, afterwards the commands C<changeto CONTEXTNAME> and
C<show arp> must be executed for every context.
The IOS shell does not permit to combine mulitple commands in a single
line, and Net::OpenSSH uses individual connections for individual commands,
so we need to use Expect to execute the changeto and show commands in
the same context.
=cut
use strict;
use warnings;
use Moo;
use Expect;
=head1 PUBLIC METHODS
=over 4
=item B<arpnip($host, $ssh)>
Retrieve ARP entries from device. C<$host> is the hostname or IP address
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }.
=cut
sub arpnip{
my ($self, $hostlabel, $ssh, @args) = @_;
debug "$hostlabel $$ arpnip()";
my ($pty, $pid) = $ssh->open2pty or die "unable to run remote command";
my $expect = Expect->init($pty);
my ($pos, $error, $match, $before, $after);
my $prompt = qr/#/;
($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
$expect->send("terminal length 0\n");
($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt);
$expect->send("show context | include Name\n");
($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt);
my @ctx;
my @arpentries;
for (split(/\n/, $before)){
if (m/Name: (\S+)/){
push(@ctx, $1);
$expect->send("changeto $1\n");
($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt);
$expect->send("show arp\n");
($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt);
for (split(/\n/, $before)){
my ($ip, $mac) = split(/\s+/);
if ($ip =~ m/(\d{1,3}\.){3}\d{1,3}/ && $mac =~ m/[0-9a-f.]+/i) {
push(@arpentries, { ip => $ip, mac => $mac });
}
}
}
}
$expect->send("exit\n");
$expect->soft_close();
return @arpentries;
}
1;

View File

@@ -0,0 +1,66 @@
package App::Netdisco::SSHCollector::Platform::BigIP;
# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4:
=head1 NAME
NApp::etdisco::SSHCollector::Platform::BigIP
=head1 DESCRIPTION
Collect ARP entries from F5 BigIP load balancers. These are Linux boxes,
but feature an additional, proprietary IP stack which does not show
up in the standard SNMP ipNetToMediaTable.
These devices also feature a CLI interface similar to IOS, which can
either be set as the login shell of the user, or be called from an
ordinary shell. This module assumes the former, and if "show net arp"
can't be executed, falls back to the latter.
=cut
use strict;
use warnings;
use Moo;
=head1 PUBLIC METHODS
=over 4
=item B<arpnip($host, $ssh)>
Retrieve ARP entries from device. C<$host> is the hostname or IP address
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }.
=cut
sub arpnip {
my ($self, $hostlabel, $ssh, @args) = @_;
debug "$hostlabel $$ arpnip()";
my @data = $ssh->capture("show net arp");
unless (@data){
@data = $ssh->capture('tmsh -c "show net arp"');
}
chomp @data;
my @arpentries;
foreach (@data){
if (m/\d{1,3}\..*resolved/){
my (undef, $ip, $mac) = split(/\s+/);
# ips can look like 172.19.254.143%10, clean
$ip =~ s/%\d+//;
push(@arpentries, {mac => $mac, ip => $ip});
}
}
return @arpentries;
}
1;

View File

@@ -0,0 +1,55 @@
package App::Netdisco::SSHCollector::Platform::IOS;
# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4:
=head1 NAME
App::Netdisco::SSHCollector::Platform::IOS
=head1 DESCRIPTION
Collect ARP entries from Cisco IOS devices.
=cut
use strict;
use warnings;
use Dancer ':script';
use Data::Printer;
use Moo;
=head1 PUBLIC METHODS
=over 4
=item B<arpnip($host, $ssh)>
Retrieve ARP entries from device. C<$host> is the hostname or IP address
of the device. C<$ssh> is a Net::OpenSSH connection to the device.
Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }.
=cut
sub arpnip {
my ($self, $hostlabel, $ssh, @args) = @_;
debug "$hostlabel $$ arpnip()";
my @data = $ssh->capture("show ip arp");
chomp @data;
my @arpentries;
# Internet 172.16.20.15 13 0024.b269.867d ARPA FastEthernet0/0.1
foreach my $line (@data) {
next unless $line =~ m/^Internet/;
my @fields = split m/\s+/, $line;
push @arpentries, { mac => $fields[3], ip => $fields[1] };
}
return @arpentries;
}
1;