line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mnet; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# version number used by Makefile.PL |
4
|
|
|
|
|
|
|
# these should be set to "dev", expect when creating a new release |
5
|
|
|
|
|
|
|
# refer to developer build notes in Makefile.PL for more info |
6
|
|
|
|
|
|
|
our $VERSION = "5.24-TRIAL01"; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Mnet - Testable network automation and reporting |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# sample.pl script to report Loopback0 ip on cisco devices |
15
|
|
|
|
|
|
|
# |
16
|
|
|
|
|
|
|
# demonstrates typical use of all major Mnet modules |
17
|
|
|
|
|
|
|
# |
18
|
|
|
|
|
|
|
# --help to list all options, also --help |
19
|
|
|
|
|
|
|
# --device to connect to device with logging |
20
|
|
|
|
|
|
|
# --username and --password should be set if necessary |
21
|
|
|
|
|
|
|
# --debug to generate extra detailed logging outputs |
22
|
|
|
|
|
|
|
# --batch to process multiple --device lines |
23
|
|
|
|
|
|
|
# --report csv: to create an output csv file |
24
|
|
|
|
|
|
|
# --record to create replayable test file |
25
|
|
|
|
|
|
|
# --test --replay for regression test output |
26
|
|
|
|
|
|
|
# |
27
|
|
|
|
|
|
|
# refer to various Mnet modules' perldoc for more info |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# load needed modules |
30
|
|
|
|
|
|
|
use warnings; |
31
|
|
|
|
|
|
|
use strict; |
32
|
|
|
|
|
|
|
use Mnet::Batch; |
33
|
|
|
|
|
|
|
use Mnet::Expect::Cli::Ios; |
34
|
|
|
|
|
|
|
use Mnet::Log qw(DEBUG INFO WARN FATAL); |
35
|
|
|
|
|
|
|
use Mnet::Opts::Cli; |
36
|
|
|
|
|
|
|
use Mnet::Report::Table; |
37
|
|
|
|
|
|
|
use Mnet::Stanza; |
38
|
|
|
|
|
|
|
use Mnet::Test; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# define --device, --username, --password, and --report cli options |
41
|
|
|
|
|
|
|
# record, redact, default, and help option attributes are shown |
42
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "device=s", record => 1 }); |
43
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "username=s" }); |
44
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "password=s", redact => 1 }); |
45
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "report=s", default => undef, |
46
|
|
|
|
|
|
|
help_tip => "specify report output, csv, json, sql, etc", |
47
|
|
|
|
|
|
|
help_text => "perldoc Mnet::Report::Table for more info", |
48
|
|
|
|
|
|
|
}); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# create object to access command line options and Mnet env variable |
51
|
|
|
|
|
|
|
# export Mnet="--password ''" env var from secure file |
52
|
|
|
|
|
|
|
my $cli = Mnet::Opts::Cli->new("Mnet"); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# define output --report table, will include first of any errors |
55
|
|
|
|
|
|
|
# use --report cli opt to output data as csv, json, or sql, etc |
56
|
|
|
|
|
|
|
my $report = Mnet::Report::Table->new({ |
57
|
|
|
|
|
|
|
columns => [ |
58
|
|
|
|
|
|
|
device => "string", |
59
|
|
|
|
|
|
|
error => "error", |
60
|
|
|
|
|
|
|
ip => "string", |
61
|
|
|
|
|
|
|
], |
62
|
|
|
|
|
|
|
output => $cli->report, |
63
|
|
|
|
|
|
|
}); |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# fork children if in --batch mode, cli opts set for current child |
66
|
|
|
|
|
|
|
# process one device or ten thousand devices with the same script |
67
|
|
|
|
|
|
|
# exit --batch parent process here when finished forking children |
68
|
|
|
|
|
|
|
$cli = Mnet::Batch::fork($cli); |
69
|
|
|
|
|
|
|
exit if not $cli; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# output report row for device error if script dies before finishing |
72
|
|
|
|
|
|
|
$report->row_on_error({ device => $cli->device }); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# call logging function, also create log object for current --device |
75
|
|
|
|
|
|
|
FATAL("missing --device") if not $cli->device; |
76
|
|
|
|
|
|
|
my $log = Mnet::Log->new({ log_id => $cli->device }); |
77
|
|
|
|
|
|
|
$log->info("processing device"); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# uncomment the push commands below to skip ssh host key checks |
80
|
|
|
|
|
|
|
# ideally host keys are already accepted, perhaps via manual ssh |
81
|
|
|
|
|
|
|
my @ssh = qw(ssh); |
82
|
|
|
|
|
|
|
#push @ssh, qw(-o StrictHostKeyChecking=no); |
83
|
|
|
|
|
|
|
#push @ssh, qw(-o UserKnownHostsFile=/dev/null); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# create an expect ssh session to current --device |
86
|
|
|
|
|
|
|
# log ssh login/auth prompts as info, instead of default debug |
87
|
|
|
|
|
|
|
# password_in set to prompt for password if --password opt not set |
88
|
|
|
|
|
|
|
# for non-ios devices refer to perldoc Mnet::Expect::Cli |
89
|
|
|
|
|
|
|
my $ssh = Mnet::Expect::Cli::Ios->new({ |
90
|
|
|
|
|
|
|
spawn => [ @ssh, "$cli->{username}\@$cli->{device}" ], |
91
|
|
|
|
|
|
|
log_id => $cli->{device}, |
92
|
|
|
|
|
|
|
log_login => "info", |
93
|
|
|
|
|
|
|
password => $cli->password, |
94
|
|
|
|
|
|
|
password_in => 1, |
95
|
|
|
|
|
|
|
}); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# retrieve ios config using ssh command, warn otherwise |
98
|
|
|
|
|
|
|
my $config = $ssh->command("show running-config"); |
99
|
|
|
|
|
|
|
WARN("unable to read config") if not $config; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# parse interface loopack0 stanza from device config |
102
|
|
|
|
|
|
|
# returns int loop0 line and lines indented under int loop0 |
103
|
|
|
|
|
|
|
# see perldoc Mnet::Stanza for more ios config templating info |
104
|
|
|
|
|
|
|
my $loop = Mnet::Stanza::parse($config, qr/^interface Loopback0$/); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# parse primary ip address from loopback config stanza |
107
|
|
|
|
|
|
|
my $ip = undef; |
108
|
|
|
|
|
|
|
$ip = $1 if $loop and $loop =~ /^ ip address (\S+) \S+$/m; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# report on parsed loopback0 interface ip addres |
111
|
|
|
|
|
|
|
$report->row({ device => $cli->device, ip => $ip }); |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# finished |
114
|
|
|
|
|
|
|
exit; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 DESCRIPTION |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
The L modules are for perl programmers who want to create testable |
119
|
|
|
|
|
|
|
network automation and/or reporting scripts as simply as possible. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
The main features are: |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=over |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=item * |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
L module can record and replay L script options, connected |
128
|
|
|
|
|
|
|
expect sessions, and compare outputs, speeding development and allowing for |
129
|
|
|
|
|
|
|
integration and regression testing of complex automation scripts. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=item * |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
L and L modules for reliable |
134
|
|
|
|
|
|
|
automation of cisco ios and other command line sessions, including |
135
|
|
|
|
|
|
|
authentication and command prompt handling. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item * |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
L module for templated config parsing and generation on cisco ios |
140
|
|
|
|
|
|
|
devices and other similar indented stanza text data. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item * |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
L can run automation scripts in batch mode to concurrently process |
145
|
|
|
|
|
|
|
a list of devices, using command line arguments and a device list file. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item * |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
L and L modules facilitate easy log, debug, alert and |
150
|
|
|
|
|
|
|
error output from automation scripts, along with redirection to per-device |
151
|
|
|
|
|
|
|
output files. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=item * |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
L module for config settings via command line, environment |
156
|
|
|
|
|
|
|
variable, and/or batch scripts, with help, tips, and password redaction. |
157
|
|
|
|
|
|
|
device list files. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=item * |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
L module for aggregating report data from scripts, |
162
|
|
|
|
|
|
|
supporting output in formats such as csv, json, and sql. |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=back |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Most of the L sub-modules can be used independently of each other, |
167
|
|
|
|
|
|
|
unless otherwise noted. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Refer to the individual modules listed in the SEE ALSO section below |
170
|
|
|
|
|
|
|
for more detail. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head1 INSTALLATION |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
The L perl modules should work in just about any unix perl environment. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
The latest release can be installed from CPAN |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
cpan install Mnet |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
Or download and install from L |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
tar -xzf Mnet-X.y.tar.gz |
183
|
|
|
|
|
|
|
cd Mnet-X.y |
184
|
|
|
|
|
|
|
perl Makefile.PL # INSTALL_BASE=/specify/path |
185
|
|
|
|
|
|
|
make test |
186
|
|
|
|
|
|
|
make install |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Check your PERL5LIB environment variable if INSTALL_BASE was used, or if you |
189
|
|
|
|
|
|
|
copied the lib/Mnet directory somewhere instead of using the included |
190
|
|
|
|
|
|
|
Makefile.PL script. Refer to L for more information |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head1 FAQ |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Below are answers to some frequently asked questions. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head2 How should I get started? |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Copy the sample script code from the SYNOPSIS above to a new .pl file, read |
199
|
|
|
|
|
|
|
through the comments, make changes as necessary, use the --debug cli option to |
200
|
|
|
|
|
|
|
troubleshoot execution. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head2 What's the easiest way to get more log output? |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Use both the L and L modules in your script |
205
|
|
|
|
|
|
|
for more output, mostly from other Mnet modules unless you add L |
206
|
|
|
|
|
|
|
calls, which are a compatible subset of log4perl calls, to your script. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head2 How should passwords be secured? |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
Environment variables should be used to provide passwords for scripts, not |
211
|
|
|
|
|
|
|
command line options. Command line options can be seen in the system process |
212
|
|
|
|
|
|
|
list by other users. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
The L new method allows a named environment variable to be |
215
|
|
|
|
|
|
|
specified that will also be parsed for command line options. Your script can |
216
|
|
|
|
|
|
|
be called from a shell script containing authentication, which is accessible |
217
|
|
|
|
|
|
|
only to authorized users, such as in the example below: |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#!/bin/sh |
220
|
|
|
|
|
|
|
# sample.sh script, chmod 700 to restrict access to current user |
221
|
|
|
|
|
|
|
# works with Mnet::Opts calls in above SYNOPISIS sample.pl script |
222
|
|
|
|
|
|
|
# "$@" passes throuh all command line options, modify as needed |
223
|
|
|
|
|
|
|
export Mnet='--username --password ' |
224
|
|
|
|
|
|
|
perl -- sample.pl "$@" |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
The L module define function has a redact property that should |
227
|
|
|
|
|
|
|
be set for password options so that the value of the option is value is always |
228
|
|
|
|
|
|
|
redacted form L outputs. |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
Also note that the L module log_expect method is used by the |
231
|
|
|
|
|
|
|
L modules to temporarily disable expect session logging |
232
|
|
|
|
|
|
|
during password entry. Any user code bypassing the L |
233
|
|
|
|
|
|
|
modules to send passwords directly, using the expect method in the |
234
|
|
|
|
|
|
|
L module, may need to do the same. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=head2 Why should I use the Mnet::Expect module? |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
The L module works with the L and L |
239
|
|
|
|
|
|
|
modules, for easy logging of normal L module activity, with extra |
240
|
|
|
|
|
|
|
options for logging, debugging, raw pty, and session tty rows and columns. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
However, you still have to handle all the expect session details, including |
243
|
|
|
|
|
|
|
send and expect calls for logging in, detecting of command prompts, capturing |
244
|
|
|
|
|
|
|
output, etc. It's easier to use the L module which handles |
245
|
|
|
|
|
|
|
all of this, if you can. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head2 Why should I use the Mnet::Expect::Cli module? |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
The L module makes it easy to login and obtain outputs from |
250
|
|
|
|
|
|
|
command line interfaces, like ssh. This module builds on the L |
251
|
|
|
|
|
|
|
module mentioned above, adding features to handle a variety of typical username |
252
|
|
|
|
|
|
|
and password prompts, command prompts, pagination prompts on long outputs, and |
253
|
|
|
|
|
|
|
caching of session command output. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
This module also works with the L module, allowing expect session |
256
|
|
|
|
|
|
|
activity to be recorded and replayed while offline. This can be of tremendous |
257
|
|
|
|
|
|
|
value, both during development, and for sustainability. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Refer also the the L module mentioned below, which has |
260
|
|
|
|
|
|
|
a couple of features relevant when working with cisco ios and other similar |
261
|
|
|
|
|
|
|
devices. |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=head2 Why should I use the Mnet::Expect::Cli::Ios module? |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
The L builds on the L module |
266
|
|
|
|
|
|
|
mentioned above, also handling enable mode authentication, the prompt changes |
267
|
|
|
|
|
|
|
going from user to enable mode, and the prompt changes in configuration modes. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=head1 AUTHOR |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
The L perl distribution has been created and is maintained by Mike Menza. |
272
|
|
|
|
|
|
|
Feedback and bug reports are welcome, feel free to contact Mike via email |
273
|
|
|
|
|
|
|
at with any comments or questions. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Copyright 2006, 2013-2022 Michael J. Menza Jr. |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
L is free software: you can redistribute it and/or modify it under |
280
|
|
|
|
|
|
|
the terms of the GNU General Public License as published by the Free Software |
281
|
|
|
|
|
|
|
Foundation, either version 3 of the License, or (at your option) any later |
282
|
|
|
|
|
|
|
version. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY |
285
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
286
|
|
|
|
|
|
|
PARTICULAR PURPOSE. See the GNU General Public License for more details. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with |
289
|
|
|
|
|
|
|
this program. If not, see L |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=head1 SEE ALSO |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
L |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
L |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
L |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
L |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
L |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
L |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
L |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
L |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=cut |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# required modules |
312
|
|
|
|
|
|
|
# note that cpan complians if use strict is missing |
313
|
|
|
|
|
|
|
# perl 5.10 or higer required for all Mnet modules, they all use this module |
314
|
|
|
|
|
|
|
# perl 5.10 may be requried for tie to capture stdout and stderr |
315
|
|
|
|
|
|
|
# perl 5.8.9 warning: use of "shift" without parentheses is ambiguous |
316
|
34
|
|
|
34
|
|
230
|
use warnings; |
|
34
|
|
|
|
|
61
|
|
|
34
|
|
|
|
|
1170
|
|
317
|
34
|
|
|
34
|
|
194
|
use strict; |
|
34
|
|
|
|
|
86
|
|
|
34
|
|
|
|
|
662
|
|
318
|
34
|
|
|
34
|
|
827
|
use 5.010; |
|
34
|
|
|
|
|
127
|
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# normal end of package |
321
|
|
|
|
|
|
|
1; |
322
|
|
|
|
|
|
|
|