line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::Manoc::Netwalker::Poller::DeviceTask; |
2
|
|
|
|
|
|
|
#ABSTRACT: Device poller task |
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
2748
|
use Moose; |
|
1
|
|
|
|
|
12
|
|
|
1
|
|
|
|
|
6
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '2.99.2'; ##TRIAL VERSION |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
5618
|
use Try::Tiny; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
52
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
345
|
use App::Manoc::Netwalker::Poller::TaskReport; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
35
|
|
11
|
1
|
|
|
1
|
|
442
|
use App::Manoc::Manifold; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
22
|
|
12
|
1
|
|
|
1
|
|
338
|
use App::Manoc::IPAddress::IPv4; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has 'device_id' => ( |
16
|
|
|
|
|
|
|
is => 'ro', |
17
|
|
|
|
|
|
|
isa => 'Int', |
18
|
|
|
|
|
|
|
required => 1 |
19
|
|
|
|
|
|
|
); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has 'device_entry' => ( |
23
|
|
|
|
|
|
|
is => 'ro', |
24
|
|
|
|
|
|
|
isa => 'Maybe[Object]', |
25
|
|
|
|
|
|
|
lazy => 1, |
26
|
|
|
|
|
|
|
builder => '_build_device_entry', |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
has 'nwinfo' => ( |
31
|
|
|
|
|
|
|
is => 'ro', |
32
|
|
|
|
|
|
|
isa => 'Object', |
33
|
|
|
|
|
|
|
lazy => 1, |
34
|
|
|
|
|
|
|
builder => '_build_nwinfo', |
35
|
|
|
|
|
|
|
); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
has 'device_set' => ( |
39
|
|
|
|
|
|
|
is => 'ro', |
40
|
|
|
|
|
|
|
isa => 'HashRef', |
41
|
|
|
|
|
|
|
builder => '_build_device_set', |
42
|
|
|
|
|
|
|
); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
has 'source' => ( |
46
|
|
|
|
|
|
|
is => 'ro', |
47
|
|
|
|
|
|
|
lazy => 1, |
48
|
|
|
|
|
|
|
builder => '_build_source', |
49
|
|
|
|
|
|
|
); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
has 'config_source' => ( |
53
|
|
|
|
|
|
|
is => 'ro', |
54
|
|
|
|
|
|
|
lazy => 1, |
55
|
|
|
|
|
|
|
builder => '_build_config_source', |
56
|
|
|
|
|
|
|
); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
has 'task_report' => ( |
60
|
|
|
|
|
|
|
is => 'ro', |
61
|
|
|
|
|
|
|
required => 0, |
62
|
|
|
|
|
|
|
builder => '_build_task_report', |
63
|
|
|
|
|
|
|
); |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
has 'uplinks' => ( |
67
|
|
|
|
|
|
|
is => 'ro', |
68
|
|
|
|
|
|
|
lazy => 1, |
69
|
|
|
|
|
|
|
builder => '_build_uplinks', |
70
|
|
|
|
|
|
|
); |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
has 'native_vlan' => ( |
74
|
|
|
|
|
|
|
is => 'ro', |
75
|
|
|
|
|
|
|
lazy => 1, |
76
|
|
|
|
|
|
|
builder => '_build_native_vlan', |
77
|
|
|
|
|
|
|
); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
has 'arp_vlan' => ( |
81
|
|
|
|
|
|
|
is => 'ro', |
82
|
|
|
|
|
|
|
lazy => 1, |
83
|
|
|
|
|
|
|
builder => '_build_arp_vlan', |
84
|
|
|
|
|
|
|
); |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
with 'App::Manoc::Netwalker::Poller::BaseTask', 'App::Manoc::Logger::Role'; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
#----------------------------------------------------------------------# |
89
|
|
|
|
|
|
|
# # |
90
|
|
|
|
|
|
|
# A t t r i b u t e s B u i l d e r # |
91
|
|
|
|
|
|
|
# # |
92
|
|
|
|
|
|
|
#----------------------------------------------------------------------# |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub _build_arp_vlan { |
95
|
|
|
|
|
|
|
my $self = shift; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
my $vlan = $self->nwinfo->arp_vlan->id || |
98
|
|
|
|
|
|
|
$self->config->default_vlan; |
99
|
|
|
|
|
|
|
return defined($vlan) ? $vlan : 1; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub _build_device_entry { |
103
|
|
|
|
|
|
|
my $self = shift; |
104
|
|
|
|
|
|
|
my $device_id = $self->device_id; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
return $self->schema->resultset('Device')->find( $self->device_id ); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub _build_device_set { |
110
|
|
|
|
|
|
|
my $self = shift; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# columns are not inflated |
113
|
|
|
|
|
|
|
my @addresses = $self->schema->resultset('Device')->get_column('mng_address')->all; |
114
|
|
|
|
|
|
|
my %addr_set = map { App::Manoc::IPAddress::IPv4->new($_)->unpadded => 1 } @addresses; |
115
|
|
|
|
|
|
|
return \%addr_set; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub _build_native_vlan { |
119
|
|
|
|
|
|
|
my $self = shift; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
my $vlan = $self->nwinfo->mat_native_vlan->id || |
122
|
|
|
|
|
|
|
$self->config->default_vlan; |
123
|
|
|
|
|
|
|
return defined($vlan) ? $vlan : 1; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub _build_nwinfo { |
127
|
|
|
|
|
|
|
my $self = shift; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
return $self->device_entry->netwalker_info; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub _create_manifold { |
133
|
|
|
|
|
|
|
my $self = shift; |
134
|
|
|
|
|
|
|
my $manifold_name = shift; |
135
|
|
|
|
|
|
|
my %params = @_; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
my $manifold; |
138
|
|
|
|
|
|
|
try { |
139
|
|
|
|
|
|
|
$manifold = App::Manoc::Manifold->new_manifold( $manifold_name, %params ); |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
catch { |
142
|
|
|
|
|
|
|
my $error = "Internal error while creating manifold $manifold_name: $_"; |
143
|
|
|
|
|
|
|
$self->log->debug($error); |
144
|
|
|
|
|
|
|
return; |
145
|
|
|
|
|
|
|
}; |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
$manifold or $self->log->debug("Manifold constructor returned undef"); |
148
|
|
|
|
|
|
|
return $manifold; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub _build_config_source { |
152
|
|
|
|
|
|
|
my $self = shift; |
153
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
154
|
|
|
|
|
|
|
my $nwinfo = $self->nwinfo; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
my $manifold_name = $nwinfo->config_manifold; |
157
|
|
|
|
|
|
|
if ( !defined($manifold_name) || $manifold_name eq $nwinfo->manifold ) { |
158
|
|
|
|
|
|
|
$self->log->debug("Using common Manifold for config"); |
159
|
|
|
|
|
|
|
return $self->source; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
$self->log->debug("Using Manifold $manifold_name for config"); |
163
|
|
|
|
|
|
|
my $host = $entry->mng_address->unpadded; |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
my %params = ( |
166
|
|
|
|
|
|
|
host => $host, |
167
|
|
|
|
|
|
|
credentials => $self->credentials |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
my $source = $self->_create_manifold( $manifold_name, %params ); |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
if ( !$source ) { |
172
|
|
|
|
|
|
|
my $error = "Cannot create config source with manifold $manifold_name"; |
173
|
|
|
|
|
|
|
$self->log->error($error); |
174
|
|
|
|
|
|
|
$self->task_report->add_error($error); |
175
|
|
|
|
|
|
|
return; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# auto connect |
179
|
|
|
|
|
|
|
if ( !$source->connect() ) { |
180
|
|
|
|
|
|
|
my $error = "Cannot connect to $host"; |
181
|
|
|
|
|
|
|
$self->log->error($error); |
182
|
|
|
|
|
|
|
$self->task_report->add_error($error); |
183
|
|
|
|
|
|
|
return; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
return $source; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub _build_source { |
189
|
|
|
|
|
|
|
my $self = shift; |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
192
|
|
|
|
|
|
|
my $nwinfo = $self->nwinfo; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
my $host = $entry->mng_address->unpadded; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
my $manifold_name = $nwinfo->manifold; |
197
|
|
|
|
|
|
|
$self->log->debug("Using Manifold $manifold_name"); |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
my %params = ( |
200
|
|
|
|
|
|
|
host => $host, |
201
|
|
|
|
|
|
|
credentials => $self->credentials, |
202
|
|
|
|
|
|
|
extra_params => { |
203
|
|
|
|
|
|
|
mat_force_vlan => $self->config->mat_force_vlan, |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
); |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
my $source = $self->_create_manifold( $manifold_name, %params ); |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
if ( !$source ) { |
210
|
|
|
|
|
|
|
my $error = "Cannot create source with manifold $manifold_name"; |
211
|
|
|
|
|
|
|
$self->log->error($error); |
212
|
|
|
|
|
|
|
$self->task_report->add_error($error); |
213
|
|
|
|
|
|
|
return; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# auto connect |
217
|
|
|
|
|
|
|
if ( !$source->connect() ) { |
218
|
|
|
|
|
|
|
my $error = "Cannot connect to $host"; |
219
|
|
|
|
|
|
|
$self->log->error($error); |
220
|
|
|
|
|
|
|
$self->task_report->add_error($error); |
221
|
|
|
|
|
|
|
return; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
return $source; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub _build_task_report { |
227
|
|
|
|
|
|
|
my $self = shift; |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
$self->device_entry or return; |
230
|
|
|
|
|
|
|
my $device_address = $self->device_entry->mng_address->address; |
231
|
|
|
|
|
|
|
return App::Manoc::Netwalker::Poller::TaskReport->new( host => $device_address ); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
sub _build_uplinks { |
235
|
|
|
|
|
|
|
my $self = shift; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
238
|
|
|
|
|
|
|
my $source = $self->source; |
239
|
|
|
|
|
|
|
my $device_set = $self->device_set; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
my %uplinks; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# get uplink from CDP |
244
|
|
|
|
|
|
|
my $neighbors = $source->neighbors; |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# filter CDP links |
247
|
|
|
|
|
|
|
while ( my ( $p, $n ) = each(%$neighbors) ) { |
248
|
|
|
|
|
|
|
foreach my $s (@$n) { |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# only links to a switch |
251
|
|
|
|
|
|
|
next unless $s->{type}->{'Switch'}; |
252
|
|
|
|
|
|
|
# only links to a kwnown device |
253
|
|
|
|
|
|
|
next unless $device_set->{ $s->{addr} }; |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
$uplinks{$p} = 1; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# get uplinks from DB and merge them |
260
|
|
|
|
|
|
|
foreach ( $entry->uplinks->all ) { |
261
|
|
|
|
|
|
|
$uplinks{ $_->interface } = 1; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
return \%uplinks; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
#----------------------------------------------------------------------# |
268
|
|
|
|
|
|
|
# # |
269
|
|
|
|
|
|
|
# D a t a u p d a t e # |
270
|
|
|
|
|
|
|
# # |
271
|
|
|
|
|
|
|
#----------------------------------------------------------------------# |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
sub update { |
275
|
|
|
|
|
|
|
my $self = shift; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# check if there is a device object in the DB |
278
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
279
|
|
|
|
|
|
|
unless ($entry) { |
280
|
|
|
|
|
|
|
$self->log->error( "Cannot find device id ", $self->device_id ); |
281
|
|
|
|
|
|
|
return; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# load netwalker info from DB |
285
|
|
|
|
|
|
|
my $nwinfo = $self->nwinfo; |
286
|
|
|
|
|
|
|
unless ($nwinfo) { |
287
|
|
|
|
|
|
|
$self->log->error( "No netwalker info for device", $entry->name ); |
288
|
|
|
|
|
|
|
return; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# try to connect and update nwinfo accordingly |
292
|
|
|
|
|
|
|
$self->log->info( "Connecting to device ", $entry->name, " ", $entry->mng_address ); |
293
|
|
|
|
|
|
|
if ( !$self->source ) { |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# TODO update nwinfo with connection messages |
296
|
|
|
|
|
|
|
$self->reschedule_on_failure(); |
297
|
|
|
|
|
|
|
$nwinfo->offline(1); |
298
|
|
|
|
|
|
|
$nwinfo->update(); |
299
|
|
|
|
|
|
|
return; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
$self->update_device_info; |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# if full_update_interval is elapsed update interface table |
305
|
|
|
|
|
|
|
my $full_update_interval = $self->config->full_update_interval; |
306
|
|
|
|
|
|
|
my $elapsed_full_update = $self->timestamp - $nwinfo->last_full_update; |
307
|
|
|
|
|
|
|
if ( $elapsed_full_update >= $full_update_interval ) { |
308
|
|
|
|
|
|
|
$self->update_if_table; |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# update nwinfo |
311
|
|
|
|
|
|
|
$nwinfo->last_full_update( $self->timestamp ); |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# always update CPD info |
315
|
|
|
|
|
|
|
$self->update_cdp_neighbors; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# update required information |
318
|
|
|
|
|
|
|
$nwinfo->get_mat and $self->update_mat; |
319
|
|
|
|
|
|
|
$nwinfo->get_arp and $self->update_arp_table; |
320
|
|
|
|
|
|
|
$nwinfo->get_vtp and $self->update_vtp_database; |
321
|
|
|
|
|
|
|
$nwinfo->get_dot11 and $self->update_dot11; |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
$nwinfo->get_config and $self->update_config; |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
$self->reschedule_on_success; |
326
|
|
|
|
|
|
|
$nwinfo->last_visited( $self->timestamp ); |
327
|
|
|
|
|
|
|
$nwinfo->offline(0); |
328
|
|
|
|
|
|
|
$nwinfo->update(); |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
$self->log->debug( "Device ", $entry->name, " ", $entry->mng_address, "updated" ); |
331
|
|
|
|
|
|
|
return 1; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub update_device_info { |
336
|
|
|
|
|
|
|
my $self = shift; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
my $source = $self->source; |
339
|
|
|
|
|
|
|
my $dev_entry = $self->device_entry; |
340
|
|
|
|
|
|
|
my $nw_entry = $self->nwinfo; |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
my $name = $source->name; |
343
|
|
|
|
|
|
|
$nw_entry->name($name); |
344
|
|
|
|
|
|
|
if ( defined($name) && $name ne $dev_entry->name ) { |
345
|
|
|
|
|
|
|
if ( $dev_entry->name ) { |
346
|
|
|
|
|
|
|
my $msg = "Name mismatch " . $dev_entry->name . " $name"; |
347
|
|
|
|
|
|
|
$self->log->warn($msg); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
else { |
350
|
|
|
|
|
|
|
$dev_entry->name($name); |
351
|
|
|
|
|
|
|
$dev_entry->update; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
$nw_entry->model( $source->model ); |
356
|
|
|
|
|
|
|
$nw_entry->os( $source->os ); |
357
|
|
|
|
|
|
|
$nw_entry->os_ver( $source->os_ver ); |
358
|
|
|
|
|
|
|
$nw_entry->vendor( $source->vendor ); |
359
|
|
|
|
|
|
|
$nw_entry->serial( $source->serial ); |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
$nw_entry->vtp_domain( $source->vtp_domain ); |
362
|
|
|
|
|
|
|
$nw_entry->boottime( $source->boottime || 0 ); |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
$nw_entry->update; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub update_cdp_neighbors { |
369
|
|
|
|
|
|
|
my $self = shift; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
my $source = $self->source; |
372
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
373
|
|
|
|
|
|
|
my $schema = $self->schema; |
374
|
|
|
|
|
|
|
my $neighbors = $source->neighbors; |
375
|
|
|
|
|
|
|
my $new_dev = 0; |
376
|
|
|
|
|
|
|
my $cdp_entries = 0; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
while ( my ( $p, $n ) = each(%$neighbors) ) { |
379
|
|
|
|
|
|
|
foreach my $s (@$n) { |
380
|
|
|
|
|
|
|
my $from_dev_id = $entry->id; |
381
|
|
|
|
|
|
|
my $to_dev_obj = App::Manoc::IPAddress::IPv4->new( $s->{addr} ); |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
my @cdp_entries = $self->schema->resultset('CDPNeigh')->search( |
384
|
|
|
|
|
|
|
{ |
385
|
|
|
|
|
|
|
from_device_id => $from_dev_id, |
386
|
|
|
|
|
|
|
from_interface => $p, |
387
|
|
|
|
|
|
|
to_device => $to_dev_obj->padded, |
388
|
|
|
|
|
|
|
to_interface => $s->{port}, |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
); |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
unless ( scalar(@cdp_entries) ) { |
393
|
|
|
|
|
|
|
$self->schema->resultset('CDPNeigh')->create( |
394
|
|
|
|
|
|
|
{ |
395
|
|
|
|
|
|
|
from_device_id => $from_dev_id, |
396
|
|
|
|
|
|
|
from_interface => $p, |
397
|
|
|
|
|
|
|
to_device => $to_dev_obj, |
398
|
|
|
|
|
|
|
to_interface => $s->{port}, |
399
|
|
|
|
|
|
|
remote_id => $s->{remote_id}, |
400
|
|
|
|
|
|
|
remote_type => $s->{remote_type}, |
401
|
|
|
|
|
|
|
last_seen => $self->timestamp, |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
); |
404
|
|
|
|
|
|
|
$new_dev++; |
405
|
|
|
|
|
|
|
$cdp_entries++; |
406
|
|
|
|
|
|
|
$self->task_report->add_warning( |
407
|
|
|
|
|
|
|
"New neighbor " . $s->{addr} . " at " . $entry->name ); |
408
|
|
|
|
|
|
|
next; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
my $link = $cdp_entries[0]; |
411
|
|
|
|
|
|
|
$link->last_seen( $self->timestamp ); |
412
|
|
|
|
|
|
|
$link->update; |
413
|
|
|
|
|
|
|
$cdp_entries++; |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
$self->task_report->cdp_entries($cdp_entries); |
417
|
|
|
|
|
|
|
$self->task_report->new_devices($new_dev); |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
sub update_if_table { |
422
|
|
|
|
|
|
|
my $self = shift; |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
my $source = $self->source; |
425
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
426
|
|
|
|
|
|
|
my $iface_filter = $self->config->{iface_filter}; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
my $ifstatus_table = $source->ifstatus_table; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
# delete old infos |
431
|
|
|
|
|
|
|
$entry->ifstatus()->delete; |
432
|
|
|
|
|
|
|
# update |
433
|
|
|
|
|
|
|
foreach my $port ( keys %$ifstatus_table ) { |
434
|
|
|
|
|
|
|
$iface_filter && lc($port) =~ /^(vlan|null|unrouted vlan)/o and next; |
435
|
|
|
|
|
|
|
my $ifstatus = $ifstatus_table->{$port}; |
436
|
|
|
|
|
|
|
$entry->add_to_ifstatus( |
437
|
|
|
|
|
|
|
{ |
438
|
|
|
|
|
|
|
interface => $port, |
439
|
|
|
|
|
|
|
%$ifstatus |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
); |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub update_mat { |
447
|
|
|
|
|
|
|
my $self = shift; |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
my $source = $self->source; |
450
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
451
|
|
|
|
|
|
|
my $schema = $self->schema; |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
my $uplinks = $self->uplinks; |
454
|
|
|
|
|
|
|
$self->log->debug( "device uplinks: ", join( ",", keys %$uplinks ) ); |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
my $timestamp = $self->timestamp; |
457
|
|
|
|
|
|
|
my $device_id = $self->device_id; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
my $ignore_portchannel = $self->config->{ignore_portchannel}; |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
my $mat = $source->mat() or return; |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
my $mat_count = 0; |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
while ( my ( $vlan, $entries ) = each(%$mat) ) { |
466
|
|
|
|
|
|
|
$self->log->debug("updating mat vlan $vlan"); |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
if ( $vlan eq 'default' ) { |
469
|
|
|
|
|
|
|
$vlan = $self->native_vlan; |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
while ( my ( $m, $p ) = each %$entries ) { |
472
|
|
|
|
|
|
|
next if $uplinks->{$p}; |
473
|
|
|
|
|
|
|
next if $ignore_portchannel && lc($p) =~ /^port-channel/; |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
$self->schema->resultset('Mat')->register_tuple( |
476
|
|
|
|
|
|
|
macaddr => $m, |
477
|
|
|
|
|
|
|
device_id => $device_id, |
478
|
|
|
|
|
|
|
interface => $p, |
479
|
|
|
|
|
|
|
timestamp => $timestamp, |
480
|
|
|
|
|
|
|
vlan => $vlan, |
481
|
|
|
|
|
|
|
); |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
} # end of entries loop |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
} # end of mat loop |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
$self->task_report->mat_entries($mat_count); |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
sub update_vtp_database { |
492
|
|
|
|
|
|
|
my $self = shift; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
my $source = $self->source; |
495
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
my $vlan_db = $source->vtp_database; |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
$self->log->info( "getting vtp info from ", $entry->mng_address ); |
500
|
|
|
|
|
|
|
if ( !defined($vlan_db) ) { |
501
|
|
|
|
|
|
|
$self->log->error("cannot retrieve vtp info"); |
502
|
|
|
|
|
|
|
$self->task_report->add_error("cannot retrieve vtp info"); |
503
|
|
|
|
|
|
|
return; |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
$self->task_report->add_warning("Vtp Vlan DB up to date"); |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
my $rs = $self->schema->resultset('VlanVtp'); |
509
|
|
|
|
|
|
|
$rs->delete(); |
510
|
|
|
|
|
|
|
while ( my ( $id, $name ) = each(%$vlan_db) ) { |
511
|
|
|
|
|
|
|
$rs->find_or_create( |
512
|
|
|
|
|
|
|
{ |
513
|
|
|
|
|
|
|
'id' => $id, |
514
|
|
|
|
|
|
|
'name' => $name |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
); |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
my $vtp_last_update = |
519
|
|
|
|
|
|
|
$self->schema->resultset('System')->find_or_create("netwalker.vtp_update"); |
520
|
|
|
|
|
|
|
$vtp_last_update->value( $self->timestamp ); |
521
|
|
|
|
|
|
|
$vtp_last_update->update(); |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
sub update_arp_table { |
527
|
|
|
|
|
|
|
my $self = shift; |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
my $source = $self->source; |
530
|
|
|
|
|
|
|
my $entry = $self->device_entry; |
531
|
|
|
|
|
|
|
my $timestamp = $self->timestamp; |
532
|
|
|
|
|
|
|
my $vlan = $self->arp_vlan; |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
$self->log->debug("Fetching arp table "); |
535
|
|
|
|
|
|
|
my $arp_table = $source->arp_table; |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
# TODO log error |
538
|
|
|
|
|
|
|
$arp_table or return; |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
my $arp_count = 0; |
541
|
|
|
|
|
|
|
my ( $ip_addr, $mac_addr ); |
542
|
|
|
|
|
|
|
while ( ( $ip_addr, $mac_addr ) = each(%$arp_table) ) { |
543
|
|
|
|
|
|
|
$self->log->debug( sprintf( "Arp table: %15s at %17s\n", $ip_addr, $mac_addr ) ); |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
$self->schema->resultset('Arp')->register_tuple( |
546
|
|
|
|
|
|
|
ipaddr => $ip_addr, |
547
|
|
|
|
|
|
|
macaddr => $mac_addr, |
548
|
|
|
|
|
|
|
vlan => $vlan, |
549
|
|
|
|
|
|
|
timestamp => $timestamp, |
550
|
|
|
|
|
|
|
); |
551
|
|
|
|
|
|
|
$arp_count++; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
$self->task_report->arp_entries($arp_count); |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
sub update_config { |
559
|
|
|
|
|
|
|
my $self = shift; |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
my $device_entry = $self->device_entry; |
562
|
|
|
|
|
|
|
my $config_date = $device_entry->get_config_date; |
563
|
|
|
|
|
|
|
my $update_interval = $self->config->config_update_interval; |
564
|
|
|
|
|
|
|
my $timestamp = $self->timestamp; |
565
|
|
|
|
|
|
|
my $config_source = $self->config_source; |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
unless ( $config_source->does('App::Manoc::ManifoldRole::FetchConfig') ) { |
568
|
|
|
|
|
|
|
$self->log->warnings("Config source does not support fetchconfig"); |
569
|
|
|
|
|
|
|
return; |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
if ( !defined($config_date) || $timestamp > $config_date + $update_interval ) { |
573
|
|
|
|
|
|
|
$self->log->info( "Fetching configuration from ", $device_entry->mng_address ); |
574
|
|
|
|
|
|
|
my $config_text = $config_source->configuration; |
575
|
|
|
|
|
|
|
if ( !defined($config_text) ) { |
576
|
|
|
|
|
|
|
$self->log->error( "Cannot fetch configuration from ", $device_entry->mng_address ); |
577
|
|
|
|
|
|
|
return; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
$self->device_entry->update_config( $config_text, $timestamp ); |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
1; |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# Local Variables: |
587
|
|
|
|
|
|
|
# mode: cperl |
588
|
|
|
|
|
|
|
# indent-tabs-mode: nil |
589
|
|
|
|
|
|
|
# cperl-indent-level: 4 |
590
|
|
|
|
|
|
|
# cperl-indent-parens-as-block: t |
591
|
|
|
|
|
|
|
# End: |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
__END__ |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=pod |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=head1 NAME |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
App::Manoc::Netwalker::Poller::DeviceTask - Device poller task |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
=head1 VERSION |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
version 2.99.2 |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
=head2 device_id |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
The id in Manoc DB of the device to update. |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
=head2 device_entry |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
The Device row in Manoc DB identified by C<device_id>. |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=head2 nwinfo |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
NWInfo associated to the current C<device_entry>. |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=head2 device_set |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
A set (hash) of all mng_address known to Manoc used to to discover |
622
|
|
|
|
|
|
|
neighbors and uplinks. |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
=head2 source |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
The source for information about the device: a connected Manifold object. |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=head2 config_source |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
The Manifold to use as a source for device configuration backup. |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=head2 task_report |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=head2 uplinks |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
=head2 native_vlan |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
=head2 arp_vlan |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
=head1 METHODS |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
=head2 update |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
Update device information |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
=head2 update_device_info |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
Updates device information (model, os, vendor) in C<nwinfo>. |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
=head2 update_cdp_neighbors |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
Update neighbor list in CDPNeigh |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
=head2 update_if_table |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
Update interface information. |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=head2 update_mat |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
Update mac address table. |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=head2 update_vtp_database |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
=head2 update_arp_table |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
=head2 update_config |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=head1 AUTHORS |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
=over 4 |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=item * |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
Gabriele Mambrini <gmambro@cpan.org> |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=item * |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
Enrico Liguori |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=back |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
This software is copyright (c) 2017 by Gabriele Mambrini. |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
687
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
=cut |