expect4r 0.0.1.dev → 0.0.2.dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|