trema 0.9.0 → 0.10.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/bin/trema +44 -19
- data/features/.nav +5 -4
- data/features/logger/unknown.feature +47 -0
- data/features/step_definitions/dump_flows_steps.rb +2 -3
- data/features/step_definitions/show_stats_steps.rb +3 -3
- data/features/support/hooks.rb +1 -1
- data/features/trema_dump_flows/README.md +5 -0
- data/features/trema_dump_flows/dump_flows.feature +15 -9
- data/features/trema_dump_flows/socket_dir_option.feature +47 -0
- data/features/trema_netns/netns.feature +7 -7
- data/features/trema_reset_stats/reset_stats.feature +37 -0
- data/features/trema_run/conf_option.feature +1 -1
- data/features/trema_run/logging_level_option.feature +2 -2
- data/features/trema_run/socket_dir_option.feature +0 -2
- data/lib/trema/command.rb +7 -23
- data/lib/trema/controller.rb +11 -17
- data/lib/trema/drb.rb +12 -6
- data/lib/trema/logger.rb +4 -0
- data/lib/trema/switch.rb +4 -4
- data/lib/trema/version.rb +1 -1
- data/trema.gemspec +6 -6
- metadata +19 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ba4d24fdaf57d51c18d72a343c23d3ceb6f5ffb
|
4
|
+
data.tar.gz: c982a5ed2c86f493542ed578c2a4b5639efdfe01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3101604fddd57d89825dd25b82adec759170a2683b814150d87b295d50c35b6d4be698b0e5400a8513ebc2344ba1e4e84dc2ba370dc73780a1c408e7a178e551
|
7
|
+
data.tar.gz: b41a030af51e5ef322b61021268cf83b4080e1c9618ca355c2b0a5a7876b4fab3445aa0c35ac51bb02b90ead858eb459e3c0bdf14b30ae453650418da0abe512
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,13 @@
|
|
3
3
|
## develop (unreleased)
|
4
4
|
|
5
5
|
|
6
|
+
## 0.10.0 (2/17/2015)
|
7
|
+
### New features
|
8
|
+
* [#418](https://github.com/trema/trema/pull/418): Ruby 2.3.0 support
|
9
|
+
* [#419](https://github.com/trema/trema/pull/419): Add trema reset_stats command
|
10
|
+
* [#421](https://github.com/trema/trema/pull/421): Add Trema::Logger#unknown method
|
11
|
+
|
12
|
+
|
6
13
|
## 0.9.0 (12/17/2015)
|
7
14
|
### New features
|
8
15
|
* [#415](https://github.com/trema/trema/pull/415): Add `trema netns [command]` command.
|
data/bin/trema
CHANGED
@@ -11,6 +11,7 @@ require 'trema'
|
|
11
11
|
# OpenFlow controller framework.
|
12
12
|
module Trema
|
13
13
|
# trema command.
|
14
|
+
# rubocop:disable ModuleLength
|
14
15
|
module App
|
15
16
|
extend GLI::App
|
16
17
|
|
@@ -50,22 +51,33 @@ module Trema
|
|
50
51
|
Phut.log_dir = options[:log_dir]
|
51
52
|
Phut.socket_dir = options[:socket_dir]
|
52
53
|
Pio::OpenFlow.switch_version('OpenFlow13') if options[:openflow13]
|
54
|
+
begin
|
55
|
+
options[:logging_level] =
|
56
|
+
{ debug: ::Logger::DEBUG,
|
57
|
+
info: ::Logger::INFO,
|
58
|
+
warn: ::Logger::WARN,
|
59
|
+
error: ::Logger::ERROR,
|
60
|
+
fatal: ::Logger::FATAL,
|
61
|
+
unknown: ::Logger::UNKNOWN
|
62
|
+
}.fetch(options[:logging_level].to_sym)
|
63
|
+
options[:logging_level] = ::Logger::DEBUG if global_options[:verbose]
|
64
|
+
rescue KeyError
|
65
|
+
raise(ArgumentError,
|
66
|
+
"Invalid log level: #{options[:logging_level]}")
|
67
|
+
end
|
53
68
|
require 'trema/switch'
|
54
69
|
Trema::Command.new.run(args, global_options.merge(options))
|
55
70
|
end
|
56
71
|
end
|
57
72
|
|
58
73
|
desc 'Print all flow entries'
|
59
|
-
arg_name '
|
74
|
+
arg_name 'switch'
|
60
75
|
command :dump_flows do |c|
|
61
|
-
c.desc 'Location to
|
76
|
+
c.desc 'Location to find socket files'
|
62
77
|
c.flag [:S, :socket_dir], default_value: Trema::DEFAULT_SOCKET_DIR
|
63
78
|
|
64
79
|
c.action do |_global_options, options, args|
|
65
|
-
|
66
|
-
args.each do |each|
|
67
|
-
puts Trema.fetch(each, options.fetch(:socket_dir)).dump_flows
|
68
|
-
end
|
80
|
+
puts Trema.fetch(args.first, options.fetch(:socket_dir)).dump_flows
|
69
81
|
end
|
70
82
|
end
|
71
83
|
|
@@ -82,8 +94,8 @@ module Trema
|
|
82
94
|
c.flag [:S, :socket_dir], default_value: Trema::DEFAULT_SOCKET_DIR
|
83
95
|
|
84
96
|
c.action do |_global_options, options, _args|
|
85
|
-
|
86
|
-
|
97
|
+
raise '--source option is mandatory' if options[:source].nil?
|
98
|
+
raise '--dest option is mandatory' if options[:dest].nil?
|
87
99
|
dest = Trema.fetch(options.fetch(:dest), options.fetch(:socket_dir))
|
88
100
|
Phut::VhostDaemon.
|
89
101
|
process(options.fetch(:source), options.fetch(:socket_dir)).
|
@@ -126,6 +138,16 @@ module Trema
|
|
126
138
|
end
|
127
139
|
end
|
128
140
|
|
141
|
+
desc 'Reset stats of packets'
|
142
|
+
command :reset_stats do |c|
|
143
|
+
c.desc 'Location to find socket files'
|
144
|
+
c.flag [:S, :socket_dir], default_value: Trema::DEFAULT_SOCKET_DIR
|
145
|
+
|
146
|
+
c.action do |_global_options, options, _args|
|
147
|
+
Trema.vhosts(options[:socket_dir]).each(&:reset_stats)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
129
151
|
desc "Brings a switch's specified port up"
|
130
152
|
command :port_up do |c|
|
131
153
|
c.desc 'switch name'
|
@@ -136,8 +158,8 @@ module Trema
|
|
136
158
|
c.flag [:S, :socket_dir], default_value: Trema::DEFAULT_SOCKET_DIR
|
137
159
|
|
138
160
|
c.action do |_global_options, options, _args|
|
139
|
-
|
140
|
-
|
161
|
+
raise '--switch option is mandatory' if options[:switch].nil?
|
162
|
+
raise '--port option is mandatory' if options[:port].nil?
|
141
163
|
Trema.trema_processes(options[:socket_dir]).each do |trema|
|
142
164
|
begin
|
143
165
|
trema.port_up(options[:switch], options[:port].to_i)
|
@@ -158,8 +180,8 @@ module Trema
|
|
158
180
|
c.flag [:S, :socket_dir], default_value: Trema::DEFAULT_SOCKET_DIR
|
159
181
|
|
160
182
|
c.action do |_global_options, options, _args|
|
161
|
-
|
162
|
-
|
183
|
+
raise '--switch option is mandatory' if options[:switch].nil?
|
184
|
+
raise '--port option is mandatory' if options[:port].nil?
|
163
185
|
Trema.trema_processes(options[:socket_dir]).each do |trema|
|
164
186
|
begin
|
165
187
|
trema.port_down(options[:switch], options[:port].to_i)
|
@@ -234,37 +256,40 @@ module Trema
|
|
234
256
|
end
|
235
257
|
end
|
236
258
|
|
259
|
+
# rubocop:disable LineLength
|
237
260
|
desc 'Opens a new shell or runs a command in the specified network namespace'
|
238
261
|
arg_name 'name [command]'
|
239
262
|
command :netns do |c|
|
240
|
-
c.action do |
|
263
|
+
c.action do |_global_options, _options, args|
|
241
264
|
command_args = args[1..-1]
|
242
|
-
if command_args && command_args.
|
265
|
+
if command_args && !command_args.empty?
|
243
266
|
system "sudo ip netns exec #{args[0]} #{command_args.join(' ')}"
|
244
267
|
else
|
245
268
|
system "sudo ip netns exec #{args[0]} #{ENV['SHELL']}"
|
246
269
|
end
|
247
270
|
end
|
248
271
|
end
|
272
|
+
# rubocop:enable LineLength
|
249
273
|
|
250
274
|
default_command :help
|
251
275
|
|
252
276
|
on_error do |e|
|
253
277
|
case e
|
254
278
|
when OptionParser::ParseError,
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
279
|
+
Trema::NoControllerDefined,
|
280
|
+
Phut::OpenVswitch::AlreadyRunning,
|
281
|
+
GLI::UnknownCommandArgument,
|
282
|
+
ArgumentError
|
259
283
|
true
|
260
284
|
when Interrupt
|
261
285
|
exit false
|
262
286
|
else
|
263
287
|
# show backtrace
|
264
|
-
|
288
|
+
raise e
|
265
289
|
end
|
266
290
|
end
|
267
291
|
|
268
292
|
exit run(ARGV)
|
269
293
|
end
|
294
|
+
# rubocop:enable ModuleLength
|
270
295
|
end
|
data/features/.nav
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
- trema_run (trema run command):
|
2
2
|
- run.feature (basic usage)
|
3
|
+
- conf_option.feature
|
4
|
+
- daemonize_option.feature
|
5
|
+
- openflow13_option.feature
|
3
6
|
- log_dir_option.feature
|
4
7
|
- pid_dir_option.feature
|
5
8
|
- socket_dir_option.feature
|
6
|
-
- conf_option.feature
|
7
|
-
- daemonize_option.feature
|
8
9
|
- logging_level_option.feature
|
9
|
-
- openflow13_option.feature
|
10
10
|
- port_option.feature
|
11
11
|
|
12
12
|
- trema_dump_flows (trema dump_flows command):
|
13
|
-
- dump_flows.feature
|
13
|
+
- dump_flows.feature (basic usage)
|
14
14
|
|
15
15
|
- trema_killall (trema killall command):
|
16
16
|
- killall.feature (basic usage)
|
@@ -38,6 +38,7 @@
|
|
38
38
|
- warn.feature
|
39
39
|
- error.feature
|
40
40
|
- fatal.feature
|
41
|
+
- unknown.feature
|
41
42
|
|
42
43
|
- api (controller API):
|
43
44
|
- logging.feature
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Feature: Trema::Controller#logger.unknown
|
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 "hello.rb" with:
|
9
|
+
"""ruby
|
10
|
+
class Hello < Trema::Controller
|
11
|
+
def start(_args)
|
12
|
+
logger.unknown 'Konnichi Wa'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
"""
|
16
|
+
|
17
|
+
@sudo
|
18
|
+
Scenario: the default logging level
|
19
|
+
When I trema run "hello.rb" interactively
|
20
|
+
And sleep 2
|
21
|
+
And I trema killall "Hello"
|
22
|
+
Then the output should contain "Konnichi Wa"
|
23
|
+
And the file "Hello.log" should contain "ANY -- : Konnichi Wa"
|
24
|
+
|
25
|
+
@sudo
|
26
|
+
Scenario: --logging_level unknown
|
27
|
+
When I run `trema run hello.rb --logging_level unknown` interactively
|
28
|
+
And sleep 2
|
29
|
+
And I trema killall "Hello"
|
30
|
+
Then the output should contain "Konnichi Wa"
|
31
|
+
And the file "Hello.log" should contain "ANY -- : Konnichi Wa"
|
32
|
+
|
33
|
+
@sudo
|
34
|
+
Scenario: -v
|
35
|
+
When I run `trema -v run hello.rb` interactively
|
36
|
+
And sleep 2
|
37
|
+
And I trema killall "Hello"
|
38
|
+
Then the output should contain "Konnichi Wa"
|
39
|
+
And the file "Hello.log" should contain "ANY -- : Konnichi Wa"
|
40
|
+
|
41
|
+
@sudo
|
42
|
+
Scenario: --verbose
|
43
|
+
When I run `trema --verbose run hello.rb` interactively
|
44
|
+
And sleep 2
|
45
|
+
And I trema killall "Hello"
|
46
|
+
Then the output should contain "Konnichi Wa"
|
47
|
+
And the file "Hello.log" should contain "ANY -- : Konnichi Wa"
|
@@ -1,9 +1,8 @@
|
|
1
1
|
Then(/^the switch "(.*?)" has (\d+) flow entr(?:y|ies)$/) do |switch, number|
|
2
|
-
|
3
|
-
command = "trema dump_flows #{switch} -S ."
|
2
|
+
command = "trema dump_flows #{switch}"
|
4
3
|
step "I successfully run `#{command}`"
|
5
4
|
dump_flows = aruba.command_monitor.find(Aruba.platform.detect_ruby(command))
|
6
|
-
expect(dump_flows.output.split("\n").size
|
5
|
+
expect(dump_flows.output.split("\n").size).to eq(number.to_i)
|
7
6
|
end
|
8
7
|
|
9
8
|
Then(/^the switch "(.*?)" has no flow entry$/) do |switch|
|
@@ -15,7 +15,7 @@ Then(/^the number of packets sent from "(.*?)" should be:$/) do |host_name, tabl
|
|
15
15
|
when /-> (\S+) = (\d+) packet/
|
16
16
|
result[Regexp.last_match(1)] = Regexp.last_match(2).to_i
|
17
17
|
else
|
18
|
-
|
18
|
+
raise "Failed to parse line '#{each}'"
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -45,7 +45,7 @@ Then(/^the number of packets received by "(.*?)" should be:$/) do |host_name, ta
|
|
45
45
|
next unless received
|
46
46
|
result[Regexp.last_match(1)] = Regexp.last_match(3).to_i
|
47
47
|
else
|
48
|
-
|
48
|
+
raise "Failed to parse line '#{each}'"
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -74,7 +74,7 @@ Then(/^the total number of received packets should be:$/) do |table|
|
|
74
74
|
next unless received
|
75
75
|
result += Regexp.last_match(3).to_i
|
76
76
|
else
|
77
|
-
|
77
|
+
raise "Failed to parse line '#{each}'"
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/features/support/hooks.rb
CHANGED
@@ -19,31 +19,37 @@ Feature: dump_flows
|
|
19
19
|
"""
|
20
20
|
And a file named "trema.conf" with:
|
21
21
|
"""ruby
|
22
|
-
vswitch { datapath_id 0xabc }
|
22
|
+
vswitch('of_switch') { datapath_id 0xabc }
|
23
23
|
"""
|
24
24
|
|
25
25
|
@sudo
|
26
26
|
Scenario: dump_flows (no flow entries)
|
27
27
|
Given I trema run "noop_controller.rb" with the configuration "trema.conf"
|
28
|
-
When I successfully run `trema dump_flows
|
29
|
-
Then the output from "trema dump_flows
|
28
|
+
When I successfully run `trema dump_flows of_switch`
|
29
|
+
Then the output from "trema dump_flows of_switch" should contain exactly ""
|
30
30
|
|
31
31
|
@sudo
|
32
32
|
Scenario: dump_flows (one flow entry)
|
33
33
|
Given I trema run "flow_mod_controller.rb" with the configuration "trema.conf"
|
34
|
-
When I successfully run `trema dump_flows
|
35
|
-
Then the output
|
34
|
+
When I successfully run `trema dump_flows of_switch`
|
35
|
+
Then the output should match:
|
36
|
+
"""
|
37
|
+
^cookie=0x0, duration=\d+\.\d+s, table=0, n_packets=0, n_bytes=0, idle_age=\d+, priority=0 actions=drop
|
38
|
+
"""
|
36
39
|
|
37
40
|
@sudo
|
38
41
|
Scenario: dump_flows OpenFlow 1.3 (no flow entries)
|
39
42
|
Given I use OpenFlow 1.3
|
40
43
|
And I trema run "noop_controller.rb" with the configuration "trema.conf"
|
41
|
-
When I successfully run `trema dump_flows
|
42
|
-
Then the output from "trema dump_flows
|
44
|
+
When I successfully run `trema dump_flows of_switch`
|
45
|
+
Then the output from "trema dump_flows of_switch" should contain exactly ""
|
43
46
|
|
44
47
|
@sudo
|
45
48
|
Scenario: dump_flows OpenFlow 1.3 (one flow entry)
|
46
49
|
Given I use OpenFlow 1.3
|
47
50
|
And I trema run "flow_mod_controller.rb" with the configuration "trema.conf"
|
48
|
-
When I successfully run `trema dump_flows
|
49
|
-
Then the output
|
51
|
+
When I successfully run `trema dump_flows of_switch`
|
52
|
+
Then the output should match:
|
53
|
+
"""
|
54
|
+
^cookie=0x0, duration=\d+\.\d+s, table=0, n_packets=0, n_bytes=0, priority=0 actions=drop
|
55
|
+
"""
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Feature: -S (--socket_dir) option
|
2
|
+
|
3
|
+
-S (--socket_dir) option specifies the location to find socket files
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given I set the environment variables to:
|
7
|
+
| variable | value |
|
8
|
+
| TREMA_LOG_DIR | . |
|
9
|
+
| TREMA_PID_DIR | . |
|
10
|
+
And a file named "flow_mod_controller.rb" with:
|
11
|
+
"""ruby
|
12
|
+
class FlowModController < Trema::Controller
|
13
|
+
def switch_ready(datapath_id)
|
14
|
+
send_flow_mod_add(datapath_id, match: Match.new)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
"""
|
18
|
+
And a file named "trema.conf" with:
|
19
|
+
"""ruby
|
20
|
+
vswitch('of_switch') { datapath_id 0xabc }
|
21
|
+
"""
|
22
|
+
And I successfully run `trema run flow_mod_controller.rb -c trema.conf -S . -d`
|
23
|
+
|
24
|
+
@sudo
|
25
|
+
Scenario: -S option
|
26
|
+
When I successfully run `trema dump_flows of_switch -S .`
|
27
|
+
Then the output should match:
|
28
|
+
"""
|
29
|
+
^cookie=0x0, duration=\d+\.\d+s, table=0, n_packets=0, n_bytes=0, idle_age=\d+, priority=0 actions=drop
|
30
|
+
"""
|
31
|
+
|
32
|
+
@sudo
|
33
|
+
Scenario: --socket_dir option
|
34
|
+
When I successfully run `trema dump_flows of_switch --socket_dir .`
|
35
|
+
Then the output should match:
|
36
|
+
"""
|
37
|
+
^cookie=0x0, duration=\d+\.\d+s, table=0, n_packets=0, n_bytes=0, idle_age=\d+, priority=0 actions=drop
|
38
|
+
"""
|
39
|
+
|
40
|
+
@sudo
|
41
|
+
Scenario: "No such directory" error
|
42
|
+
When I run `trema dump_flows of_switch --socket_dir sock`
|
43
|
+
Then the exit status should not be 0
|
44
|
+
And the stderr should contain:
|
45
|
+
"""
|
46
|
+
No such directory
|
47
|
+
"""
|
@@ -45,11 +45,11 @@ Feature: netns
|
|
45
45
|
@sudo
|
46
46
|
Scenario Outline: netns namespece command
|
47
47
|
When I run `<command>`
|
48
|
-
Then the stdout should contain "<
|
48
|
+
Then the stdout should contain "<message>"
|
49
49
|
Examples:
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
| command | message |
|
51
|
+
| trema netns host1 ip add show host1 | 192.168.1.2 |
|
52
|
+
| trema netns host1 -- ping -c1 192.168.1.3 | 1 packets transmitted, 1 received, |
|
53
|
+
| trema netns host1 "ping -c1 192.168.1.3" | 1 packets transmitted, 1 received, |
|
54
|
+
| trema netns host1 "ip addr show lo" | 127.0.0.1 |
|
55
|
+
| trema netns host1 ls $PWD | simple_hub.conf |
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Feature: reset_stats
|
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 "flood.rb" with:
|
9
|
+
"""ruby
|
10
|
+
class Flood < Trema::Controller
|
11
|
+
def packet_in(datapath_id, message)
|
12
|
+
send_packet_out(
|
13
|
+
datapath_id,
|
14
|
+
packet_in: message,
|
15
|
+
actions: SendOutPort.new(:flood)
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
"""
|
20
|
+
And a file named "trema.conf" with:
|
21
|
+
"""ruby
|
22
|
+
vswitch { datapath_id 0xabc }
|
23
|
+
vhost('host1') { ip '192.168.0.1' }
|
24
|
+
vhost('host2') { ip '192.168.0.2' }
|
25
|
+
link '0xabc', 'host1'
|
26
|
+
link '0xabc', 'host2'
|
27
|
+
"""
|
28
|
+
|
29
|
+
@sudo
|
30
|
+
Scenario: run controller_file
|
31
|
+
When I successfully run `trema run flood.rb -c trema.conf -d`
|
32
|
+
And I successfully run `trema send_packets --source host1 --dest host2`
|
33
|
+
And I successfully run `trema reset_stats`
|
34
|
+
Then I successfully run `trema show_stats host1`
|
35
|
+
And the output from "trema show_stats host1" should contain exactly ""
|
36
|
+
And I successfully run `trema show_stats host2`
|
37
|
+
And the output from "trema show_stats host2" should contain exactly ""
|
@@ -54,7 +54,7 @@ Feature: -c (--conf) option
|
|
54
54
|
"""
|
55
55
|
When I run `trema run null_controller.rb -c invalid_trema.conf`
|
56
56
|
Then the exit status should not be 0
|
57
|
-
Then the output should
|
57
|
+
Then the output should match /uninitialized constant .*::Baz \(NameError\)/
|
58
58
|
|
59
59
|
@sudo
|
60
60
|
Scenario: SyntaxError
|
@@ -26,10 +26,10 @@ Feature: -l (--logging_level) option
|
|
26
26
|
And the file "Hello.log" should contain "DEBUG -- : Konnichi Wa"
|
27
27
|
|
28
28
|
@sudo
|
29
|
-
Scenario: "Invalid
|
29
|
+
Scenario: "Invalid log level" error
|
30
30
|
When I run `trema run hello.rb --logging_level hoge -d`
|
31
31
|
Then the exit status should not be 0
|
32
32
|
And the stderr should contain:
|
33
33
|
"""
|
34
|
-
Invalid
|
34
|
+
Invalid log level: hoge
|
35
35
|
"""
|
@@ -17,14 +17,12 @@ Feature: -S (--socket_dir) option
|
|
17
17
|
When I successfully run `trema run null_controller.rb -S . -d`
|
18
18
|
And sleep 3
|
19
19
|
Then a socket file named "NullController.ctl" should exist
|
20
|
-
And a socket file named "trema.NullController.ctl" should exist
|
21
20
|
|
22
21
|
@sudo
|
23
22
|
Scenario: --socket_dir option
|
24
23
|
When I successfully run `trema run null_controller.rb --socket_dir . -d`
|
25
24
|
And sleep 3
|
26
25
|
Then a socket file named "NullController.ctl" should exist
|
27
|
-
And a socket file named "trema.NullController.ctl" should exist
|
28
26
|
|
29
27
|
@sudo
|
30
28
|
Scenario: "No such directory" error
|
data/lib/trema/command.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
require 'English'
|
2
2
|
|
3
3
|
module Trema
|
4
|
-
class InvalidLoggingLevel < StandardError; end
|
5
|
-
|
6
4
|
# trema command
|
7
5
|
# rubocop:disable ClassLength
|
8
6
|
class Command
|
9
|
-
def self.unix_domain_socket(name
|
10
|
-
|
11
|
-
path = File.expand_path(File.join Phut.socket_dir, file_name)
|
7
|
+
def self.unix_domain_socket(name, check = false)
|
8
|
+
path = File.expand_path(File.join(Phut.socket_dir, "#{name}.ctl"))
|
12
9
|
if check && !FileTest.socket?(path)
|
13
|
-
|
10
|
+
raise "Socket file #{path} does not exist."
|
14
11
|
end
|
15
12
|
'drbunix:' + path
|
16
13
|
end
|
@@ -22,24 +19,11 @@ module Trema
|
|
22
19
|
def run(args, options)
|
23
20
|
@args = args
|
24
21
|
@daemon = options[:daemonize]
|
25
|
-
|
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
|
-
|
39
22
|
$LOAD_PATH.unshift File.expand_path(File.dirname(@args.first))
|
40
23
|
load @args.first
|
41
24
|
port_number = (options[:port] || Controller::DEFAULT_TCP_PORT).to_i
|
42
|
-
@controller =
|
25
|
+
@controller =
|
26
|
+
Controller.create(port_number, options.fetch(:logging_level))
|
43
27
|
|
44
28
|
trap_signals
|
45
29
|
create_pid_file
|
@@ -119,9 +103,9 @@ module Trema
|
|
119
103
|
# rubocop:enable MethodLength
|
120
104
|
|
121
105
|
def start_controller_and_drb_threads
|
106
|
+
DRb.start_service Command.unix_domain_socket(@controller.name), self
|
122
107
|
@controller_thread = Thread.new { @controller.run @args[1..-1] }
|
123
108
|
@controller_thread.abort_on_exception = true
|
124
|
-
DRb.start_service Command.unix_domain_socket(@controller.name), self
|
125
109
|
DRb.thread.join
|
126
110
|
rescue
|
127
111
|
killall
|
@@ -166,7 +150,7 @@ module Trema
|
|
166
150
|
# rubocop:enable MethodLength
|
167
151
|
|
168
152
|
def create_pid_file
|
169
|
-
|
153
|
+
raise "#{name} is already running." if running?
|
170
154
|
update_pid_file
|
171
155
|
end
|
172
156
|
|
data/lib/trema/controller.rb
CHANGED
@@ -107,13 +107,9 @@ module Trema
|
|
107
107
|
# rubocop:enable MethodLength
|
108
108
|
end
|
109
109
|
|
110
|
-
class << self
|
111
|
-
attr_accessor :logging_level
|
112
|
-
end
|
113
|
-
|
114
110
|
include Pio
|
115
111
|
|
116
|
-
SWITCH = {}
|
112
|
+
SWITCH = {} # rubocop:disable MutableConstant
|
117
113
|
DEFAULT_TCP_PORT = 6653
|
118
114
|
|
119
115
|
# @return [Logger]
|
@@ -134,19 +130,21 @@ module Trema
|
|
134
130
|
end
|
135
131
|
|
136
132
|
# @private
|
137
|
-
def self.create(port_number = DEFAULT_TCP_PORT
|
133
|
+
def self.create(port_number = DEFAULT_TCP_PORT,
|
134
|
+
logging_level = ::Logger::INFO)
|
138
135
|
unless @controller_klass
|
139
|
-
|
136
|
+
raise NoControllerDefined, 'No controller class is defined.'
|
140
137
|
end
|
141
|
-
@controller_klass.new(port_number)
|
138
|
+
@controller_klass.new(port_number, logging_level)
|
142
139
|
end
|
143
140
|
|
144
141
|
# @private
|
145
|
-
def initialize(port_number = DEFAULT_TCP_PORT
|
142
|
+
def initialize(port_number = DEFAULT_TCP_PORT,
|
143
|
+
logging_level = ::Logger::INFO)
|
146
144
|
@port_number = port_number
|
147
145
|
@threads = []
|
148
146
|
@logger = Logger.new(name)
|
149
|
-
@logger.level =
|
147
|
+
@logger.level = logging_level
|
150
148
|
end
|
151
149
|
|
152
150
|
# @private
|
@@ -154,9 +152,6 @@ module Trema
|
|
154
152
|
# explicitly, because this is called implicitly by "trema run"
|
155
153
|
# command.
|
156
154
|
def run(args)
|
157
|
-
drb_socket_file =
|
158
|
-
File.expand_path(File.join(Phut.socket_dir, "#{name}.ctl"))
|
159
|
-
@drb = DRb::DRbServer.new 'drbunix:' + drb_socket_file, self
|
160
155
|
maybe_send_handler :start, args
|
161
156
|
socket = TCPServer.open('<any>', @port_number)
|
162
157
|
start_timers
|
@@ -168,7 +163,6 @@ module Trema
|
|
168
163
|
end
|
169
164
|
|
170
165
|
def stop
|
171
|
-
@drb.stop_service if @drb
|
172
166
|
@threads.map(&:kill)
|
173
167
|
end
|
174
168
|
|
@@ -182,7 +176,7 @@ module Trema
|
|
182
176
|
when 'OpenFlow13'
|
183
177
|
FlowMod.new(FlowModAdd13Option.new(options).to_hash)
|
184
178
|
else
|
185
|
-
|
179
|
+
raise "Unsupported OpenFlow version: #{Pio::OpenFlow.version}"
|
186
180
|
end
|
187
181
|
send_message datapath_id, flow_mod
|
188
182
|
end
|
@@ -318,14 +312,14 @@ module Trema
|
|
318
312
|
when :modify
|
319
313
|
maybe_send_handler :port_modify, datapath_id, message
|
320
314
|
else
|
321
|
-
|
315
|
+
raise "Invalid Port Status message: #{message.inspect}"
|
322
316
|
end
|
323
317
|
when Barrier::Reply
|
324
318
|
maybe_send_handler :barrier_reply, datapath_id, message
|
325
319
|
when DescriptionStats::Reply
|
326
320
|
maybe_send_handler :description_stats_reply, datapath_id, message
|
327
321
|
else
|
328
|
-
|
322
|
+
raise "Unknown OpenFlow message: #{message.inspect}"
|
329
323
|
end
|
330
324
|
end
|
331
325
|
# rubocop:enable MethodLength
|
data/lib/trema/drb.rb
CHANGED
@@ -5,18 +5,24 @@ require 'phut'
|
|
5
5
|
module Trema
|
6
6
|
def self.trema_process(controller_name, socket_dir)
|
7
7
|
Phut.socket_dir = socket_dir
|
8
|
-
socket_path = File.join(Phut.socket_dir, "
|
8
|
+
socket_path = File.join(Phut.socket_dir, "#{controller_name}.ctl")
|
9
9
|
unless FileTest.socket?(socket_path)
|
10
|
-
|
10
|
+
raise %(Controller process "#{controller_name}" does not exist.)
|
11
11
|
end
|
12
12
|
DRbObject.new_with_uri('drbunix:' + socket_path)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.trema_processes(socket_dir = Phut.socket_dir)
|
16
16
|
Phut.socket_dir = socket_dir
|
17
|
-
Dir.glob(File.join
|
18
|
-
|
19
|
-
|
17
|
+
all = Dir.glob(File.join(Phut.socket_dir, '*.ctl'))
|
18
|
+
vhosts = Dir.glob(File.join(Phut.socket_dir, 'vhost.*.ctl'))
|
19
|
+
(all - vhosts).map { |each| DRbObject.new_with_uri("drbunix:#{each}") }
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.vhosts(socket_dir = Phut.socket_dir)
|
23
|
+
Phut.socket_dir = socket_dir
|
24
|
+
vhosts = Dir.glob(File.join(Phut.socket_dir, 'vhost.*.ctl'))
|
25
|
+
vhosts.map { |each| DRbObject.new_with_uri("drbunix:#{each}") }
|
20
26
|
end
|
21
27
|
|
22
28
|
def self.fetch(name, socket_dir)
|
@@ -27,6 +33,6 @@ module Trema
|
|
27
33
|
next
|
28
34
|
end
|
29
35
|
end
|
30
|
-
|
36
|
+
raise %("#{name}" does not exist.)
|
31
37
|
end
|
32
38
|
end
|
data/lib/trema/logger.rb
CHANGED
data/lib/trema/switch.rb
CHANGED
@@ -23,10 +23,10 @@ module Trema
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def datapath_id
|
26
|
-
|
26
|
+
raise 'Switch is not initialized.' unless @features_reply
|
27
27
|
@features_reply.datapath_id
|
28
28
|
end
|
29
|
-
|
29
|
+
alias dpid datapath_id
|
30
30
|
|
31
31
|
def write(message)
|
32
32
|
@socket.write message.to_binary
|
@@ -68,7 +68,7 @@ module Trema
|
|
68
68
|
@error_message = message
|
69
69
|
fail InitError, message.description
|
70
70
|
else
|
71
|
-
|
71
|
+
raise "Failed to receive #{expected_message_klass} message"
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -78,7 +78,7 @@ module Trema
|
|
78
78
|
header_binary = drain(OPENFLOW_HEADER_LENGTH)
|
79
79
|
header = OpenFlowHeaderParser.read(header_binary)
|
80
80
|
body_binary = drain(header.message_length - OPENFLOW_HEADER_LENGTH)
|
81
|
-
|
81
|
+
raise if (header_binary + body_binary).length != header.message_length
|
82
82
|
header_binary + body_binary
|
83
83
|
end
|
84
84
|
|
data/lib/trema/version.rb
CHANGED
data/trema.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |gem|
|
|
23
23
|
|
24
24
|
gem.add_dependency 'bundler', '~> 1.11.2'
|
25
25
|
gem.add_dependency 'gli', '~> 2.13.4'
|
26
|
-
gem.add_dependency 'phut', '~> 0.7.
|
26
|
+
gem.add_dependency 'phut', '~> 0.7.7'
|
27
27
|
gem.add_dependency 'pio', '~> 0.30.0'
|
28
28
|
|
29
29
|
# Docs
|
@@ -31,13 +31,13 @@ Gem::Specification.new do |gem|
|
|
31
31
|
gem.add_development_dependency 'yard', '~> 0.8.7.6'
|
32
32
|
|
33
33
|
# Test
|
34
|
-
gem.add_development_dependency 'aruba', '~> 0.
|
34
|
+
gem.add_development_dependency 'aruba', '~> 0.13.0'
|
35
35
|
gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.8'
|
36
36
|
gem.add_development_dependency 'coveralls', '~> 0.8.10'
|
37
|
-
gem.add_development_dependency 'cucumber', '~> 2.
|
37
|
+
gem.add_development_dependency 'cucumber', '~> 2.3.2'
|
38
38
|
gem.add_development_dependency 'rake'
|
39
|
-
gem.add_development_dependency 'reek', '~> 3.
|
39
|
+
gem.add_development_dependency 'reek', '~> 3.10.2'
|
40
40
|
gem.add_development_dependency 'rspec', '~> 3.4.0'
|
41
|
-
gem.add_development_dependency 'rspec-given', '~> 3.
|
42
|
-
gem.add_development_dependency 'rubocop', '~> 0.
|
41
|
+
gem.add_development_dependency 'rspec-given', '~> 3.8.0'
|
42
|
+
gem.add_development_dependency 'rubocop', '~> 0.37.2'
|
43
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yasuhito Takamiya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.7.
|
47
|
+
version: 0.7.7
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.7.
|
54
|
+
version: 0.7.7
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pio
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
103
|
+
version: 0.13.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.13.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: codeclimate-test-reporter
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 2.
|
145
|
+
version: 2.3.2
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 2.
|
152
|
+
version: 2.3.2
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: rake
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 3.
|
173
|
+
version: 3.10.2
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 3.
|
180
|
+
version: 3.10.2
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: rspec
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,28 +198,28 @@ dependencies:
|
|
198
198
|
requirements:
|
199
199
|
- - "~>"
|
200
200
|
- !ruby/object:Gem::Version
|
201
|
-
version: 3.
|
201
|
+
version: 3.8.0
|
202
202
|
type: :development
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
|
-
version: 3.
|
208
|
+
version: 3.8.0
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
210
|
name: rubocop
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
212
212
|
requirements:
|
213
213
|
- - "~>"
|
214
214
|
- !ruby/object:Gem::Version
|
215
|
-
version: 0.
|
215
|
+
version: 0.37.2
|
216
216
|
type: :development
|
217
217
|
prerelease: false
|
218
218
|
version_requirements: !ruby/object:Gem::Requirement
|
219
219
|
requirements:
|
220
220
|
- - "~>"
|
221
221
|
- !ruby/object:Gem::Version
|
222
|
-
version: 0.
|
222
|
+
version: 0.37.2
|
223
223
|
description: Trema is a full-stack, easy-to-use framework for developing OpenFlow
|
224
224
|
controllers in Ruby.
|
225
225
|
email:
|
@@ -257,6 +257,7 @@ files:
|
|
257
257
|
- features/logger/error.feature
|
258
258
|
- features/logger/fatal.feature
|
259
259
|
- features/logger/info.feature
|
260
|
+
- features/logger/unknown.feature
|
260
261
|
- features/logger/warn.feature
|
261
262
|
- features/step_definitions/.gitignore
|
262
263
|
- features/step_definitions/.rubocop.yml
|
@@ -276,13 +277,16 @@ files:
|
|
276
277
|
- features/trema_delete_link/README.md
|
277
278
|
- features/trema_delete_link/delete_link.feature
|
278
279
|
- features/trema_delete_link/socket_dir_option.feature
|
280
|
+
- features/trema_dump_flows/README.md
|
279
281
|
- features/trema_dump_flows/dump_flows.feature
|
282
|
+
- features/trema_dump_flows/socket_dir_option.feature
|
280
283
|
- features/trema_killall/README.md
|
281
284
|
- features/trema_killall/all_option.feature
|
282
285
|
- features/trema_killall/killall.feature
|
283
286
|
- features/trema_killall/socket_dir_option.feature
|
284
287
|
- features/trema_netns/README.md
|
285
288
|
- features/trema_netns/netns.feature
|
289
|
+
- features/trema_reset_stats/reset_stats.feature
|
286
290
|
- features/trema_run/README.md
|
287
291
|
- features/trema_run/conf_option.feature
|
288
292
|
- features/trema_run/daemonize_option.feature
|
@@ -345,7 +349,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
345
349
|
version: '0'
|
346
350
|
requirements: []
|
347
351
|
rubyforge_project:
|
348
|
-
rubygems_version: 2.
|
352
|
+
rubygems_version: 2.5.1
|
349
353
|
signing_key:
|
350
354
|
specification_version: 4
|
351
355
|
summary: Full-stack OpenFlow framework.
|