trema 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Rakefile +2 -0
  4. data/bin/trema +17 -2
  5. data/cucumber.yml +7 -0
  6. data/features/.nav +47 -0
  7. data/features/{logging.feature → api/logging.feature} +1 -7
  8. data/features/{send_flow_mod_add.feature → api/send_flow_mod_add.feature} +2 -7
  9. data/features/handlers/barrier_reply.feature +30 -0
  10. data/features/{echo_reply_handler.feature → handlers/echo_reply.feature} +14 -13
  11. data/features/handlers/hello_failed.feature +56 -0
  12. data/features/handlers/packet_in.feature +32 -0
  13. data/features/handlers/start.feature +31 -0
  14. data/features/handlers/switch_disconnected.feature +34 -0
  15. data/features/handlers/switch_ready.feature +26 -0
  16. data/features/logger/debug.feature +41 -0
  17. data/features/logger/error.feature +41 -0
  18. data/features/logger/fatal.feature +41 -0
  19. data/features/logger/info.feature +41 -0
  20. data/features/logger/warn.feature +41 -0
  21. data/features/step_definitions/README.txt +2 -0
  22. data/features/step_definitions/dump_flows_steps.rb +13 -0
  23. data/features/step_definitions/rest_api_steps.rb +40 -0
  24. data/features/step_definitions/show_stats_steps.rb +31 -4
  25. data/features/step_definitions/trema_steps.rb +72 -0
  26. data/features/support/hooks.rb +4 -1
  27. data/features/trema_delete_link/README.md +5 -0
  28. data/features/{trema_delete_link.feature → trema_delete_link/delete_link.feature} +9 -13
  29. data/features/trema_delete_link/socket_dir_option.feature +12 -0
  30. data/features/trema_killall/README.md +5 -0
  31. data/features/trema_killall/all_option.feature +20 -0
  32. data/features/{trema_killall.feature → trema_killall/killall.feature} +10 -28
  33. data/features/trema_killall/socket_dir_option.feature +38 -0
  34. data/features/trema_run/README.md +5 -0
  35. data/features/trema_run/conf_option.feature +66 -0
  36. data/features/trema_run/daemonize_option.feature +19 -0
  37. data/features/trema_run/log_dir_option.feature +32 -0
  38. data/features/trema_run/logging_level_option.feature +30 -0
  39. data/features/trema_run/openflow13_option.feature +39 -0
  40. data/features/trema_run/pid_dir_option.feature +32 -0
  41. data/features/trema_run/port_option.feature +32 -0
  42. data/features/trema_run/run.feature +83 -0
  43. data/features/trema_run/socket_dir_option.feature +34 -0
  44. data/features/trema_start/README.md +5 -0
  45. data/features/trema_start/socket_dir_option.feature +9 -0
  46. data/features/{trema_start.feature → trema_start/start.feature} +23 -24
  47. data/features/trema_stop/README.md +5 -0
  48. data/features/trema_stop/socket_dir_option.feature +9 -0
  49. data/features/{trema_stop.feature → trema_stop/stop.feature} +7 -12
  50. data/lib/trema/command.rb +15 -2
  51. data/lib/trema/controller.rb +16 -2
  52. data/lib/trema/switch.rb +25 -26
  53. data/lib/trema/version.rb +1 -1
  54. data/trema.gemspec +8 -7
  55. metadata +73 -26
  56. data/features/cleanup_on_failure.feature +0 -118
  57. data/features/step_definitions/README.md +0 -7
  58. data/features/trema_run.feature +0 -72
@@ -0,0 +1,83 @@
1
+ Feature: run
2
+ @sudo
3
+ Scenario: run controller_file
4
+ Given a file named "hello.rb" with:
5
+ """ruby
6
+ class Hello < Trema::Controller
7
+ def start(_args)
8
+ logger.info 'Hello'
9
+ end
10
+ end
11
+ """
12
+ When I run `trema run hello.rb` interactively
13
+ Then I stop the command if stdout contains:
14
+ """
15
+ Hello
16
+ """
17
+
18
+ @sudo
19
+ Scenario: "No controller class is defined" error
20
+ Given a file named "empty.rb" with:
21
+ """
22
+ """
23
+ When I trema run "empty.rb"
24
+ Then the exit status should not be 0
25
+ And the stderr should contain:
26
+ """
27
+ No controller class is defined.
28
+ """
29
+
30
+ @sudo
31
+ Scenario: SyntaxError
32
+ Given a file named "invalid_ruby.rb" with:
33
+ """
34
+ Today is 13 March 2015
35
+ """
36
+ When I run `trema run invalid_ruby.rb`
37
+ And the exit status should not be 0
38
+ Then the output should contain "(SyntaxError)"
39
+
40
+ @sudo
41
+ Scenario: NameError
42
+ Given a file named "invalid_ruby.rb" with:
43
+ """ruby
44
+ class InvalidRuby < Trema::Controller
45
+ Foo
46
+ Bar
47
+ Baz
48
+ end
49
+ """
50
+ When I run `trema run invalid_ruby.rb`
51
+ Then the exit status should not be 0
52
+ And the output should contain "uninitialized constant InvalidRuby::Foo (NameError)"
53
+
54
+ @sudo
55
+ Scenario: RuntimeError
56
+ Given a file named "start_fail.rb" with:
57
+ """ruby
58
+ class StartFail < Trema::Controller
59
+ def start(_args)
60
+ fail 'bang!'
61
+ end
62
+ end
63
+ """
64
+ When I run `trema run start_fail.rb`
65
+ Then the exit status should not be 0
66
+ And the output should contain "bang! (RuntimeError)"
67
+
68
+ @sudo
69
+ Scenario: cleanup on failure
70
+ Given a file named "switch_ready_fail.rb" with:
71
+ """ruby
72
+ class SwitchReadyFail < Trema::Controller
73
+ def switch_ready(_dpid)
74
+ fail 'bang!'
75
+ end
76
+ end
77
+ """
78
+ When I run `trema -v run switch_ready_fail.rb -c trema.conf`
79
+ Then virtual links should not exist
80
+ And the following files should not exist:
81
+ | SwitchReadyFail.pid |
82
+ | vhost.host1.pid |
83
+ | vhost.host2.pid |
@@ -0,0 +1,34 @@
1
+ Feature: -S (--socket_dir) option
2
+
3
+ -S (--socket_dir) option specifies the location to put socket files
4
+
5
+ Background:
6
+ Given a file named "null_controller.rb" with:
7
+ """ruby
8
+ class NullController < Trema::Controller; end
9
+ """
10
+
11
+ @sudo
12
+ Scenario: -S option
13
+ Given a socket directory named "sock"
14
+ When I successfully run `trema run null_controller.rb -S sock -d`
15
+ And I run `sleep 3`
16
+ Then a socket file named "sock/NullController.ctl" should exist
17
+ And a socket file named "sock/trema.NullController.ctl" should exist
18
+
19
+ @sudo
20
+ Scenario: --socket_dir option
21
+ Given a socket directory named "sock"
22
+ When I successfully run `trema run null_controller.rb --socket_dir sock -d`
23
+ And I run `sleep 3`
24
+ Then a socket file named "sock/NullController.ctl" should exist
25
+ And a socket file named "sock/trema.NullController.ctl" should exist
26
+
27
+ @sudo
28
+ Scenario: "No such directory" error
29
+ When I run `trema run null_controller.rb -S sock -d`
30
+ Then the exit status should not be 0
31
+ And the stderr should contain:
32
+ """
33
+ No such directory
34
+ """
@@ -0,0 +1,5 @@
1
+ `trema start` starts the stopped vswitch or vhost again.
2
+
3
+ ```
4
+ trema [global options] start [command options] name
5
+ ```
@@ -0,0 +1,9 @@
1
+ Feature: -S (--socket_dir) option
2
+
3
+ -S (--socket_dir) option specifies the location to find socket files
4
+
5
+ @sudo @wip
6
+ Scenario: -S option
7
+
8
+ @sudo @wip
9
+ Scenario: --socket_dir option
@@ -1,34 +1,34 @@
1
- Feature: trema start command
1
+ Feature: start
2
2
  Background:
3
- Given I set the environment variables to:
4
- | variable | value |
5
- | TREMA_LOG_DIR | . |
6
- | TREMA_PID_DIR | . |
7
- | TREMA_SOCKET_DIR | . |
8
- And a file named "switch_ready_controller.rb" with:
9
- """
3
+ Given a file named "switch_ready_controller.rb" with:
4
+ """ruby
10
5
  class SwitchReadyController < Trema::Controller
6
+ def start(_args)
7
+ @switch_ready_invoked = 0
8
+ end
9
+
11
10
  def switch_ready(dpid)
12
- if @reconnect
11
+ if @switch_ready_invoked > 0
13
12
  logger.info "Switch #{dpid.to_hex} connected again."
14
13
  else
15
14
  logger.info "Switch #{dpid.to_hex} connected."
16
- @reconnect = true
17
15
  end
16
+ @switch_ready_invoked += 1
18
17
  end
19
18
  end
20
19
  """
21
20
  And a file named "trema.conf" with:
22
- """
21
+ """ruby
23
22
  vswitch { datapath_id 0xabc }
24
23
  vhost('host1') { ip '192.168.0.1' }
25
24
  link '0xabc', 'host1'
26
25
  """
27
- And I run `trema run switch_ready_controller.rb -c trema.conf -d`
26
+ And I successfully run `trema run switch_ready_controller.rb -c trema.conf -d`
28
27
 
29
28
  @sudo
30
- Scenario: trema stop and start switch_name
29
+ Scenario: stop and start a switch
31
30
  Given I successfully run `trema stop 0xabc`
31
+ And I successfully run `sleep 3`
32
32
  When I successfully run `trema start 0xabc`
33
33
  And I successfully run `sleep 10`
34
34
  Then the file "SwitchReadyController.log" should contain:
@@ -37,16 +37,15 @@ Feature: trema start command
37
37
  """
38
38
 
39
39
  @sudo
40
- Scenario: trema stop and start host_name
40
+ Scenario: stop and start host_name
41
41
  Given I successfully run `trema stop host1`
42
42
  And I successfully run `sleep 3`
43
43
  When I successfully run `trema start host1`
44
44
  And I successfully run `sleep 10`
45
- Then the following files should exist:
46
- | vhost.host1.pid |
45
+ Then the file named "vhost.host1.pid" should exist
47
46
 
48
47
  @sudo
49
- Scenario: start switch_name (already running)
48
+ Scenario: "Open vSwitch is already running" error
50
49
  When I run `trema start 0xabc`
51
50
  Then the exit status should not be 0
52
51
  And the output should contain:
@@ -54,16 +53,16 @@ Feature: trema start command
54
53
  error: Open vSwitch (dpid = 2748) is already running!
55
54
  """
56
55
 
57
- @sudo
58
- Scenario: start host_name (already running)
56
+ @sudo @wip
57
+ Scenario: "vswitch is already running" error
59
58
  When I run `trema start host1`
60
59
  Then the exit status should not be 0
61
- # And the output should contain:
62
- # """
63
- # error: vhost "host1" is already running!
64
- # """
60
+ And the output should contain:
61
+ """
62
+ error: vhost "host1" is already running!
63
+ """
65
64
 
66
- @sudo
65
+ @sudo @announce-output
67
66
  Scenario: start NO_SUCH_NAME
68
67
  When I run `trema start NO_SUCH_NAME`
69
68
  Then the exit status should not be 0
@@ -0,0 +1,5 @@
1
+ `trema stop` stops a vswitch or a vhost.
2
+
3
+ ```
4
+ trema [global options] stop [command options] name
5
+ ```
@@ -0,0 +1,9 @@
1
+ Feature: -S (--socket_dir) option
2
+
3
+ -S (--socket_dir) option specifies the location to find socket files
4
+
5
+ @sudo @wip
6
+ Scenario: -S option
7
+
8
+ @sudo @wip
9
+ Scenario: --socket_dir option
@@ -1,12 +1,7 @@
1
- Feature: trema stop command
1
+ Feature: stop
2
2
  Background:
3
- Given I set the environment variables to:
4
- | variable | value |
5
- | TREMA_LOG_DIR | . |
6
- | TREMA_PID_DIR | . |
7
- | TREMA_SOCKET_DIR | . |
8
- And a file named "switch_disconnected_controller.rb" with:
9
- """
3
+ Given a file named "switch_disconnected_controller.rb" with:
4
+ """ruby
10
5
  class SwitchDisconnectedController < Trema::Controller
11
6
  def switch_disconnected(dpid)
12
7
  logger.info "Switch #{dpid.to_hex} is disconnected."
@@ -14,7 +9,7 @@ Feature: trema stop command
14
9
  end
15
10
  """
16
11
  And a file named "trema.conf" with:
17
- """
12
+ """ruby
18
13
  vswitch { datapath_id 0xabc }
19
14
 
20
15
  vhost('host1') { ip '192.168.0.1' }
@@ -23,10 +18,10 @@ Feature: trema stop command
23
18
  link '0xabc', 'host1'
24
19
  link '0xabc', 'host2'
25
20
  """
26
- And I run `trema run switch_disconnected_controller.rb -c trema.conf -d`
21
+ And I trema run "switch_disconnected_controller.rb" with the configuration "trema.conf"
27
22
 
28
23
  @sudo
29
- Scenario: stop switch_name
24
+ Scenario: stop a switch
30
25
  When I successfully run `trema stop 0xabc`
31
26
  And I successfully run `sleep 10`
32
27
  Then the file "SwitchDisconnectedController.log" should contain:
@@ -35,7 +30,7 @@ Feature: trema stop command
35
30
  """
36
31
 
37
32
  @sudo
38
- Scenario: stop host_name
33
+ Scenario: stop a host
39
34
  When I successfully run `trema stop host1`
40
35
  And I successfully run `sleep 5`
41
36
  Then the file "vhost.host1.pid" should not exist
data/lib/trema/command.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'English'
2
2
 
3
3
  module Trema
4
+ class InvalidLoggingLevel < StandardError; end
5
+
4
6
  # trema command
5
7
  # rubocop:disable ClassLength
6
8
  class Command
@@ -21,8 +23,19 @@ module Trema
21
23
  @args = args
22
24
  @daemon = options[:daemonize]
23
25
 
24
- Controller.logging_level =
25
- options[:verbose] ? ::Logger::DEBUG : ::Logger::INFO
26
+ begin
27
+ Controller.logging_level =
28
+ { debug: ::Logger::DEBUG,
29
+ info: ::Logger::INFO,
30
+ warn: ::Logger::WARN,
31
+ error: ::Logger::ERROR,
32
+ fatal: ::Logger::FATAL }.fetch(options[:logging_level].to_sym)
33
+ Controller.logging_level = ::Logger::DEBUG if options[:verbose]
34
+ rescue KeyError
35
+ raise(InvalidLoggingLevel,
36
+ "Invalid logging level: #{options[:logging_level]}")
37
+ end
38
+
26
39
  $LOAD_PATH.unshift File.expand_path(File.dirname(@args.first))
27
40
  load @args.first
28
41
  port_number = (options[:port] || Controller::DEFAULT_TCP_PORT).to_i
@@ -7,6 +7,8 @@ require 'trema/logger'
7
7
  require 'trema/monkey_patch/integer'
8
8
 
9
9
  module Trema
10
+ class NoControllerDefined < StandardError; end
11
+
10
12
  # The base class of Trema controller. Subclass and override handlers
11
13
  # to implement a custom OpenFlow controller.
12
14
  #
@@ -134,7 +136,9 @@ module Trema
134
136
 
135
137
  # @private
136
138
  def self.create(port_number = DEFAULT_TCP_PORT)
137
- fail 'No controller class is defined.' unless @controller_klass
139
+ unless @controller_klass
140
+ fail NoControllerDefined, 'No controller class is defined.'
141
+ end
138
142
  @controller_klass.new(port_number)
139
143
  end
140
144
 
@@ -268,8 +272,16 @@ module Trema
268
272
  end
269
273
 
270
274
  def create_and_register_new_switch(socket)
271
- switch = Switch.new(socket).init
275
+ switch = Switch.new(socket)
276
+ switch.init
272
277
  SWITCH[switch.datapath_id] = switch
278
+ rescue Switch::InitError
279
+ error_message = switch.error_message
280
+ case error_message
281
+ when OpenFlow10::Error::HelloFailed, OpenFlow13::Error::HelloFailed
282
+ maybe_send_handler :hello_failed, error_message
283
+ raise $ERROR_INFO
284
+ end
273
285
  end
274
286
 
275
287
  def unregister_switch(datapath_id)
@@ -309,6 +321,8 @@ module Trema
309
321
  else
310
322
  fail "Invalid Port Status message: #{message.inspect}"
311
323
  end
324
+ when Barrier::Reply
325
+ maybe_send_handler :barrier_reply, datapath_id, message
312
326
  else
313
327
  fail "Unknown OpenFlow message: #{message.inspect}"
314
328
  end
data/lib/trema/switch.rb CHANGED
@@ -3,6 +3,10 @@ require 'pio'
3
3
  module Trema
4
4
  # OpenFlow switch.
5
5
  class Switch
6
+ attr_reader :error_message
7
+
8
+ class InitError < StandardError; end
9
+
6
10
  include Pio
7
11
 
8
12
  OPENFLOW_HEADER_LENGTH = 8
@@ -35,51 +39,46 @@ module Trema
35
39
  private
36
40
 
37
41
  def exchange_hello_messages
38
- fail 'Failed to exchange Hello messages' unless read.is_a?(Hello)
39
42
  write Hello.new
43
+ expect_receiving Hello
40
44
  end
41
45
 
42
46
  def exchange_echo_messages
43
47
  write Echo::Request.new
44
- loop do
45
- message = read
46
- if message.is_a?(Echo::Reply)
47
- break
48
- else
49
- handle_early message 'Failed to exchange Echo messages'
50
- end
51
- end
48
+ expect_receiving Echo::Reply
52
49
  end
53
50
 
54
51
  def exchange_features_messages
55
52
  write Features::Request.new
53
+ @features_reply = expect_receiving(Features::Reply)
54
+ end
55
+
56
+ # rubocop:disable MethodLength
57
+ def expect_receiving(expected_message_klass)
56
58
  loop do
57
59
  message = read
58
- if message.is_a?(Features::Reply)
59
- @features_reply = message
60
- break
60
+ case message
61
+ when expected_message_klass
62
+ return message
63
+ when Echo::Request
64
+ write Echo::Reply.new(xid: message.xid)
65
+ when PacketIn, PortStatus # , FlowRemoved (not implemented yet)
66
+ return
67
+ when OpenFlow10::Error::HelloFailed, OpenFlow13::Error::HelloFailed
68
+ @error_message = message
69
+ fail InitError, message.description
61
70
  else
62
- handle_early message 'Failed to exchange Features messages'
71
+ fail "Failed to receive #{expected_message_klass} message"
63
72
  end
64
73
  end
65
74
  end
66
-
67
- def handle_early(message, fail_message)
68
- case message
69
- when Echo::Request
70
- write Echo::Reply.new xid: message.xid
71
- when PacketIn, FlowRemoved, PortStatus
72
- return
73
- else
74
- fail fail_message
75
- end
76
- end
75
+ # rubocop:enable MethodLength
77
76
 
78
77
  def read_openflow_binary
79
78
  header_binary = drain(OPENFLOW_HEADER_LENGTH)
80
79
  header = OpenFlowHeaderParser.read(header_binary)
81
- body_binary = drain(header.message_length - OPENFLOW_HEADER_LENGTH)
82
- fail if (header_binary + body_binary).length != header.message_length
80
+ body_binary = drain(header.length - OPENFLOW_HEADER_LENGTH)
81
+ fail if (header_binary + body_binary).length != header.length
83
82
  header_binary + body_binary
84
83
  end
85
84
 
data/lib/trema/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Base module.
2
2
  module Trema
3
3
  # gem version.
4
- VERSION = '0.5.1'.freeze
4
+ VERSION = '0.6.0'.freeze
5
5
  end
data/trema.gemspec CHANGED
@@ -22,21 +22,22 @@ Gem::Specification.new do |gem|
22
22
  gem.test_files = `git ls-files -- {spec,features}/*`.split("\n")
23
23
 
24
24
  gem.add_dependency 'bundler', '~> 1.10.6'
25
- gem.add_dependency 'gli', '~> 2.13.1'
26
- gem.add_dependency 'phut', '~> 0.6.6'
27
- gem.add_dependency 'pio', '~> 0.24.1'
25
+ gem.add_dependency 'gli', '~> 2.13.2'
26
+ gem.add_dependency 'phut', '~> 0.6.9'
27
+ gem.add_dependency 'pio', '~> 0.26.0'
28
28
  gem.add_dependency 'rake'
29
29
 
30
30
  # Docs
31
+ gem.add_development_dependency 'relish', '~> 0.7.1'
31
32
  gem.add_development_dependency 'yard', '~> 0.8.7.6'
32
33
 
33
34
  # Test
34
- gem.add_development_dependency 'aruba', '~> 0.8.1'
35
- gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.7'
35
+ gem.add_development_dependency 'aruba', '~> 0.9.0'
36
+ gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.8'
36
37
  gem.add_development_dependency 'coveralls', '~> 0.8.2'
37
38
  gem.add_development_dependency 'cucumber', '~> 2.0.2'
38
- gem.add_development_dependency 'reek', '~> 3.1'
39
+ gem.add_development_dependency 'reek', '~> 3.3.1'
39
40
  gem.add_development_dependency 'rspec', '~> 3.3.0'
40
41
  gem.add_development_dependency 'rspec-given', '~> 3.7.1'
41
- gem.add_development_dependency 'rubocop', '~> 0.32.1'
42
+ gem.add_development_dependency 'rubocop', '~> 0.34.0'
42
43
  end