expect4r 0.0.1.dev → 0.0.2.dev
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/lib/expect/io.rb +16 -16
- data/lib/expect4r.rb +1 -1
- data/lib/router/cisco/common/common.rb +13 -0
- data/lib/router/cisco/common/ping.rb +94 -25
- data/lib/router/cisco/common/show.rb +4 -11
- data/lib/router/cisco/ios/ios.rb +4 -1
- data/lib/router/cisco/iox/iox.rb +5 -2
- data/lib/router/juniper/junos/junos.rb +1 -0
- data/lib/router/juniper/junos/ping.rb +120 -0
- metadata +6 -5
data/README.rdoc
CHANGED
@@ -13,7 +13,7 @@ You talk to routers by connecting to them using ssh or telnet and send exec or c
|
|
13
13
|
j = J.new_telnet :host=> '', :user=> 'lab', :pwd => 'lab'
|
14
14
|
j.login
|
15
15
|
|
16
|
-
* Push
|
16
|
+
* Push configurations to routers
|
17
17
|
|
18
18
|
ios.config 'no logging console'
|
19
19
|
|
data/lib/expect/io.rb
CHANGED
@@ -52,8 +52,8 @@ end
|
|
52
52
|
module Expect4r
|
53
53
|
|
54
54
|
class ConnectionError < RuntimeError
|
55
|
-
def initialize(
|
56
|
-
@output =
|
55
|
+
def initialize(*args)
|
56
|
+
@output = args[0]
|
57
57
|
end
|
58
58
|
def err_msg
|
59
59
|
"Connection Error: #{@output}"
|
@@ -61,22 +61,20 @@ module Expect4r
|
|
61
61
|
end
|
62
62
|
|
63
63
|
class ExpTimeoutError < RuntimeError
|
64
|
-
def initialize(
|
65
|
-
@output, @
|
64
|
+
def initialize(*args)
|
65
|
+
@output, @timeout = args
|
66
66
|
end
|
67
67
|
def err_msg
|
68
|
-
"Timeout Error: #{@output}"
|
68
|
+
"Timeout Error: timeout= #{@timeout}: #{@output}"
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
class NoChildError < RuntimeError
|
73
|
-
end
|
74
72
|
class SpawnError < RuntimeError
|
75
|
-
def initialize(
|
76
|
-
@cmd =
|
73
|
+
def initialize(*args)
|
74
|
+
@cmd = args[0]
|
77
75
|
end
|
78
76
|
def err_msg
|
79
|
-
"Error: #{
|
77
|
+
"Spawn Error: #{@cmd}"
|
80
78
|
end
|
81
79
|
end
|
82
80
|
class Expect4rIO_Error < RuntimeError
|
@@ -96,7 +94,6 @@ module Expect4r
|
|
96
94
|
def spawn(cmd)
|
97
95
|
begin
|
98
96
|
child_exited = false
|
99
|
-
# STDOUT.puts "*** FALSE ***"
|
100
97
|
@thread = Thread.new do
|
101
98
|
PTY.spawn(cmd) do |pipe_read, pipe_write, pid|
|
102
99
|
@r, @w, @pid = pipe_read, pipe_write, pid
|
@@ -109,7 +106,6 @@ module Expect4r
|
|
109
106
|
end
|
110
107
|
end
|
111
108
|
@thread.priority = -2
|
112
|
-
# STDOUT.puts "*** #{child_exited} ***"
|
113
109
|
unless child_exited
|
114
110
|
while @r.nil?
|
115
111
|
sleep(0.05)
|
@@ -122,6 +118,7 @@ module Expect4r
|
|
122
118
|
|
123
119
|
def logout
|
124
120
|
child_exit
|
121
|
+
@pid
|
125
122
|
end
|
126
123
|
|
127
124
|
def putc(c)
|
@@ -136,6 +133,7 @@ module Expect4r
|
|
136
133
|
def exp_puts(s)
|
137
134
|
exp_print "#{s}\r"
|
138
135
|
end
|
136
|
+
|
139
137
|
def exp_print(s)
|
140
138
|
exp_internal "print: #{s.inspect}, io_writer: #{@w}"
|
141
139
|
return unless @w
|
@@ -192,7 +190,7 @@ module Expect4r
|
|
192
190
|
end
|
193
191
|
end
|
194
192
|
exp_internal "#{ev.inspect} buf: #{buf.inspect}"
|
195
|
-
raise
|
193
|
+
raise ExpTimeoutError.new(buf, ti) if ev == :timeout
|
196
194
|
[buf, ev]
|
197
195
|
end
|
198
196
|
|
@@ -244,9 +242,10 @@ module Expect4r
|
|
244
242
|
when :abort
|
245
243
|
elapsed = Time.now - t0
|
246
244
|
if elapsed < timeout
|
245
|
+
child_exit
|
247
246
|
raise ConnectionError.new(c)
|
248
247
|
else
|
249
|
-
raise ExpTimeoutError.new(c,
|
248
|
+
raise ExpTimeoutError.new(c, timeout)
|
250
249
|
end
|
251
250
|
else
|
252
251
|
@lp = buf.last
|
@@ -260,8 +259,8 @@ module Expect4r
|
|
260
259
|
#FIXME ? putline to send_cmd ?
|
261
260
|
# hide putline and expose cmd
|
262
261
|
def putline(line, arg={})
|
263
|
-
raise
|
264
|
-
|
262
|
+
raise ConnectionError.new(line) if child_exited?
|
263
|
+
|
265
264
|
arg = {:ti=>13, :no_echo=>false, :debug=>0, :sync=> false, :no_trim=>false}.merge(arg)
|
266
265
|
no_echo = arg[:no_echo]
|
267
266
|
ti = arg[:ti]
|
@@ -306,6 +305,7 @@ module Expect4r
|
|
306
305
|
when :abort
|
307
306
|
elapsed = Time.now - t0
|
308
307
|
if elapsed < ti
|
308
|
+
child_exit
|
309
309
|
raise ConnectionError.new(line)
|
310
310
|
else
|
311
311
|
raise ExpTimeoutError.new(line, elapsed)
|
data/lib/expect4r.rb
CHANGED
@@ -19,6 +19,19 @@ module CiscoCommon
|
|
19
19
|
@lp =~ /\(config(|.+)\)/
|
20
20
|
Regexp.last_match(1).size == 0
|
21
21
|
end
|
22
|
+
|
23
|
+
def method_missing(name, *args, &block)
|
24
|
+
if name.to_s =~ /^show_/
|
25
|
+
cmd = name.to_s.split('_').join(' ') + args.join(' ')
|
26
|
+
cmd.gsub!(/running config/, 'running-config')
|
27
|
+
output = __send__ :exec, cmd, *args
|
28
|
+
elsif name.to_s =~ /^shell_/
|
29
|
+
cmd = name.to_s.split('_')[1..-1].join(' ') + args.join(' ')
|
30
|
+
output = __send__ :shell, cmd, *args
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
22
35
|
|
23
36
|
end
|
24
37
|
end
|
@@ -3,37 +3,106 @@ require 'router/error'
|
|
3
3
|
module Expect4r::Router::CiscoCommon
|
4
4
|
module Ping
|
5
5
|
include ::Expect4r::Router::Error
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dest = arg
|
16
|
-
when Hash
|
17
|
-
dest = arg[:dest]
|
6
|
+
|
7
|
+
def ping(target_ip_address, arg={})
|
8
|
+
|
9
|
+
pct_success = arg.delete(:pct_success) || 99
|
10
|
+
|
11
|
+
if arg.empty?
|
12
|
+
|
13
|
+
output = exec "ping #{target_ip_address}", arg
|
14
|
+
|
18
15
|
else
|
19
|
-
|
16
|
+
|
17
|
+
@matches = Set.new
|
18
|
+
|
19
|
+
set_ping_base_matches target_ip_address, arg
|
20
|
+
set_ping_extended_matches arg
|
21
|
+
set_ping_sweep_matches arg
|
22
|
+
|
23
|
+
output = exec "ping", arg
|
24
|
+
|
20
25
|
end
|
21
|
-
|
26
|
+
|
22
27
|
r = output[0].find { |x| x =~/Success.*[^\d](\d+) percent \((\d+)\/(\d+)\)/}
|
28
|
+
|
23
29
|
if r &&
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
Regexp.last_match(1) &&
|
31
|
+
Regexp.last_match(2) &&
|
32
|
+
Regexp.last_match(3)
|
33
|
+
|
34
|
+
pct = $1.to_i
|
35
|
+
tx = $3.to_i
|
36
|
+
rx = $2.to_i
|
37
|
+
|
38
|
+
if $1.to_i < pct_success
|
39
|
+
raise ::Expect4r::Router::Error::PingError.new(@host, target_ip_address, pct_success, pct, tx, rx, output)
|
40
|
+
else
|
41
|
+
[$1.to_i,[$2.to_i,$3.to_i],output]
|
42
|
+
end
|
43
|
+
|
34
44
|
else
|
35
|
-
raise PingError.new(
|
45
|
+
raise ::Expect4r::Router::Error::PingError.new(@host, target_ip_adress, pct_success, pct, tx, rx, output)
|
36
46
|
end
|
47
|
+
|
37
48
|
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def set_ping_base_matches(target_ip_address, arg={})
|
53
|
+
protocol = arg[:protocol] || ''
|
54
|
+
repeat_count = arg[:repeat_count] || arg[:count] || ''
|
55
|
+
datagram_size = arg[:datagram_size] || arg[:size] || ''
|
56
|
+
timeout = arg[:timeout] || ''
|
57
|
+
@matches << [/Protocol.+\: $/, protocol]
|
58
|
+
@matches << [/Target IP address\: $/, target_ip_address]
|
59
|
+
@matches << [/Repeat count.+\: $/, repeat_count]
|
60
|
+
@matches << [/Datagram size.+\: $/, datagram_size]
|
61
|
+
@matches << [/Timeout.+\: $/, timeout]
|
62
|
+
end
|
63
|
+
|
64
|
+
def set_ping_extended_matches(arg={})
|
65
|
+
extended_keys = [:source_address, :tos, :df, :pattern]
|
66
|
+
if (extended_keys & arg.keys).empty? and ! arg[:source_address]
|
67
|
+
@matches << [/Extended.+\: $/, '']
|
68
|
+
else
|
69
|
+
src_adr = arg[:source_address]
|
70
|
+
tos = arg[:tos] || ''
|
71
|
+
df = arg[:df] || ''
|
72
|
+
pattern = arg[:pattern] || ''
|
73
|
+
@matches << [/Extended.+\: $/, 'yes']
|
74
|
+
@matches << [/Source address or interface\: $/, src_adr]
|
75
|
+
@matches << [/Type of service.+\: $/, tos]
|
76
|
+
@matches << [/Set DF bit.+\: $/, df]
|
77
|
+
@matches << [/Data pattern.+\: $/, pattern]
|
78
|
+
@matches << [/Validate reply.+\: $/, ''] #TODO
|
79
|
+
@matches << [/Loose, Strict,.+\: $/, ''] #TODO
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_ping_sweep_matches(arg={})
|
84
|
+
sweep_keys = [:sweep_min_size, :sweep_max_size, :sweep_interval]
|
85
|
+
if (sweep_keys & arg.keys).empty?
|
86
|
+
@matches << [/Sweep range of sizes.+: $/, 'no']
|
87
|
+
else
|
88
|
+
min_size = arg[:sweep_min_size] || ''
|
89
|
+
max_size = arg[:sweep_max_size] || ''
|
90
|
+
interval = arg[:sweep_interval] || ''
|
91
|
+
@matches << [/Sweep range of sizes.+: $/, 'yes']
|
92
|
+
@matches << [/Sweep min size.+\: $/, min_size]
|
93
|
+
@matches << [/Sweep max size.+\: $/, max_size]
|
94
|
+
@matches << [/Sweep interval.+\: $/, interval]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
38
98
|
end
|
39
99
|
end
|
100
|
+
|
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
|
+
|
@@ -3,20 +3,13 @@ module Show
|
|
3
3
|
|
4
4
|
def show(s, arg={})
|
5
5
|
output = []
|
6
|
+
nlines = 0
|
6
7
|
s.each_line { |l|
|
8
|
+
next unless l.strip.size>0
|
7
9
|
output << exec("show #{l}", arg) if l.strip.size>0
|
10
|
+
nlines +=1
|
8
11
|
}
|
9
|
-
output
|
10
|
-
end
|
11
|
-
|
12
|
-
def method_missing(name, *args, &block)
|
13
|
-
if name.to_s =~ /^show_/
|
14
|
-
cmd = name.to_s.split('_').join(' ') + args.join(' ')
|
15
|
-
cmd.gsub!(/running config/, 'running-config')
|
16
|
-
output = __send__ :exec, cmd, *args
|
17
|
-
else
|
18
|
-
super
|
19
|
-
end
|
12
|
+
nlines > 1 ? output : output[0]
|
20
13
|
end
|
21
14
|
|
22
15
|
end
|
data/lib/router/cisco/ios/ios.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'router/cisco/common/common'
|
2
|
+
|
1
3
|
class Expect4r::Ios < ::Expect4r::BaseObject
|
2
4
|
|
3
5
|
include Expect4r
|
@@ -59,7 +61,8 @@ class Expect4r::Ios < ::Expect4r::BaseObject
|
|
59
61
|
end
|
60
62
|
|
61
63
|
def error?(output)
|
62
|
-
string_start_with_pct_char?(output[-2]) ||
|
64
|
+
string_start_with_pct_char?(output[-2]) ||
|
65
|
+
string_start_with_pct_char?(output[-3])
|
63
66
|
end
|
64
67
|
|
65
68
|
end
|
data/lib/router/cisco/iox/iox.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
|
2
|
+
require 'router/cisco/common/common'
|
3
|
+
|
1
4
|
class Expect4r::Iox < ::Expect4r::BaseObject
|
2
5
|
|
3
6
|
include Expect4r
|
@@ -28,14 +31,14 @@ class Expect4r::Iox < ::Expect4r::BaseObject
|
|
28
31
|
if /\% Failed to commit/.match(output.join)
|
29
32
|
err = show_configuration_failed
|
30
33
|
abort_config
|
31
|
-
raise Iox::SemanticError.new(show_configuration_failed)
|
34
|
+
raise Iox::SemanticError.new(self.class.to_s, show_configuration_failed)
|
32
35
|
end
|
33
36
|
output
|
34
37
|
end
|
35
38
|
|
36
39
|
def putline(line,*args)
|
37
40
|
output, rc = super
|
38
|
-
raise SyntaxError.new(line) if output.join =~ /\% Invalid input detected at/
|
41
|
+
raise SyntaxError.new(self.class.to_s, line) if output.join =~ /\% Invalid input detected at/
|
39
42
|
output
|
40
43
|
end
|
41
44
|
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'router/error'
|
2
|
+
|
3
|
+
module Expect4r::Router::Junos
|
4
|
+
module Ping
|
5
|
+
|
6
|
+
def ping(host, arg={})
|
7
|
+
|
8
|
+
pct_success = arg.delete(:pct_success) || 99
|
9
|
+
|
10
|
+
output = exec(ping_cmd(host, arg), arg)
|
11
|
+
|
12
|
+
r = output[0].find { |x| p x ; x =~/(\d+) packets transmitted, (\d+) packets received, (\d+)\% packet loss/}
|
13
|
+
|
14
|
+
if r &&
|
15
|
+
Regexp.last_match(1) &&
|
16
|
+
Regexp.last_match(2) &&
|
17
|
+
Regexp.last_match(3)
|
18
|
+
|
19
|
+
success = 100 - $3.to_i
|
20
|
+
tx = $2.to_i
|
21
|
+
rx = $3.to_i
|
22
|
+
|
23
|
+
if (100 - $3.to_i) < pct_success
|
24
|
+
raise ::Expect4r::Router::Error::PingError.new(@host, host, pct_success, tx, rx, output)
|
25
|
+
else
|
26
|
+
[$1.to_i,[$2.to_i,$3.to_i],output]
|
27
|
+
end
|
28
|
+
|
29
|
+
else
|
30
|
+
raise ::Expect4r::Router::Error::PingError.new(@host, host, pct_success, $1.to_i, tx, rx, output)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def ping_cmd(host, arg={})
|
38
|
+
cmd = "ping #{host}"
|
39
|
+
cmd += " rapid"
|
40
|
+
cmd += " count #{arg[:count] || arg[:repeat_count]}" if arg[:count] || arg[:repeat_count]
|
41
|
+
cmd += " size #{arg[:size] || arg[:datagram_size]}" if arg[:size] || arg[:datagram_size]
|
42
|
+
cmd += " pattern #{arg[:pattern]}" if arg[:pattern]
|
43
|
+
cmd += " tos #{arg[:tos]}" if arg[:tos]
|
44
|
+
cmd += " ttl #{arg[:ttl]}" if arg[:ttl]
|
45
|
+
cmd
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
__END__
|
52
|
+
|
53
|
+
|
54
|
+
if __FILE__ == $0
|
55
|
+
|
56
|
+
module Expect4r
|
57
|
+
module Router
|
58
|
+
module Junos
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
if __FILE__ == $0
|
66
|
+
|
67
|
+
require "test/unit"
|
68
|
+
|
69
|
+
class TestLibraryFileName < Test::Unit::TestCase
|
70
|
+
include Expect4r::Router::Junos::Ping
|
71
|
+
def test_case_name
|
72
|
+
|
73
|
+
assert_equal 'ping 1.1.1.1 rapid', ping_cmd( '1.1.1.1')
|
74
|
+
assert_equal 'ping 1.1.1.1 rapid size 256', ping_cmd( '1.1.1.1', :size=>256)
|
75
|
+
assert_equal 'ping 1.1.1.1 rapid size 256', ping_cmd( '1.1.1.1', :datagram_size=>256)
|
76
|
+
assert_equal 'ping 1.1.1.1 rapid pattern 0xdead', ping_cmd( '1.1.1.1', :pattern=>'0xdead')
|
77
|
+
assert_equal 'ping 1.1.1.1 rapid tos 2', ping_cmd( '1.1.1.1', :tos=>2)
|
78
|
+
assert_equal 'ping 1.1.1.1 rapid ttl 2', ping_cmd( '1.1.1.1', :ttl=>2)
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
__END__
|
87
|
+
|
88
|
+
5 packets transmitted, 5 packets received, 0% packet loss
|
89
|
+
round-trip min/avg/max/stddev = 1.483/17.024/78.904/30.940 ms
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
Possible completions:
|
94
|
+
<host> Hostname or IP address of remote host
|
95
|
+
atm Ping remote Asynchronous Transfer Mode node
|
96
|
+
bypass-routing Bypass routing table, use specified interface
|
97
|
+
count Number of ping requests to send (1..2000000000 packets)
|
98
|
+
detail Display incoming interface of received packet
|
99
|
+
do-not-fragment Don't fragment echo request packets (IPv4)
|
100
|
+
inet Force ping to IPv4 destination
|
101
|
+
inet6 Force ping to IPv6 destination
|
102
|
+
interface Source interface (multicast, all-ones, unrouted packets)
|
103
|
+
interval Delay between ping requests (seconds)
|
104
|
+
logical-router Name of logical router
|
105
|
+
+ loose-source Intermediate loose source route entry (IPv4)
|
106
|
+
mpls Ping label-switched path
|
107
|
+
no-resolve Don't attempt to print addresses symbolically
|
108
|
+
pattern Hexadecimal fill pattern
|
109
|
+
rapid Send requests rapidly (default count of 5)
|
110
|
+
record-route Record and report packet's path (IPv4)
|
111
|
+
routing-instance Routing instance for ping attempt
|
112
|
+
size Size of request packets (0..65468 bytes)
|
113
|
+
source Source address of echo request
|
114
|
+
strict Use strict source route option (IPv4)
|
115
|
+
+ strict-source Intermediate strict source route entry (IPv4)
|
116
|
+
tos IP type-of-service value (0..255)
|
117
|
+
ttl IP time-to-live value (IPv6 hop-limit value) (hops)
|
118
|
+
verbose Display detailed output
|
119
|
+
vpls Ping VPLS MAC address
|
120
|
+
wait Delay after sending last packet (seconds)
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- dev
|
10
|
-
version: 0.0.
|
10
|
+
version: 0.0.2.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-25 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
|
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
|
|
@@ -61,10 +61,11 @@ files:
|
|
61
61
|
- lib/router/error.rb
|
62
62
|
- lib/router/juniper/junos/junos.rb
|
63
63
|
- lib/router/juniper/junos/modes.rb
|
64
|
+
- lib/router/juniper/junos/ping.rb
|
64
65
|
- lib/router/juniper/junos/show.rb
|
65
66
|
- lib/router/modes.rb
|
66
67
|
has_rdoc: true
|
67
|
-
homepage:
|
68
|
+
homepage: http://github.com/jesnault/expect4r
|
68
69
|
licenses: []
|
69
70
|
|
70
71
|
post_install_message:
|