expect4r 0.0.2.dev → 0.0.3.dev
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +76 -22
- data/lib/expect/io.rb +103 -31
- data/lib/expect4r.rb +2 -0
- data/lib/misc/shell.rb +40 -4
- data/lib/router/cisco/common/common.rb +10 -0
- data/lib/router/cisco/common/ping.rb +23 -8
- data/lib/router/cisco/ios/ios.rb +8 -3
- data/lib/router/cisco/ios/modes.rb +10 -0
- data/lib/router/cisco/iox/iox.rb +7 -3
- data/lib/router/cisco/iox/modes.rb +13 -0
- data/lib/router/cisco/iox/ping.rb +55 -0
- data/lib/router/common.rb +0 -24
- data/lib/router/juniper/junos/junos.rb +7 -4
- data/lib/router/juniper/junos/modes.rb +28 -1
- data/lib/router/juniper/junos/ping.rb +18 -0
- data/lib/router/modes.rb +15 -0
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
= Expect4r -- Interact with Cisco IOS, IOS-XR, and Juniper JUNOS CLI.
|
2
|
+
|
1
3
|
Expect4r is a library that enables a ruby program to 'talk' to routers following a written ruby script.
|
2
4
|
You talk to routers by connecting to them using ssh or telnet and send exec or config command and collect router output than can be parsed using ruby.
|
3
5
|
|
@@ -21,16 +23,21 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
|
|
21
23
|
interface loopback0
|
22
24
|
shutdown
|
23
25
|
}
|
24
|
-
|
25
|
-
|
26
|
+
|
26
27
|
iox.config
|
27
28
|
iox.exp_send 'interface GigabitEthernet0/2/0/0'
|
28
29
|
iox.exp_send 'desc to switch port 13'
|
29
30
|
iox.exp_send 'ipv4 address 190.0.0.9 255.255.255.252'
|
30
31
|
iox.exp_send 'no shut'
|
31
32
|
iox.commit
|
32
|
-
|
33
|
-
|
33
|
+
|
34
|
+
iox.config %|
|
35
|
+
interface GigabitEthernet0/2/0/0
|
36
|
+
desc to switch port 13'
|
37
|
+
ipv4 address 190.0.0.9 255.255.255.252'
|
38
|
+
no shut'
|
39
|
+
|
|
40
|
+
|
34
41
|
j.config %{
|
35
42
|
edit logical-router Orleans protocols bgp
|
36
43
|
edit group session-to-200
|
@@ -41,7 +48,6 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
|
|
41
48
|
|
42
49
|
* exec commands
|
43
50
|
|
44
|
-
|
45
51
|
j.exec 'set cli screen-length 0'
|
46
52
|
|
47
53
|
iox.exec "terminal len 0\nterminal width 0"
|
@@ -54,7 +60,6 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
|
|
54
60
|
|
55
61
|
* interact with CLI.
|
56
62
|
|
57
|
-
|
58
63
|
irb> r.interact
|
59
64
|
|
60
65
|
#
|
@@ -98,13 +103,13 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
|
|
98
103
|
Parsing a response becomes a matter of iterating an array using the
|
99
104
|
Arrays's enumerator methods such as find, find_all ...
|
100
105
|
|
101
|
-
irb
|
102
|
-
irb
|
103
|
-
irb
|
104
|
-
irb
|
106
|
+
irb> output = ts.exec %{
|
107
|
+
irb" show terminal | include History
|
108
|
+
irb" show line | include AUX
|
109
|
+
irb" }
|
105
110
|
=> [
|
106
|
-
["show terminal | include History", "History is enabled, history size is 10.", "
|
107
|
-
["show line | include AUX", " 17 AUX 9600/9600 - 0/0 -", "
|
111
|
+
["show terminal | include History", "History is enabled, history size is 10.", "ios#"],
|
112
|
+
["show line | include AUX", " 17 AUX 9600/9600 - 0/0 -", "ios#"]
|
108
113
|
]
|
109
114
|
|
110
115
|
output[0] contains output for 1st command 'show terminal'.
|
@@ -113,14 +118,63 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
|
|
113
118
|
output[n-1] contains output for nth command.
|
114
119
|
|
115
120
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
121
|
+
* Ping
|
122
|
+
|
123
|
+
irb(main):016:0> ios.ping '192.168.1.23', :count=> 100, :pct_success=>90, :sweep_max_size=> 1500
|
124
|
+
=> [ 99, [146148, 146500],
|
125
|
+
[["ping",
|
126
|
+
"Protocol [ip]: ", "",
|
127
|
+
"Target IP address: ", "192.168.1.23",
|
128
|
+
"Repeat count [5]: ", "100",
|
129
|
+
"Datagram size [100]: ", "",
|
130
|
+
"Timeout in seconds [2]: ", "",
|
131
|
+
"Extended commands [n]: ", "",
|
132
|
+
"Sweep range of sizes [n]: ", "yes",
|
133
|
+
"Sweep min size [36]: ", "",
|
134
|
+
"Sweep max size [18024]: ", "1500",
|
135
|
+
"Sweep interval [1]: ", "",
|
136
|
+
"Type escape sequence to abort.",
|
137
|
+
"Sending 146500, [36..1500]-byte ICMP Echos to 192.168.1.23, timeout is 2 seconds:",
|
138
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!.!!!!!!!!.!!!!!!!!!!!!!!!!!!!",
|
139
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
140
|
+
...
|
141
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
142
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
143
|
+
"Success rate is 99 percent (146148/146500), round-trip min/avg/max = 1/7/924 ms",
|
144
|
+
"ios#"]]]
|
145
|
+
|
146
|
+
|
147
|
+
irb> iox.ping '192.168.1.100'
|
148
|
+
=> [100, [5, 5],
|
149
|
+
[["ping 192.168.1.100",
|
150
|
+
"\rTue Oct 26 08:42:58.235 UTC",
|
151
|
+
"Type escape sequence to abort.",
|
152
|
+
"Sending 5, 100-byte ICMP Echos to 192.168.1.100, timeout is 2 seconds:",
|
153
|
+
"!!!!!",
|
154
|
+
"Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/2 ms",
|
155
|
+
"RP/0/0/CPU0:Paris-rp0#"]]]
|
156
|
+
|
157
|
+
|
158
|
+
irb> iox.ping '192.168.1.100', :sweep_min_size => 1000, :sweep_max_size => 1300
|
159
|
+
=> [100, [1505, 1505],
|
160
|
+
[["ping",
|
161
|
+
"\rTue Oct 26 08:44:33.024 UTC",
|
162
|
+
"Protocol [ipv4]: ", "",
|
163
|
+
"\rTarget IP address: ", "192.168.1.100",
|
164
|
+
"\rRepeat count [5]: ", "", "\rDatagram size [100]: ", "",
|
165
|
+
"\rTimeout in seconds [2]: ", "",
|
166
|
+
"\rExtended commands? [no]: ", "",
|
167
|
+
"\rSweep range of sizes? [no]: ", "yes",
|
168
|
+
"\rSweep min size [36]: ", "1000",
|
169
|
+
"\rSweep max size [18024]: ", "1300",
|
170
|
+
"\rSweep interval [1]: ", "",
|
171
|
+
"\rType escape sequence to abort.",
|
172
|
+
"Sending 1505, [1000..1300]-byte ICMP Echos to 192.168.1.100, timeout is 2 seconds:",
|
173
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
174
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
175
|
+
...
|
176
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
177
|
+
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
178
|
+
"Success rate is 100 percent (1505/1505), round-trip min/avg/max = 1/1/3 ms",
|
179
|
+
"RP/0/0/CPU0:Paris-rp0#"]]]
|
126
180
|
|
data/lib/expect/io.rb
CHANGED
@@ -81,14 +81,15 @@ module Expect4r
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def child_exit
|
84
|
-
if @
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
if @proxy
|
85
|
+
@proxy.logout
|
86
|
+
else
|
87
|
+
Process.kill(:KILL, @pid) if @pid
|
88
|
+
@thread.kill if @thread
|
88
89
|
end
|
89
90
|
rescue Errno::ESRCH, Errno::ECHILD => e
|
90
91
|
ensure
|
91
|
-
@lp, @r, @w, @pid = [nil]*
|
92
|
+
@lp, @r, @w, @pid, @proxy = [nil]*5
|
92
93
|
end
|
93
94
|
|
94
95
|
def spawn(cmd)
|
@@ -150,6 +151,7 @@ module Expect4r
|
|
150
151
|
end
|
151
152
|
|
152
153
|
def interact(k=?\C-z)
|
154
|
+
login unless connected?
|
153
155
|
STDOUT.puts "\n\#\n\# #{ctrl_key k} to terminate.\n\#\n"
|
154
156
|
reader :start
|
155
157
|
writer k
|
@@ -202,14 +204,25 @@ module Expect4r
|
|
202
204
|
@r && (not child_exited?)
|
203
205
|
end
|
204
206
|
|
205
|
-
def
|
207
|
+
def login_by_proxy(proxy)
|
208
|
+
raise ArgumentError, "Don't know how to login to #{proxy}" unless proxy.respond_to? :_login_
|
209
|
+
_login_ :proxy=> proxy
|
210
|
+
end
|
211
|
+
alias :login_via :login_by_proxy
|
212
|
+
|
213
|
+
def login(cmd, arg={})
|
214
|
+
|
206
215
|
return if connected?
|
207
216
|
|
208
|
-
|
217
|
+
if arg[:proxy]
|
218
|
+
login_proxy cmd, arg
|
219
|
+
else
|
220
|
+
spawn cmd
|
221
|
+
end
|
209
222
|
|
210
|
-
|
211
|
-
timeout =
|
212
|
-
no_echo =
|
223
|
+
arg={:timeout=>13, :no_echo=>false}.merge(arg)
|
224
|
+
timeout = arg[:timeout]
|
225
|
+
no_echo = arg[:no_echo]
|
213
226
|
|
214
227
|
output=[]
|
215
228
|
t0 = Time.now
|
@@ -223,7 +236,9 @@ module Expect4r
|
|
223
236
|
when spawnee_prompt
|
224
237
|
read_pipe._io_save false, "match PROMPT"
|
225
238
|
throw(:done, [:ok, output])
|
226
|
-
when /(
|
239
|
+
when /Last (L|l)ogin:/
|
240
|
+
read_pipe._io_save no_echo # consumes
|
241
|
+
when /(user\s*name\s*|login):\s*$/i
|
227
242
|
read_pipe._io_save no_echo, "match USERNAME"
|
228
243
|
exp_puts spawnee_username
|
229
244
|
when /password:\s*$/i
|
@@ -235,6 +250,9 @@ module Expect4r
|
|
235
250
|
when /.*\r\n/
|
236
251
|
exp_internal "match EOL"
|
237
252
|
read_pipe._io_save no_echo, "match EOL", "\r\n"
|
253
|
+
when /Are you sure you want to continue connecting \(yes\/no\)\?/
|
254
|
+
read_pipe._io_save no_echo, "match continue connecting"
|
255
|
+
exp_puts 'yes'
|
238
256
|
end
|
239
257
|
end
|
240
258
|
end
|
@@ -243,18 +261,24 @@ module Expect4r
|
|
243
261
|
elapsed = Time.now - t0
|
244
262
|
if elapsed < timeout
|
245
263
|
child_exit
|
246
|
-
raise ConnectionError.new(
|
264
|
+
raise ConnectionError.new(cmd)
|
247
265
|
else
|
248
|
-
raise ExpTimeoutError.new(
|
266
|
+
raise ExpTimeoutError.new(cmd, timeout)
|
249
267
|
end
|
250
268
|
else
|
251
269
|
@lp = buf.last
|
252
270
|
end
|
253
271
|
[buf, ev]
|
254
|
-
|
255
272
|
end
|
256
273
|
|
257
274
|
private
|
275
|
+
|
276
|
+
def login_proxy(cmd, arg)
|
277
|
+
@proxy = arg[:proxy].dup
|
278
|
+
@proxy.login
|
279
|
+
@proxy.exp_puts cmd
|
280
|
+
@r, @w, @pid = @proxy.instance_eval { [@r, @w, @pid] }
|
281
|
+
end
|
258
282
|
|
259
283
|
#FIXME ? putline to send_cmd ?
|
260
284
|
# hide putline and expose cmd
|
@@ -407,7 +431,7 @@ module Kernel
|
|
407
431
|
end
|
408
432
|
|
409
433
|
module Expect4r
|
410
|
-
class
|
434
|
+
class BaseLoginObject
|
411
435
|
class << self
|
412
436
|
def new_telnet(*args)
|
413
437
|
new :telnet, *args
|
@@ -421,11 +445,26 @@ module Expect4r
|
|
421
445
|
@routers << r
|
422
446
|
end
|
423
447
|
end
|
424
|
-
attr_reader :host, :user, :method, :port
|
448
|
+
attr_reader :host, :user, :method, :port, :proxy
|
425
449
|
alias :username :user
|
426
450
|
alias :hostname :host
|
451
|
+
# Adds a login to a Expect4r::BaseLoginObject"
|
452
|
+
#
|
453
|
+
# Constructor:
|
454
|
+
# * <tt>new</tt> <method>, <username>, <password>, [port_number]
|
455
|
+
# * <tt>new</tt> <method>, options={}
|
456
|
+
#
|
457
|
+
# Options are:
|
458
|
+
# * <tt>:host</tt> or <tt>:hostname</tt>
|
459
|
+
# * <tt>:user</tt> or <tt>:username</tt>
|
460
|
+
# * <tt>:pwd</tt> or <tt>:password</tt>
|
461
|
+
#
|
462
|
+
# Examples:
|
463
|
+
# new :telnet, :user=> 'lab', :password=>'lab'
|
464
|
+
# new :ssh, :user=> 'jme'
|
465
|
+
#
|
427
466
|
def initialize(*args)
|
428
|
-
|
467
|
+
ciphered_password=nil
|
429
468
|
if args.size>2 and args[1].is_a?(String)
|
430
469
|
@method, host, @user, pwd = args
|
431
470
|
elsif args.size == 2 and args[1].is_a?(Hash) and args[0].is_a?(Symbol)
|
@@ -433,29 +472,62 @@ module Expect4r
|
|
433
472
|
host = args[1][:host] || args[1][:hostname]
|
434
473
|
@user = args[1][:user]|| args[1][:username]
|
435
474
|
pwd = args[1][:pwd] || args[1][:password]
|
436
|
-
|
475
|
+
ciphered_password = args[1][:ciphered_password]
|
437
476
|
end
|
438
477
|
@host, port = host.split
|
439
478
|
@port = port.to_i
|
440
|
-
@pwd = if
|
441
|
-
|
479
|
+
@pwd = if ciphered_password
|
480
|
+
ciphered_password
|
442
481
|
else
|
443
482
|
Expect4r.cipher(pwd) if pwd
|
444
483
|
end
|
445
484
|
@ps1 = /(.*)(>|#|\$)\s*$/
|
446
485
|
@more = / --More-- /
|
447
486
|
@matches=Set.new
|
448
|
-
|
487
|
+
BaseLoginObject.add(self)
|
449
488
|
self
|
450
489
|
end
|
490
|
+
|
491
|
+
def spawnee
|
492
|
+
case method
|
493
|
+
when :telnet ; "telnet #{host} #{port if port>0}"
|
494
|
+
when :ssh ; "ssh #{spawnee_username}@#{host}"
|
495
|
+
else
|
496
|
+
raise RuntimeError
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
def spawnee_username
|
501
|
+
@user
|
502
|
+
end
|
503
|
+
|
504
|
+
def spawnee_prompt
|
505
|
+
@ps1
|
506
|
+
end
|
507
|
+
|
508
|
+
def dup
|
509
|
+
if @pwd
|
510
|
+
self.class.new @method, @host, @user, Expect4r.decipher(@pwd)
|
511
|
+
else
|
512
|
+
self.class.new @method, @host, @user
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
private
|
517
|
+
|
518
|
+
def spawnee_password
|
519
|
+
@pwd = Expect4r.cipher( ask("(#{self}) Enter your password: ") { |q| q.echo = "X" } ) unless @pwd
|
520
|
+
Expect4r.decipher(@pwd)
|
521
|
+
end
|
522
|
+
|
451
523
|
end
|
452
524
|
end
|
453
525
|
|
454
526
|
if __FILE__ != $0
|
455
527
|
|
456
528
|
at_exit {
|
457
|
-
if Expect4r::
|
458
|
-
Expect4r::
|
529
|
+
if Expect4r::BaseLoginObject.routers
|
530
|
+
Expect4r::BaseLoginObject.routers.each { |r| r.logout if r.respond_to? :logout }
|
459
531
|
end
|
460
532
|
}
|
461
533
|
|
@@ -463,21 +535,21 @@ else
|
|
463
535
|
|
464
536
|
require "test/unit"
|
465
537
|
|
466
|
-
class Expect4r::
|
538
|
+
class Expect4r::BaseLoginObject
|
467
539
|
def initialize
|
468
|
-
Expect4r::
|
540
|
+
Expect4r::BaseLoginObject.add(self)
|
469
541
|
end
|
470
542
|
end
|
471
543
|
|
472
|
-
class
|
544
|
+
class TestRouterBaseLoginObject < Test::Unit::TestCase
|
473
545
|
include Expect4r
|
474
546
|
|
475
547
|
def test_add
|
476
|
-
assert [],
|
477
|
-
|
478
|
-
assert 1,
|
479
|
-
|
480
|
-
assert_equal 2,
|
548
|
+
assert [], BaseLoginObject.routers
|
549
|
+
BaseLoginObject.new
|
550
|
+
assert 1, BaseLoginObject.routers.size
|
551
|
+
BaseLoginObject.new
|
552
|
+
assert_equal 2, BaseLoginObject.routers.size
|
481
553
|
end
|
482
554
|
end
|
483
555
|
|
data/lib/expect4r.rb
CHANGED
@@ -7,6 +7,7 @@ module Expect4r
|
|
7
7
|
autoload :Ios, 'router/cisco/ios/ios'
|
8
8
|
autoload :J, 'router/juniper/junos/junos'
|
9
9
|
autoload :Shell, 'misc/shell'
|
10
|
+
autoload :RShell, 'misc/shell'
|
10
11
|
|
11
12
|
module Router
|
12
13
|
autoload :Common, 'router/common'
|
@@ -33,6 +34,7 @@ module Expect4r
|
|
33
34
|
module Junos
|
34
35
|
autoload :Modes, 'router/juniper/junos/modes'
|
35
36
|
autoload :Show, 'router/juniper/junos/show'
|
37
|
+
autoload :Ping, 'router/juniper/junos/ping'
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
data/lib/misc/shell.rb
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
require 'expect/io'
|
2
|
-
|
3
1
|
module Expect4r
|
4
|
-
|
5
2
|
class Shell
|
6
3
|
include Expect4r
|
7
4
|
def initialize()
|
@@ -15,5 +12,44 @@ module Expect4r
|
|
15
12
|
spawn @shell
|
16
13
|
end
|
17
14
|
end
|
15
|
+
class RShell < ::Expect4r::BaseLoginObject
|
16
|
+
include Expect4r
|
17
|
+
def initialize(*args)
|
18
|
+
super
|
19
|
+
default_ps1
|
20
|
+
end
|
21
|
+
def logout
|
22
|
+
default_ps1
|
23
|
+
super
|
24
|
+
end
|
25
|
+
def login(arg={})
|
26
|
+
super(spawnee, arg)
|
27
|
+
cmd %{export COLUMNS=1024}
|
28
|
+
end
|
29
|
+
# FIXME: 1.9.2 bug:
|
30
|
+
# It calls LoginBaseOject#login() instead of calling J#login()
|
31
|
+
# modified login_by_proxy to call _login_ seems to work.
|
32
|
+
alias :_login_ :login
|
33
|
+
|
34
|
+
def ps1=(val)
|
35
|
+
# Assumes bash
|
36
|
+
@ps1_bis = /#{val}$/
|
37
|
+
cmd %? export PS1='#{val}' ?
|
38
|
+
@ps1 = @ps1_bi
|
39
|
+
end
|
40
|
+
def cmd(*args)
|
41
|
+
exp_send *args
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def default_ps1
|
47
|
+
@ps1 = /.+[^\#](\#|\$)\s+$/
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
__END__
|
53
|
+
|
18
54
|
|
19
|
-
|
55
|
+
cmd %? PROMPT_COMMAND="echo -n [$(date +%k:%m:%S)]: && pwd" && export PS1='#{val}' ?
|
@@ -2,6 +2,16 @@
|
|
2
2
|
module Expect4r::Router
|
3
3
|
module CiscoCommon
|
4
4
|
|
5
|
+
#
|
6
|
+
# Returns the config level depths:
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# iox(config-ospf-ar)#
|
11
|
+
#
|
12
|
+
# irb> iox.config_lvl?
|
13
|
+
# => 3
|
14
|
+
#
|
5
15
|
def config_lvl?
|
6
16
|
return -1 unless config?
|
7
17
|
@lp =~ /\(config(|.+)\)/
|
@@ -4,6 +4,29 @@ module Expect4r::Router::CiscoCommon
|
|
4
4
|
module Ping
|
5
5
|
include ::Expect4r::Router::Error
|
6
6
|
|
7
|
+
# Adds a <tt>ping</tt> method to <tt>CiscoCommon::Ping mixin</tt>:
|
8
|
+
#
|
9
|
+
# Options are:
|
10
|
+
# * <tt>:protocol</tt>
|
11
|
+
# * <tt>:repeat_count</tt> or <tt>:count</tt>
|
12
|
+
# * <tt>:datagram_size</tt> or <tt>:size</tt>
|
13
|
+
# * <tt>:timeout</tt>
|
14
|
+
# * <tt>:source_address</tt>
|
15
|
+
# * <tt>:tos</tt>
|
16
|
+
# * <tt>:df</tt>
|
17
|
+
# * <tt>:pattern</tt>
|
18
|
+
# * <tt>:sweep_min_size</tt>
|
19
|
+
# * <tt>:sweep_max_size</tt>
|
20
|
+
# * <tt>:sweep_interval</tt>
|
21
|
+
# * <tt>:pct_success</tt> - default is 99.
|
22
|
+
#
|
23
|
+
# Option examples:
|
24
|
+
# :protocol => 'ipv4'
|
25
|
+
# :count => 10
|
26
|
+
# :timeout => 1
|
27
|
+
# :size=> 512
|
28
|
+
# :protocol=> 'ipv4', :count=> 20, :size=> 1500, :timeout=>5
|
29
|
+
#
|
7
30
|
def ping(target_ip_address, arg={})
|
8
31
|
|
9
32
|
pct_success = arg.delete(:pct_success) || 99
|
@@ -98,11 +121,3 @@ private
|
|
98
121
|
end
|
99
122
|
end
|
100
123
|
|
101
|
-
__END__
|
102
|
-
|
103
|
-
p.ping '192.168.1.23'
|
104
|
-
p.ping '192.168.1.23', :sweep_max_size=> 1512, :pct_success => 95
|
105
|
-
p.ping '192.168.1.23', :source_address => '192.168.1.199', :count=> 100, :pct_success=> 90
|
106
|
-
|
107
|
-
puts output[2][0].join("\n").split(": \n").join(": ")
|
108
|
-
|
data/lib/router/cisco/ios/ios.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'router/cisco/common/common'
|
2
2
|
|
3
|
-
class Expect4r::Ios < ::Expect4r::
|
3
|
+
class Expect4r::Ios < ::Expect4r::BaseLoginObject
|
4
4
|
|
5
5
|
include Expect4r
|
6
6
|
include Expect4r::Router::Common
|
@@ -33,12 +33,17 @@ class Expect4r::Ios < ::Expect4r::BaseObject
|
|
33
33
|
Expect4r.decipher(@pwd) # password is ciphered ...
|
34
34
|
end
|
35
35
|
|
36
|
-
def login
|
37
|
-
super(spawnee)
|
36
|
+
def login(arg={})
|
37
|
+
super(spawnee,arg)
|
38
38
|
enable
|
39
39
|
exec "term len 0\nterm width 0"
|
40
40
|
self
|
41
41
|
end
|
42
|
+
# FIXME: 1.9.2 bug:
|
43
|
+
# It calls LoginBaseOject#login() instead of calling J#login()
|
44
|
+
# modified login_by_proxy to call _login_ seems to work.
|
45
|
+
alias :_login_ :login
|
46
|
+
|
42
47
|
|
43
48
|
def putline(line,*args)
|
44
49
|
output, rc = super
|
@@ -3,6 +3,10 @@ require 'router/modes'
|
|
3
3
|
module Expect4r::Router::Ios
|
4
4
|
module Modes
|
5
5
|
|
6
|
+
# Adds a <tt>in?</tt> mixin.
|
7
|
+
#
|
8
|
+
# Returns the mode the router is in: :user, :exec, :config
|
9
|
+
#
|
6
10
|
def in?(mode=:none)
|
7
11
|
login unless connected?
|
8
12
|
case mode
|
@@ -61,10 +65,16 @@ module Modes
|
|
61
65
|
@lp =~ /\(config(|.+)\)/
|
62
66
|
end
|
63
67
|
|
68
|
+
#
|
69
|
+
# returns <tt>true</tt> if router is in <tt>:exec</tt> (enabled) mode, <tt>false</tt> otherwise.
|
70
|
+
#
|
64
71
|
def exec?
|
65
72
|
! user? and ! config?
|
66
73
|
end
|
67
74
|
|
75
|
+
#
|
76
|
+
# returns <tt>true</tt> if router is in <tt>:user</tt> mode, <tt>false</tt> otherwise.
|
77
|
+
#
|
68
78
|
def user?
|
69
79
|
@lp =~ /.+>\s*$/
|
70
80
|
end
|
data/lib/router/cisco/iox/iox.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'router/cisco/common/common'
|
3
3
|
|
4
|
-
class Expect4r::Iox < ::Expect4r::
|
4
|
+
class Expect4r::Iox < ::Expect4r::BaseLoginObject
|
5
5
|
|
6
6
|
include Expect4r
|
7
7
|
include Expect4r::Router
|
@@ -18,12 +18,16 @@ class Expect4r::Iox < ::Expect4r::BaseObject
|
|
18
18
|
@more = / --More-- /
|
19
19
|
end
|
20
20
|
|
21
|
-
def login
|
22
|
-
super(spawnee)
|
21
|
+
def login(arg={})
|
22
|
+
super(spawnee, arg)
|
23
23
|
config 'no logging console' if port>0
|
24
24
|
exec "terminal len 0\nterminal width 0"
|
25
25
|
self
|
26
26
|
end
|
27
|
+
# FIXME: 1.9.2 bug:
|
28
|
+
# It calls LoginBaseOject#login() instead of calling J#login()
|
29
|
+
# modified login_by_proxy to call _login_ seems to work.
|
30
|
+
alias :_login_ :login
|
27
31
|
|
28
32
|
def commit(arg={})
|
29
33
|
return unless config?
|
@@ -3,6 +3,19 @@ require 'router/modes'
|
|
3
3
|
module Expect4r::Router::Iox
|
4
4
|
module Modes
|
5
5
|
|
6
|
+
# Adds an Iox <tt>config>/tt> mixin.
|
7
|
+
#
|
8
|
+
# Options are:
|
9
|
+
#
|
10
|
+
# Option examples:
|
11
|
+
#
|
12
|
+
# iox.config %{
|
13
|
+
# interface GigabitEthernet0/2/0/0
|
14
|
+
# desc to switch port 13'
|
15
|
+
# ipv4 address 190.0.0.9 255.255.255.252'
|
16
|
+
# no shut'
|
17
|
+
# }
|
18
|
+
#
|
6
19
|
def config(config=nil, arg={})
|
7
20
|
login unless connected?
|
8
21
|
if config
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
__END__
|
3
|
+
|
4
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 ?
|
5
|
+
donotfrag set DF bit in IP header
|
6
|
+
pattern data pattern
|
7
|
+
size datagram size
|
8
|
+
source source address or source interface
|
9
|
+
sweep sweep ping
|
10
|
+
timeout timeout in seconds
|
11
|
+
type type of service
|
12
|
+
validate validate return packet
|
13
|
+
verbose verbose output
|
14
|
+
<cr>
|
15
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size ?
|
16
|
+
<36-18024> datagram size
|
17
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size 100 ?
|
18
|
+
donotfrag set DF bit in IP header
|
19
|
+
pattern data pattern
|
20
|
+
source source address or source interface
|
21
|
+
sweep sweep ping
|
22
|
+
timeout timeout in seconds
|
23
|
+
type type of service
|
24
|
+
validate validate return packet
|
25
|
+
verbose verbose output
|
26
|
+
<cr>
|
27
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size 100 donotfrag ?
|
28
|
+
pattern data pattern
|
29
|
+
source source address or source interface
|
30
|
+
sweep sweep ping
|
31
|
+
timeout timeout in seconds
|
32
|
+
type type of service
|
33
|
+
validate validate return packet
|
34
|
+
verbose verbose output
|
35
|
+
<cr>
|
36
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size 100 donotfrag pattern ?
|
37
|
+
<0-65535> data pattern
|
38
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size 100 donotfrag pattern 0xdead type 2 ?
|
39
|
+
source source address or source interface
|
40
|
+
sweep sweep ping
|
41
|
+
timeout timeout in seconds
|
42
|
+
validate validate return packet
|
43
|
+
verbose verbose output
|
44
|
+
<cr>
|
45
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size 100 donotfrag pattern 0xdead type 2 timeout 10 sweep ?
|
46
|
+
source source address or source interface
|
47
|
+
validate validate return packet
|
48
|
+
verbose verbose output
|
49
|
+
<cr>
|
50
|
+
RP/0/0/CPU0:Paris-rp0#ping ipv4 1.1.1.1 count 5 size 100 donotfrag pattern 0xdead type 2 timeout 10 sweep ?
|
51
|
+
source source address or source interface
|
52
|
+
validate validate return packet
|
53
|
+
verbose verbose output
|
54
|
+
<cr>
|
55
|
+
RP/0/0/CPU0:Paris-rp0#
|
data/lib/router/common.rb
CHANGED
@@ -14,29 +14,5 @@ module Common
|
|
14
14
|
putc "\n" if console?
|
15
15
|
end
|
16
16
|
|
17
|
-
def spawnee
|
18
|
-
case method
|
19
|
-
when :telnet ; "telnet #{host} #{port if port>0}"
|
20
|
-
when :ssh ; "ssh #{spawnee_username}@#{host}"
|
21
|
-
else
|
22
|
-
raise RuntimeError
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def spawnee_username
|
27
|
-
@user
|
28
|
-
end
|
29
|
-
|
30
|
-
def spawnee_prompt
|
31
|
-
@ps1
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def spawnee_password
|
37
|
-
@pwd = Expect4r.cipher( ask("Enter your password: ") { |q| q.echo = "X" } ) unless @pwd
|
38
|
-
Expect4r.decipher(@pwd)
|
39
|
-
end
|
40
|
-
|
41
17
|
end
|
42
18
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Expect4r::J < ::Expect4r::
|
1
|
+
class Expect4r::J < ::Expect4r::BaseLoginObject
|
2
2
|
include Expect4r
|
3
3
|
include Expect4r::Router::Error
|
4
4
|
include Expect4r::Router::Common
|
@@ -13,12 +13,15 @@ class Expect4r::J < ::Expect4r::BaseObject
|
|
13
13
|
@more = /---\(more(| \d+\%)\)---/
|
14
14
|
end
|
15
15
|
|
16
|
-
def login
|
17
|
-
|
18
|
-
super(spawnee)
|
16
|
+
def login(arg={})
|
17
|
+
super(spawnee, arg)
|
19
18
|
exec 'set cli screen-length 0'
|
20
19
|
self
|
21
20
|
end
|
21
|
+
# FIXME: 1.9.2 bug:
|
22
|
+
# It calls LoginBaseOject#login() instead of calling J#login()
|
23
|
+
# modified login_by_proxy to call _login_ seems to work.
|
24
|
+
alias :_login_ :login
|
22
25
|
|
23
26
|
def console?
|
24
27
|
@port>0
|
@@ -3,6 +3,18 @@ require 'router/modes'
|
|
3
3
|
module Expect4r::Router::Junos
|
4
4
|
module Modes
|
5
5
|
|
6
|
+
# Adds a Junos <tt>config</tt> mixin.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# j.config %{
|
11
|
+
# edit logical-router Orleans protocols bgp
|
12
|
+
# edit group session-to-200
|
13
|
+
# set type external
|
14
|
+
# set peer-as 200
|
15
|
+
# set neighbor 40.0.2.1 peer-as 200
|
16
|
+
# }
|
17
|
+
#
|
6
18
|
def config(stmts=nil, arg={})
|
7
19
|
login unless connected?
|
8
20
|
if stmts
|
@@ -13,10 +25,16 @@ def config(stmts=nil, arg={})
|
|
13
25
|
change_mode_to(mode)
|
14
26
|
output
|
15
27
|
else
|
16
|
-
|
28
|
+
to_config
|
17
29
|
end
|
18
30
|
end
|
19
31
|
|
32
|
+
# Adds a Junos <tt>exec</tt> mixin.
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
#
|
36
|
+
# j.exec 'set cli screen-length 0'
|
37
|
+
#
|
20
38
|
def exec(cmd=nil, *args)
|
21
39
|
login unless connected?
|
22
40
|
if cmd.nil?
|
@@ -50,14 +68,23 @@ def shell(cmd=nil, *args)
|
|
50
68
|
end
|
51
69
|
end
|
52
70
|
|
71
|
+
#
|
72
|
+
# returns <tt>true</tt> if router is in <tt>:exec</tt> mode, <tt>false</tt> otherwise.
|
73
|
+
#
|
53
74
|
def exec?
|
54
75
|
@lp =~ /> $/ ? true : false
|
55
76
|
end
|
56
77
|
|
78
|
+
#
|
79
|
+
# returns <tt>true</tt> if router is in <tt>:config</tt> mode, <tt>false</tt> otherwise.
|
80
|
+
#
|
57
81
|
def config?
|
58
82
|
@lp =~ /^.+# $/ ? true : false
|
59
83
|
end
|
60
84
|
|
85
|
+
#
|
86
|
+
# returns <tt>true</tt> if router is in <tt>:shell</tt> mode, <tt>false</tt> otherwise.
|
87
|
+
#
|
61
88
|
def shell?
|
62
89
|
@lp == '% ' ? true : false
|
63
90
|
end
|
@@ -3,6 +3,24 @@ require 'router/error'
|
|
3
3
|
module Expect4r::Router::Junos
|
4
4
|
module Ping
|
5
5
|
|
6
|
+
# Adds a ping method to J class:
|
7
|
+
#
|
8
|
+
# Options are:
|
9
|
+
# * <tt>:count</tt> or <tt>:repeat_count</tt>
|
10
|
+
# * <tt>:size</tt> or <tt>:datagram_size</tt>
|
11
|
+
# * <tt>:datagram_size</tt> or <tt>:size</tt>
|
12
|
+
# * <tt>:timeout</tt>
|
13
|
+
# * <tt>:tos</tt>
|
14
|
+
# * <tt>:ttl</tt>
|
15
|
+
# * <tt>:pattern</tt>
|
16
|
+
# * <tt>:pct_success</tt> - default is 99.
|
17
|
+
#
|
18
|
+
# Option examples:
|
19
|
+
# :count => 10
|
20
|
+
# :timeout => 1
|
21
|
+
# :size=> 512
|
22
|
+
# :protocol=> 'ipv4', :count=> 20, :size=> 1500, :timeout=>5, :ttl=>16
|
23
|
+
#
|
6
24
|
def ping(host, arg={})
|
7
25
|
|
8
26
|
pct_success = arg.delete(:pct_success) || 99
|
data/lib/router/modes.rb
CHANGED
@@ -2,6 +2,21 @@ module Expect4r
|
|
2
2
|
module Router
|
3
3
|
module Common
|
4
4
|
module Modes
|
5
|
+
|
6
|
+
# Adds a <tt>in?</tt> mixin.
|
7
|
+
#
|
8
|
+
# Examples:
|
9
|
+
#
|
10
|
+
# irb(main):007:0> iox.in?
|
11
|
+
# => :exec
|
12
|
+
# irb(main):008:0> iox.config
|
13
|
+
# => :config
|
14
|
+
# irb(main):009:0> iox.in?
|
15
|
+
# => :config
|
16
|
+
# irb(main):010:0> iox.shell
|
17
|
+
# => :shell
|
18
|
+
# irb(main):011:0> iox.in?
|
19
|
+
# => :shell
|
5
20
|
def in?(mode=:none)
|
6
21
|
login unless connected?
|
7
22
|
case mode
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- dev
|
10
|
-
version: 0.0.
|
10
|
+
version: 0.0.3.dev
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jean-Michel Esnault
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-27 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 1.5.0
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
|
-
description: A Ruby Library for interacting with IOS, IOS-XR, and JUNOS
|
35
|
+
description: A Ruby Library for interacting with IOS, IOS-XR, and JUNOS CLI.
|
36
36
|
email: jesnault@gmail.com
|
37
37
|
executables: []
|
38
38
|
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- lib/router/cisco/ios/termserver.rb
|
58
58
|
- lib/router/cisco/iox/iox.rb
|
59
59
|
- lib/router/cisco/iox/modes.rb
|
60
|
+
- lib/router/cisco/iox/ping.rb
|
60
61
|
- lib/router/common.rb
|
61
62
|
- lib/router/error.rb
|
62
63
|
- lib/router/juniper/junos/junos.rb
|