create html dump file
[dell-switch] / neighbours.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use autodie;
5
6 # ./sw-name-mac.sh
7 # ./sw-names | xargs -i ./dell-switch.pl {} 'show lldp neighbors'
8
9 use Data::Dump qw(dump);
10
11 my $debug = $ENV{DEBUG} || 0;
12
13 my $mac2name;
14
15 open(my $f, '<'. '/dev/shm/sw-name-mac');
16 while(<$f>) {
17         chomp;
18         #my ( $ip, $name, $mac ) = split(/ /,$_);
19         my ( $name, $mac ) = split(/ /,$_);
20         $mac = lc($mac);
21         $mac2name->{$mac} = $name;
22 }
23
24 sub mac2name {
25         my ( $mac, $name ) = @_;
26
27         $mac = lc($mac);
28
29         if ( exists $mac2name->{$mac} ) {
30                 my $mac_name = $mac2name->{$mac};
31                 warn "ERROR: name different $name != $mac_name" if $name && $name ne $mac_name;
32                 return ( $mac, $mac_name );
33         }
34         return ( $mac, $name );
35 }
36
37 warn "# mac2name = ",dump($mac2name) if $debug;
38
39 open(my $n_fh, '>', '/dev/shm/neighbors.tab');
40 open(my $html_fh, '>', '/var/www/neighbors.html');
41 print $html_fh qq{<table>\n};
42
43 # parse Dell switch lldp neighbors output
44
45 foreach my $file ( glob('log/*lldp*') ) {
46         my ( undef, $name, undef ) = split(/_/, $file);
47         print "# $name $file\n" if $debug;
48
49         my $line_regex;
50         my @ports;
51
52         open(my $f, '<', $file);
53         while(<$f>) {
54                 chomp;
55                 #print "## $_<--\n";
56                 next if ( /^$/ || /^\s+Port/ );
57                 if ( /^--+/ ) {
58                         $line_regex = $_;
59                         $line_regex =~ s/\s+$//;
60                         $line_regex =~ s/-/./g;
61                         $line_regex =~ s/^/(/g;
62                         $line_regex =~ s/ /) (/g;
63                         $line_regex =~ s/$/)/g;
64
65                         if ( $file =~ m/remote-device/ ) {
66                                 $line_regex =~ s{\) \(}{.)(}g;
67                                 $line_regex =~ s{\(\.+\)$}{(.+)}g;
68                         }
69
70                         print "## line_regex = $line_regex\n" if $debug;
71                         next;
72                 }
73
74                 s{^\s+}{} if $file =~ m/remote-device/; # remote left-over from pager
75
76                 my @v;
77
78                 if ( defined($line_regex) &&  /$line_regex/ ) {
79                         # port, mac, remote_port, system_name, capabilities
80                         @v = ( $1, $2, $3, $4, $5 );
81
82                         if ( $file =~ m/neighbors/ ) {
83
84                                 # show lldp neighbours
85                                 # Port       Device ID          Port ID          System Name     Capabilities 
86
87                         } elsif ( $file =~ m/remote-device/ ) {
88
89                                 # show lldp remote-device all
90                                 # Interface RemID   Chassis ID          Port ID           System Name
91
92                                 @v = ( $v[0], $v[2], $v[3], $v[4], '' );
93
94                                 # move overflow numbers from system name to port id
95                                 if ( $v[3] =~ s{^(\d+)}{} ) {
96                                         $v[2] .= $1;
97                                 }
98
99                         } else {
100                                 die "don't know how to parse $file";
101                         }
102                 } elsif ( defined($line_regex) && $file =~ m/remote-device/ ) {
103                         # if we don't have system name, line_regex is too long
104                         my @s = split(/\s+/,$_);
105                         @v = ( $s[0], $s[2], $s[3], '', '' ) if $#s == 3;
106                 } elsif ( $debug ) {
107                         my $l = $line_regex;
108                         $l =~ s{[\(\)]}{}g;
109                         print "# [$_]<-- LINE IGNORED\n# [$l]\n",dump($_);
110                 }
111
112                 if (@v) {
113                         print "# [$_] ",join('|',@v),$/ if $debug;
114
115                         @v = map { s/^\s+//; s/\s+$//; $_ } @v;
116
117                         if ( length($v[1]) == 6 ) { # decode text mac
118                                 $v[1] = unpack('H*', $v[1]);
119                                 $v[1] =~ s/(..)/$1:/g;
120                                 $v[1] =~ s/:$//;
121                         }
122
123                         ( $v[1], $v[3] ) = mac2name( $v[1], $v[3] );
124
125
126                         #my ( $port, $device_id, $port_id, $system_name, $cap ) = @v;
127                         if ( @ports && $v[0] =~ m/^$/ ) {
128                                 my @old = @{ pop @ports };
129                                 foreach my $i ( 0 .. $#old ) {
130                                         $old[$i] .= $v[$i];
131                                 }
132                                 push @ports, [ @old ];
133                         } else {
134                                 push @ports, [ @v ];
135                         }
136                 } else {
137                         if ( $debug ) {
138                                 my $l = $line_regex;
139                                 $l =~ s{[\(\)]}{}g;
140                                 print "# [$_]<-- IGNORED no v\n# [$l]\n";
141                         }
142                 }
143         }
144
145         foreach my $p ( @ports ) {
146                 next if ( $p->[1] eq lc($p->[2]) && $p->[3] eq '' ); # FIXME hosts?
147                 print "$name ", join(' | ', @$p ), "\n";
148                 print $n_fh "$name\t", join("\t", @$p ), "\n";
149                 print $html_fh "<tr><td>$name</td><td>", join("</td><td>", @$p ), "</td></tr>\n";
150         }
151 }
152
153 # prase MikroTik /ip neighbor print detail terse
154
155 foreach my $file ( glob('../mikrotik-switch/out/*neighbor*'), glob('../tilera/out/*neighbor*') ) {
156         my $name = $1 if $file =~ m{out/([\w\-]+)\.ip neighbor};
157         print "## [$name] file $file\n" if $debug;
158         open(my $f, '<', $file);
159         while(<$f>) {
160                 chomp;
161                 next if m/^\s*$/;
162                 s{^\s*\d+\s+}{}; # remote ordinal number
163                 print "# $_\n" if $debug;
164                 my $l;
165                 foreach my $kv ( split(/ /, $_) ) {
166                         my ($k,$v) = split(/=/, $kv);
167                         $l->{$k} = $v if ( defined($v) && $v ne '""' );
168                 }
169
170                 no warnings 'uninitialized';
171
172                 #warn "## l=",dump($l),$/;
173                 # Port       Device ID          Port ID          System Name     Capabilities 
174                 my @v = (
175                         $l->{interface},
176                         $l->{'mac-address'},
177                         $l->{'interface-name'},
178                         $l->{'identity'},
179                         #$l->{caps},
180                         join(' ', $l->{address}, $l->{platform}, $l->{board}, $l->{version} ),
181                 );
182
183                 ( $v[1], $v[3] ) = mac2name( $v[1], $v[3] );
184
185                 print "$name ", join(' | ', @v), $/;
186                 print $n_fh "$name\t", join("\t", @v ), "\n";
187                 print $html_fh "<tr><td>$name</td><td>", join("</td><td>", @v ), "</td></tr>\n";
188         }
189 }
190
191 print $html_fh qq{</table>\n};