1package App::Netdisco::SSHCollector::Platform::CPVSX;
2
3=head1 NAME
4
5App::Netdisco::SSHCollector::Platform::CPVSX
6
7=head1 DESCRIPTION
8
9Collect ARP entries from Check Point VSX
10
11This collector uses "C<arp>" as the command for the arp utility on your
12system. Clish "C<show arp>" does not work correctly in versions prior to R77.30.
13Config example:
14
15 device_auth:
16   - tag: sshcpvsx
17     driver: cli
18     platform: CPVSX
19     only: '192.0.2.1'
20     username: oliver
21     password: letmein
22     expert_password: letmein2
23
24
25=cut
26
27use strict;
28use warnings;
29
30use Dancer ':script';
31use Expect;
32use Moo;
33
34=head1 PUBLIC METHODS
35
36=over 4
37
38=item B<arpnip($host, $ssh)>
39
40Retrieve ARP entries from device. C<$host> is the hostname or IP address
41of the device. C<$ssh> is a Net::OpenSSH connection to the device.
42
43Returns a list of hashrefs in the format C<< { mac => MACADDR, ip => IPADDR } >>.
44
45=back
46
47=cut
48
49sub arpnip {
50    my ($self, $hostlabel, $ssh, $args) = @_;
51
52    my @arpentries = ();
53
54    debug "$hostlabel $$ arpnip()";
55
56    my ($pty, $pid) = $ssh->open2pty;
57    unless ($pty) {
58        debug "unable to run remote command [$hostlabel] " . $ssh->error;
59        return ();
60    }
61    my $expect = Expect->init($pty);
62
63    my ($pos, $error, $match, $before, $after);
64    my $prompt;
65
66    $prompt = qr/>/;
67    ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
68
69    # TODO: check CP os/version via "cpstat os" and VSX status via "show vsx"
70    # $expect->send("show vsx\n");
71    # ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
72    # debug "$hostlabel $$ show vsx: $before";
73
74    # Enumerate virtual systems
75    # Virtual systems list
76    # VS ID       VS NAME
77    # 0           0
78    # 1           BACKUP-VSX_xxxxxx_Context
79    # ...
80
81    $expect->send("show virtual-system all\n");
82    ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
83
84    my @vsxentries = ();
85    my @lines = split(m/\n/, $before);
86
87    my $linereg = qr/(\d+)\s+([A-Za-z0-9_-]+)/;
88    foreach my $line (@lines) {
89        if ($line =~ $linereg) {
90            my ($vsid, $vsname) = ($1, $2);
91            push @vsxentries, { vsid => $vsid,  vsname=> $vsname };
92            debug "$hostlabel $$ $vsid, $vsname";
93        }
94    }
95
96    # TODO:
97    # Expert mode should be used only for pre-R77.30 versions
98    # For R77.30 and later we can use:
99    # set virtual-system $vsid
100    # show arp dynamic all
101
102    $expect->send("expert\n");
103
104    $prompt = qr/Enter expert password:/;
105    ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
106
107    $expect->send( $args->{expert_password} ."\n" );
108
109    $prompt = qr/#/;
110    ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
111
112    foreach (@vsxentries) {
113        my $vsid = $_->{vsid};
114        debug "$hostlabel $$ arpnip VSID: $vsid";
115
116        $expect->send("vsenv $vsid\n");
117        ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
118
119        $expect->send("arp -n | tail -n +2\n");
120        ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt);
121
122        @lines = split(m/\n/, $before);
123
124        # 192.168.1.1 ether 00:b6:aa:f5:bb:6e C eth1
125        $linereg = qr/([0-9\.]+)\s+ether\s+([a-fA-F0-9:]+)/;
126
127        foreach my $line (@lines) {
128            if ($line =~ $linereg) {
129                my ($ip, $mac) = ($1, $2);
130                push @arpentries, { mac => $mac, ip => $ip };
131                debug "$hostlabel $$ arpnip VSID: $vsid IP: $ip MAC: $mac";
132            }
133        }
134
135    }
136
137    $expect->send("exit\n");
138
139    $prompt = qr/>/;
140    ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt);
141
142    $expect->send("exit\n");
143
144    $expect->soft_close();
145
146    return @arpentries;
147}
148
1491;
150