New version of the IOSXR module using Expect
* The previous module only worked for 32-bit IOSXR, and already there some fiddling with the STDIN of the process was required when being run from netdisco-backend * In 64-bit IOSXR, the STDIN workaround stopped working and created a stuck ssh process on every arpnip * This new version uses Expect instead of plain SSH, so a proper pty is provided under any circumstances * Successfully tested on recent 32- and 64-bit variants
This commit is contained in:
@@ -6,7 +6,10 @@ App::Netdisco::SSHCollector::Platform::IOSXR
|
|||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
Collect ARP entries from Cisco IOSXR devices.
|
Collect ARP entries from IOSXR routers using Expect
|
||||||
|
|
||||||
|
This is a reworked version of the IOSXR module, and it is suitable
|
||||||
|
for both 32- and 64-bit IOSXR.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
@@ -14,6 +17,7 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use Dancer ':script';
|
use Dancer ':script';
|
||||||
|
use Expect;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
=head1 PUBLIC METHODS
|
=head1 PUBLIC METHODS
|
||||||
@@ -34,20 +38,31 @@ Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADD
|
|||||||
sub arpnip {
|
sub arpnip {
|
||||||
my ($self, $hostlabel, $ssh, $args) = @_;
|
my ($self, $hostlabel, $ssh, $args) = @_;
|
||||||
|
|
||||||
# IOSXR show commands seem to depend on an available STDIN
|
|
||||||
unless (-t STDIN){
|
|
||||||
open STDIN, "<", "/dev/zero" or warn "Failed to fake stdin: $!";
|
|
||||||
}
|
|
||||||
|
|
||||||
debug "$hostlabel $$ arpnip()";
|
debug "$hostlabel $$ arpnip()";
|
||||||
my @data = $ssh->capture("show arp vrf all");
|
|
||||||
|
|
||||||
chomp @data;
|
my ($pty, $pid) = $ssh->open2pty;
|
||||||
my @arpentries;
|
unless ($pty) {
|
||||||
|
warn "unable to run remote command [$hostlabel] " . $ssh->error;
|
||||||
|
return ();
|
||||||
|
}
|
||||||
|
my $expect = Expect->init($pty);
|
||||||
|
|
||||||
|
my ($pos, $error, $match, $before, $after);
|
||||||
|
my $prompt = qr/# +$/;
|
||||||
|
my $timeout = 10;
|
||||||
|
|
||||||
|
($pos, $error, $match, $before, $after) = $expect->expect($timeout, -re, $prompt);
|
||||||
|
|
||||||
|
$expect->send("terminal length 0\n");
|
||||||
|
($pos, $error, $match, $before, $after) = $expect->expect($timeout, -re, $prompt);
|
||||||
|
|
||||||
|
$expect->send("show arp vrf all\n");
|
||||||
|
($pos, $error, $match, $before, $after) = $expect->expect($timeout, -re, $prompt);
|
||||||
|
|
||||||
|
my @arpentries = ();
|
||||||
|
my @data = split(m/\n/, $before);
|
||||||
|
|
||||||
# 0.0.0.0 00:00:00 0000.0000.0000 Dynamic ARPA GigabitEthernet0/0/0/0
|
|
||||||
foreach (@data) {
|
foreach (@data) {
|
||||||
|
|
||||||
my ($ip, $age, $mac, $state, $t, $iface) = split(/\s+/);
|
my ($ip, $age, $mac, $state, $t, $iface) = split(/\s+/);
|
||||||
|
|
||||||
if ($ip =~ m/(\d{1,3}\.){3}\d{1,3}/
|
if ($ip =~ m/(\d{1,3}\.){3}\d{1,3}/
|
||||||
@@ -56,6 +71,10 @@ sub arpnip {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$expect->send("exit\n");
|
||||||
|
$expect->soft_close();
|
||||||
|
|
||||||
return @arpentries;
|
return @arpentries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user