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.23-TRIAL01"; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Mnet - Testable network automation and reporting |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# sample 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, or --help |
19
|
|
|
|
|
|
|
# --device to connect to device with logging |
20
|
|
|
|
|
|
|
# --username and --password should be set if necessary |
21
|
|
|
|
|
|
|
# --batch to process multiple --device lines |
22
|
|
|
|
|
|
|
# --report csv: to create an output csv file |
23
|
|
|
|
|
|
|
# --record to create replayable test file |
24
|
|
|
|
|
|
|
# --test --replay for regression test output |
25
|
|
|
|
|
|
|
# |
26
|
|
|
|
|
|
|
# refer to various Mnet modules' perldoc for more info |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# load modules |
29
|
|
|
|
|
|
|
use warnings; |
30
|
|
|
|
|
|
|
use strict; |
31
|
|
|
|
|
|
|
use Mnet::Batch; |
32
|
|
|
|
|
|
|
use Mnet::Expect::Cli::Ios; |
33
|
|
|
|
|
|
|
use Mnet::Log qw(DEBUG INFO WARN FATAL); |
34
|
|
|
|
|
|
|
use Mnet::Opts::Cli; |
35
|
|
|
|
|
|
|
use Mnet::Report::Table; |
36
|
|
|
|
|
|
|
use Mnet::Stanza; |
37
|
|
|
|
|
|
|
use Mnet::Test; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# define --device, --username, --password, and --report cli options |
40
|
|
|
|
|
|
|
# record, redact, default, and help option attributes are shown |
41
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "device=s", record => 1 }); |
42
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "username=s" }); |
43
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "password=s", redact => 1 }); |
44
|
|
|
|
|
|
|
Mnet::Opts::Cli::define({ getopt => "report=s", default => undef, |
45
|
|
|
|
|
|
|
help_tip => "specify report output, csv, json, sql, etc", |
46
|
|
|
|
|
|
|
help_text => "perldoc Mnet::Report::Table for more info", |
47
|
|
|
|
|
|
|
}); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# create object to access command line options and Mnet env variable |
50
|
|
|
|
|
|
|
# export Mnet="--password ''" env var from secure file |
51
|
|
|
|
|
|
|
my $cli = Mnet::Opts::Cli->new("Mnet"); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# define output --report table, will include first of any errors |
54
|
|
|
|
|
|
|
# use --report cli opt to output data as csv, json, or sql, etc |
55
|
|
|
|
|
|
|
my $report = Mnet::Report::Table->new({ |
56
|
|
|
|
|
|
|
columns => [ |
57
|
|
|
|
|
|
|
device => "string", |
58
|
|
|
|
|
|
|
error => "error", |
59
|
|
|
|
|
|
|
ip => "string", |
60
|
|
|
|
|
|
|
], |
61
|
|
|
|
|
|
|
output => $cli->report, |
62
|
|
|
|
|
|
|
}); |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# fork children if in --batch mode, cli opts set for current child |
65
|
|
|
|
|
|
|
# process one device or ten thousand devices with the same script |
66
|
|
|
|
|
|
|
# exit --batch parent process here when finished forking children |
67
|
|
|
|
|
|
|
$cli = Mnet::Batch::fork($cli); |
68
|
|
|
|
|
|
|
exit if not $cli; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# output report row for device error if script dies before finishing |
71
|
|
|
|
|
|
|
$report->row_on_error({ device => $cli->device }); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# call logging function, also create log object for current --device |
74
|
|
|
|
|
|
|
FATAL("missing --device") if not $cli->device; |
75
|
|
|
|
|
|
|
my $log = Mnet::Log->new({ log_id => $cli->device }); |
76
|
|
|
|
|
|
|
$log->info("processing device"); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# uncomment the push commands below to skip ssh host key checks |
79
|
|
|
|
|
|
|
# ideally host keys are already accepted, perhaps via manual ssh |
80
|
|
|
|
|
|
|
my @ssh = qw(ssh); |
81
|
|
|
|
|
|
|
#push @ssh, qw(-o StrictHostKeyChecking=no); |
82
|
|
|
|
|
|
|
#push @ssh, qw(-o UserKnownHostsFile=/dev/null); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# create an expect ssh session to current --device |
85
|
|
|
|
|
|
|
# log ssh login/auth prompts as info, instead of default debug |
86
|
|
|
|
|
|
|
# password_in set to prompt for password if --password opt not set |
87
|
|
|
|
|
|
|
# for non-ios devices refer to perldoc Mnet::Expect::Cli |
88
|
|
|
|
|
|
|
my $ssh = Mnet::Expect::Cli::Ios->new({ |
89
|
|
|
|
|
|
|
spawn => [ @ssh, "$cli->{username}\@$cli->{device}" ], |
90
|
|
|
|
|
|
|
log_id => $cli->{device}, |
91
|
|
|
|
|
|
|
log_login => "info", |
92
|
|
|
|
|
|
|
password => $cli->password, |
93
|
|
|
|
|
|
|
password_in => 1, |
94
|
|
|
|
|
|
|
}); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# retrieve ios config using ssh command, warn otherwise |
97
|
|
|
|
|
|
|
my $config = $ssh->command("show running-config"); |
98
|
|
|
|
|
|
|
WARN("unable to read config") if not $config; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# parse interface loopack0 stanza from device config |
101
|
|
|
|
|
|
|
# returns int loop0 line and lines indented under int loop0 |
102
|
|
|
|
|
|
|
# see perldoc Mnet::Stanza for more ios config templating info |
103
|
|
|
|
|
|
|
my $loop = Mnet::Stanza::parse($config, qr/^interface Loopback0$/); |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# parse primary ip address from loopback config stanza |
106
|
|
|
|
|
|
|
my $ip = undef; |
107
|
|
|
|
|
|
|
$ip = $1 if $loop and $loop =~ /^ ip address (\S+) \S+$/m; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# report on parsed loopback0 interface ip addres |
110
|
|
|
|
|
|
|
$report->row({ device => $cli->device, ip => $ip }); |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# finished |
113
|
|
|
|
|
|
|
exit; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 DESCRIPTION |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
The L modules are for perl programmers who want to create testable |
118
|
|
|
|
|
|
|
network automation and/or reporting scripts as simply as possible. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
The main features are: |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=over |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=item * |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
L module can record and replay L script options, connected |
127
|
|
|
|
|
|
|
expect sessions, and compare outputs, speeding development and allowing for |
128
|
|
|
|
|
|
|
integration and regression testing of complex automation scripts. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=item * |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
L and L modules for reliable |
133
|
|
|
|
|
|
|
automation of cisco ios and other command line sessions, including |
134
|
|
|
|
|
|
|
authentication and command prompt handling. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item * |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
L module for templated config parsing and generation on cisco ios |
139
|
|
|
|
|
|
|
devices and other similar indented stanza text data. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item * |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
L can run automation scripts in batch mode to concurrently process |
144
|
|
|
|
|
|
|
a list of devices, using command line arguments and a device list file. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item * |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
L can facilitate easy log, debug, alert and error output from |
149
|
|
|
|
|
|
|
automation scripts, outputs can be redirected to per-device files. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item * |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
L module for config settings via command line, environment |
154
|
|
|
|
|
|
|
variable, and/or batch scripts, with help, tips, and password redaction. |
155
|
|
|
|
|
|
|
device list files. |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=item * |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
L module for aggregating report data from scripts, |
160
|
|
|
|
|
|
|
supporting output in formats such as csv, json, and sql. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=back |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Most of the L sub-modules can be used independently of each other, |
165
|
|
|
|
|
|
|
unless otherwise noted. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Refer to the individual modules listed in the SEE ALSO section below |
168
|
|
|
|
|
|
|
for more detail. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=head1 INSTALLATION |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
The L perl modules should work in just about any unix perl environment. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
The latest release can be installed from CPAN |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
cpan install Mnet |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
Or download and install from L |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
tar -xzf Mnet-X.y.tar.gz |
181
|
|
|
|
|
|
|
cd Mnet-X.y |
182
|
|
|
|
|
|
|
perl Makefile.PL # INSTALL_BASE=/specify/path |
183
|
|
|
|
|
|
|
make test |
184
|
|
|
|
|
|
|
make install |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
Check your PERL5LIB environment variable if INSTALL_BASE was used, or if you |
187
|
|
|
|
|
|
|
copied the lib/Mnet directory somewhere instead of using the included |
188
|
|
|
|
|
|
|
Makefile.PL script. Refer to L for more information |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 AUTHOR |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
The L perl distribution has been created and is maintained by Mike Menza. |
193
|
|
|
|
|
|
|
Feedback and bug reports are welcome, feel free to contact Mike via email |
194
|
|
|
|
|
|
|
at with any comments or questions. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Copyright 2006, 2013-2021 Michael J. Menza Jr. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
L is free software: you can redistribute it and/or modify it under |
201
|
|
|
|
|
|
|
the terms of the GNU General Public License as published by the Free Software |
202
|
|
|
|
|
|
|
Foundation, either version 3 of the License, or (at your option) any later |
203
|
|
|
|
|
|
|
version. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY |
206
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
207
|
|
|
|
|
|
|
PARTICULAR PURPOSE. See the GNU General Public License for more details. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with |
210
|
|
|
|
|
|
|
this program. If not, see L |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head1 SEE ALSO |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
L |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
L |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
L |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
L |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
L |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
L |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
L |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
L |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=cut |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# required modules |
233
|
|
|
|
|
|
|
# note that cpan complians if use strict is missing |
234
|
|
|
|
|
|
|
# perl 5.10 or higer required for all Mnet modules, they all use this module |
235
|
|
|
|
|
|
|
# perl 5.10 may be requried for tie to capture stdout and stderr |
236
|
|
|
|
|
|
|
# perl 5.8.9 warning: use of "shift" without parentheses is ambiguous |
237
|
34
|
|
|
34
|
|
236
|
use warnings; |
|
34
|
|
|
|
|
58
|
|
|
34
|
|
|
|
|
1155
|
|
238
|
34
|
|
|
34
|
|
177
|
use strict; |
|
34
|
|
|
|
|
62
|
|
|
34
|
|
|
|
|
646
|
|
239
|
34
|
|
|
34
|
|
782
|
use 5.010; |
|
34
|
|
|
|
|
137
|
|
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# normal end of package |
242
|
|
|
|
|
|
|
1; |
243
|
|
|
|
|
|
|
|