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 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 configigurations to routers
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(output)
56
- @output = 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(output, elapsed)
65
- @output, @elapsed = output, elapsed
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(cmd)
76
- @cmd = cmd
73
+ def initialize(*args)
74
+ @cmd = args[0]
77
75
  end
78
76
  def err_msg
79
- "Error: #{msg}"
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 RuntimeError, buf if ev == :timeout
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, elapsed)
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 NoChildError if child_exited?
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
@@ -32,7 +32,7 @@ module Expect4r
32
32
  end
33
33
  module Junos
34
34
  autoload :Modes, 'router/juniper/junos/modes'
35
- autoload :Show, 'router/juniper/junos/show'
35
+ autoload :Show, 'router/juniper/junos/show'
36
36
  end
37
37
  end
38
38
 
@@ -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
- def ping(arg={})
7
- if arg.is_a?(Hash)
8
- arg = {:pct_success=>100}.merge(arg)
9
- pct_success = arg[:pct_success]
10
- else
11
- pct_success = 100
12
- end
13
- case arg
14
- when String
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
- raise ArgumentError, "Invalid argument: #{arg.inspect}"
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
- output = exec "ping #{dest}", arg
26
+
22
27
  r = output[0].find { |x| x =~/Success.*[^\d](\d+) percent \((\d+)\/(\d+)\)/}
28
+
23
29
  if r &&
24
- Regexp.last_match(1) &&
25
- Regexp.last_match(2) &&
26
- Regexp.last_match(3)
27
-
28
- if $1.to_i < pct_success
29
- raise PingError('router name here', dest, pct_success, $1.to_i, $2.to_i,$3.to_i, output)
30
- else
31
- [$1.to_i,[$2.to_i,$3.to_i],output]
32
- end
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('router name here', dest, pct_success, $1.to_i, $2.to_i,$3.to_i, output)
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
@@ -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]) || string_start_with_pct_char?(output[-3])
64
+ string_start_with_pct_char?(output[-2]) ||
65
+ string_start_with_pct_char?(output[-3])
63
66
  end
64
67
 
65
68
  end
@@ -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
 
@@ -5,6 +5,7 @@ class Expect4r::J < ::Expect4r::BaseObject
5
5
  include Expect4r::Router::Common::Modes
6
6
  include Expect4r::Router::Junos::Modes
7
7
  include Expect4r::Router::Junos::Show
8
+ include Expect4r::Router::Junos::Ping
8
9
 
9
10
  def initialize(*args)
10
11
  super
@@ -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
- - 1
8
+ - 2
9
9
  - dev
10
- version: 0.0.1.dev
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-24 00:00:00 -07:00
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 Ios, IosXR, and Junos CLI.
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: