phut 0.7.7 → 0.7.8

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rubocop.yml +14 -1
  4. data/.travis.yml +2 -6
  5. data/Gemfile +30 -2
  6. data/Gemfile.lock +156 -0
  7. data/README.md +7 -2
  8. data/Rakefile +4 -3
  9. data/bin/phut +35 -83
  10. data/bin/vhost +28 -26
  11. data/features/{dsl.feature → dsl/error.feature} +8 -6
  12. data/features/{dsl_link.feature → dsl/link.feature} +11 -14
  13. data/features/dsl/netns.feature +115 -0
  14. data/features/dsl/vhost.feature +37 -0
  15. data/features/{dsl_vswitch.feature → dsl/vswitch.feature} +12 -12
  16. data/features/phut_run.feature +15 -0
  17. data/features/shell/vswitch#destroy.feature +10 -0
  18. data/features/shell/vswitch#ports.feature +36 -0
  19. data/features/shell/vswitch.all.feature +26 -0
  20. data/features/shell/vswitch.create.feature +30 -0
  21. data/features/shell/vswitch.destroy.feature +19 -0
  22. data/features/shell/vswitch.destroy_all.feature +18 -0
  23. data/features/step_definitions/link_steps.rb +5 -0
  24. data/features/step_definitions/netns_steps.rb +31 -0
  25. data/features/step_definitions/phut_steps.rb +5 -34
  26. data/features/step_definitions/vhost_steps.rb +5 -0
  27. data/features/step_definitions/vswitch_steps.rb +17 -0
  28. data/features/support/env.rb +3 -3
  29. data/features/support/hooks.rb +23 -15
  30. data/lib/phut.rb +3 -0
  31. data/lib/phut/finder.rb +19 -0
  32. data/lib/phut/link.rb +84 -0
  33. data/lib/phut/netns.rb +111 -22
  34. data/lib/phut/open_vswitch.rb +98 -96
  35. data/lib/phut/parser.rb +39 -8
  36. data/lib/phut/raw_socket.rb +4 -0
  37. data/lib/phut/route.rb +34 -0
  38. data/lib/phut/setting.rb +21 -4
  39. data/lib/phut/shell_runner.rb +13 -2
  40. data/lib/phut/syntax.rb +31 -14
  41. data/lib/phut/syntax/directive.rb +9 -1
  42. data/lib/phut/syntax/netns_directive.rb +13 -2
  43. data/lib/phut/syntax/vhost_directive.rb +2 -0
  44. data/lib/phut/syntax/vswitch_directive.rb +3 -1
  45. data/lib/phut/version.rb +3 -1
  46. data/lib/phut/veth.rb +68 -0
  47. data/lib/phut/vhost.rb +99 -58
  48. data/lib/phut/vhost_daemon.rb +53 -11
  49. data/lib/phut/vsctl.rb +125 -0
  50. data/lib/phut/vswitch.rb +10 -0
  51. data/phut.gemspec +9 -31
  52. data/tasks/cucumber.rake +5 -1
  53. data/tasks/flay.rake +2 -0
  54. data/tasks/flog.rake +3 -1
  55. data/tasks/gem.rake +2 -0
  56. data/tasks/minitest.rake +7 -0
  57. data/tasks/reek.rake +2 -0
  58. data/tasks/rubocop.rake +2 -0
  59. data/tasks/yard.rake +2 -0
  60. data/test/phut/link_test.rb +85 -0
  61. data/test/phut/netns_test.rb +58 -0
  62. data/test/phut/open_vswitch_test.rb +125 -0
  63. data/test/phut/veth_test.rb +48 -0
  64. data/test/phut/vhost_test.rb +56 -0
  65. metadata +41 -287
  66. data/.rspec +0 -3
  67. data/Guardfile +0 -29
  68. data/features/dsl_vhost.feature +0 -37
  69. data/features/phut_kill.feature +0 -27
  70. data/features/shell.feature +0 -39
  71. data/lib/phut/configuration.rb +0 -92
  72. data/lib/phut/null_logger.rb +0 -14
  73. data/lib/phut/virtual_link.rb +0 -109
  74. data/spec/phut/parser_spec.rb +0 -66
  75. data/spec/phut_spec.rb +0 -45
  76. data/spec/spec_helper.rb +0 -14
  77. data/tasks/LICENSE +0 -675
  78. data/tasks/relish.rake +0 -8
  79. data/tasks/rspec.rake +0 -8
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'phut/shell_runner'
4
+ require 'pio'
5
+
6
+ module Phut
7
+ # ovs-vsctl wrapper
8
+ class Vsctl
9
+ MAX_BRIDGE_NAME_LENGTH = 15
10
+
11
+ extend ShellRunner
12
+
13
+ def self.list_br(prefix)
14
+ sudo('ovs-vsctl list-br').split.each_with_object([]) do |each, list|
15
+ match = /^#{prefix}(\S+)/.match(each)
16
+ next unless match
17
+ name = match[1]
18
+ vsctl = new(name: name, bridge: prefix + name)
19
+ list << { name: vsctl.name,
20
+ dpid: vsctl.dpid,
21
+ openflow_version: vsctl.openflow_version,
22
+ tcp_port: vsctl.tcp_port }
23
+ end
24
+ end
25
+
26
+ include ShellRunner
27
+
28
+ attr_reader :name
29
+ attr_reader :bridge
30
+
31
+ def initialize(name:, bridge:)
32
+ @name = name
33
+ @bridge = bridge
34
+ end
35
+
36
+ def dpid
37
+ ('0x' +
38
+ sudo("ovs-vsctl get bridge #{@bridge} datapath-id").delete('"')).hex
39
+ end
40
+
41
+ def openflow_version
42
+ case sudo("ovs-ofctl show #{@bridge} -O OpenFlow10,OpenFlow13")
43
+ when /^OFPT_FEATURES_REPLY \(xid=0x[^\)]+\):/
44
+ 1.0
45
+ when /^OFPT_FEATURES_REPLY \(OF(\d\.\d)\)/
46
+ Regexp.last_match(1).to_f
47
+ else
48
+ raise "Couldn't identify the OpenFlow version of #{@bridge}"
49
+ end
50
+ end
51
+
52
+ def add_bridge
53
+ sudo "ovs-vsctl add-br #{@bridge}"
54
+ sudo "/sbin/sysctl -w net.ipv6.conf.#{@bridge}.disable_ipv6=1 -q"
55
+ end
56
+
57
+ def delete_bridge
58
+ sudo "ovs-vsctl del-br #{@bridge}"
59
+ end
60
+
61
+ def openflow_version=(version)
62
+ sudo "ovs-vsctl set bridge #{@bridge} "\
63
+ "protocols=OpenFlow#{version.to_s.delete('.')} "
64
+ rescue
65
+ raise "Invalid openflow_version: #{version}"
66
+ end
67
+
68
+ def dpid=(dpid)
69
+ sudo "ovs-vsctl set bridge #{@bridge} "\
70
+ "other-config:datapath-id=#{fill_zero(dpid)}"
71
+ end
72
+
73
+ def tcp_port
74
+ controller_info = sudo("ovs-vsctl get-controller #{@bridge}")
75
+ return if controller_info.empty?
76
+ controller_info.chomp.split(':').last.to_i
77
+ end
78
+
79
+ def tcp_port=(tcp_port)
80
+ raise "Invalid tcp_port: #{tcp_port}" if tcp_port.negative?
81
+ sudo "ovs-vsctl set-controller #{@bridge} "\
82
+ "tcp:127.0.0.1:#{tcp_port} "\
83
+ "-- set controller #{@bridge} connection-mode=out-of-band"
84
+ end
85
+
86
+ def delete_controller
87
+ sudo "ovs-vsctl del-controller #{@bridge}"
88
+ end
89
+
90
+ def set_fail_mode_secure
91
+ sudo "ovs-vsctl set-fail-mode #{@bridge} secure"
92
+ end
93
+
94
+ def add_port(device)
95
+ sudo "ovs-vsctl add-port #{@bridge} #{device}"
96
+ nil
97
+ end
98
+
99
+ def add_numbered_port(port_number, device)
100
+ add_port device
101
+ sudo "ovs-vsctl set Interface #{device} "\
102
+ "ofport_request=#{port_number}"
103
+ nil
104
+ end
105
+
106
+ def bring_port_up(port_number)
107
+ sh "sudo ovs-ofctl mod-port #{@bridge} #{port_number} up"
108
+ end
109
+
110
+ def bring_port_down(port_number)
111
+ sh "sudo ovs-ofctl mod-port #{@bridge} #{port_number} down"
112
+ end
113
+
114
+ def ports
115
+ sudo("ovs-vsctl list-ports #{@bridge}").split
116
+ end
117
+
118
+ private
119
+
120
+ def fill_zero(dpid)
121
+ hex = format('%x', dpid)
122
+ '0' * (16 - hex.length) + hex
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'phut/open_vswitch'
4
+
5
+ # Base module
6
+ module Phut
7
+ # Open vSwitch controller.
8
+ class Vswitch < OpenVswitch; end
9
+ Vswitch.bridge_prefix = 'vsw_'
10
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('../lib', __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'phut/version'
@@ -9,46 +11,22 @@ Gem::Specification.new do |gem|
9
11
  gem.description = 'A simple network emulator '\
10
12
  'with capabilities similar to mininet.'
11
13
 
12
- gem.license = 'GPL3'
14
+ gem.licenses = %w[GPLv2 MIT]
13
15
 
14
16
  gem.authors = ['Yasuhito Takamiya']
15
17
  gem.email = ['yasuhito@gmail.com']
16
18
  gem.homepage = 'http://github.com/trema/phut'
17
19
 
18
- gem.executables = %w(phut vhost)
20
+ gem.executables = %w[phut vhost]
19
21
  gem.files = `git ls-files`.split("\n")
20
22
 
21
23
  gem.extra_rdoc_files = ['README.md']
22
- gem.test_files = `git ls-files -- {spec,features}/*`.split("\n")
24
+ gem.test_files = `git ls-files -- {test,features}/*`.split("\n")
23
25
 
24
- gem.required_ruby_version = '>= 2.0.0'
26
+ gem.required_ruby_version = '>= 2.3.0'
25
27
 
26
- gem.add_dependency 'activesupport', '~> 4.2', '>= 4.2.5'
27
- gem.add_dependency 'gli', '~> 2.13.4'
28
- gem.add_dependency 'pio', '~> 0.30.0'
28
+ gem.add_dependency 'activesupport', '~> 5.1.0'
29
+ gem.add_dependency 'gli', '~> 2.16.0'
30
+ gem.add_dependency 'pio', '~> 0.30.2'
29
31
  gem.add_dependency 'pry', '~> 0.10.3'
30
-
31
- # Docs
32
- gem.add_development_dependency 'relish'
33
- gem.add_development_dependency 'yard', '~> 0.8.7.6'
34
-
35
- # Development
36
- gem.add_development_dependency 'guard', '~> 2.13.0'
37
- gem.add_development_dependency 'guard-bundler', '~> 2.1.0'
38
- gem.add_development_dependency 'guard-cucumber', '~> 2.0.0'
39
- gem.add_development_dependency 'guard-rspec', '~> 4.6.4'
40
- gem.add_development_dependency 'guard-rubocop', '~> 1.2.0'
41
-
42
- # Test
43
- gem.add_development_dependency 'aruba', '~> 0.11.2'
44
- gem.add_development_dependency 'codeclimate-test-reporter'
45
- gem.add_development_dependency 'coveralls', '~> 0.8.10'
46
- gem.add_development_dependency 'cucumber', '~> 2.1.0'
47
- gem.add_development_dependency 'flay', '~> 2.6.1'
48
- gem.add_development_dependency 'flog', '~> 4.3.2'
49
- gem.add_development_dependency 'rake'
50
- gem.add_development_dependency 'reek', '~> 3.7.1'
51
- gem.add_development_dependency 'rspec', '~> 3.4.0'
52
- gem.add_development_dependency 'rspec-given', '~> 3.7.1'
53
- gem.add_development_dependency 'rubocop', '~> 0.35.1'
54
32
  end
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'cucumber/rake/task'
3
- Cucumber::Rake::Task.new
5
+ Cucumber::Rake::Task.new do |task|
6
+ task.cucumber_opts = '--tags ~@wip'
7
+ end
4
8
  Cucumber::Rake::Task.new('cucumber:travis') do |task|
5
9
  task.cucumber_opts = '--tags ~@wip --tags ~@sudo --tags ~@shell'
6
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'rake/tasklib'
3
5
  require 'flay'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'flog'
3
5
 
@@ -8,7 +10,7 @@ begin
8
10
  threshold = 10
9
11
 
10
12
  bad_methods = flog.totals.select do |name, score|
11
- !(/##{flog.no_method}$/ =~ name) && score > threshold
13
+ /##{flog.no_method}$/ !~ name && score > threshold
12
14
  end
13
15
  bad_methods.sort { |a, b| a[1] <=> b[1] }.reverse_each do |name, score|
14
16
  printf "%8.1f: %s\n", score, name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  unless Dir.glob(File.join(__dir__, '../*.gemspec')).empty?
3
5
  require 'bundler/gem_tasks'
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.test_files = FileList['test/**/*_test.rb']
7
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'reek/rake/task'
3
5
  Reek::Rake::Task.new do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'rubocop/rake_task'
3
5
  RuboCop::RakeTask.new
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'yard'
3
5
  YARD::Rake::YardocTask.new do |t|
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/array/access'
4
+ require 'minitest/autorun'
5
+ require 'phut/link'
6
+
7
+ module Phut
8
+ class LinkTest < Minitest::Test
9
+ def test_link_all
10
+ assert Link.all.empty?
11
+
12
+ Link.create :switch1, :switch2
13
+ assert_equal 1, Link.all.size
14
+ assert_equal %w[switch1 switch2], Link.all.first.ends.map(&:name)
15
+
16
+ Link.create :host1, :host2
17
+ assert_equal 2, Link.all.size
18
+ assert_equal %w[host1 host2], Link.all.second.ends.map(&:name)
19
+ end
20
+
21
+ def test_link_find
22
+ assert_nil Link.find(:switch1, :switch2)
23
+
24
+ link = Link.create(:switch1, :switch2)
25
+ assert_equal link, Link.find(:switch1, :switch2)
26
+ assert_equal link, Link.find(:switch2, :switch1)
27
+ assert_equal link, Link.find('switch1', 'switch2')
28
+ assert_equal link, Link.find('switch2', 'switch1')
29
+ end
30
+
31
+ def test_start
32
+ link = Link.new(:switch1, :switch2)
33
+ link.start
34
+
35
+ assert_equal link, Link.all.first
36
+ assert_equal link, link.start
37
+ end
38
+
39
+ def test_destroy
40
+ link = Link.create(:switch1, :switch2)
41
+
42
+ link.destroy
43
+ assert Link.all.empty?
44
+ end
45
+
46
+ def test_ends
47
+ link = Link.create(:switch1, :switch2)
48
+
49
+ assert_equal 2, link.ends.size
50
+ assert_equal 'switch1', link.ends.first.name
51
+ assert_equal 'switch2', link.ends.second.name
52
+ end
53
+
54
+ def test_device
55
+ link1 = Link.create(:switch1, :switch2)
56
+ link2 = Link.create(:host1, :host2)
57
+
58
+ assert_equal 'L0_switch1', link1.device(:switch1).to_s
59
+ assert_equal 'L0_switch1', link1.device('switch1').to_s
60
+ assert_equal 'L0_switch2', link1.device(:switch2).to_s
61
+ assert_equal 'L0_switch2', link1.device('switch2').to_s
62
+
63
+ assert_equal 'L1_host1', link2.device(:host1).to_s
64
+ assert_equal 'L1_host1', link2.device('host1').to_s
65
+ assert_equal 'L1_host2', link2.device(:host2).to_s
66
+ assert_equal 'L1_host2', link2.device('host2').to_s
67
+
68
+ assert_nil link1.device(:firewall)
69
+ end
70
+
71
+ private
72
+
73
+ def setup
74
+ log_dir = File.expand_path('../../log', __dir__)
75
+ Phut.logger = ::Logger.new("#{log_dir}/test.log")
76
+ end
77
+
78
+ def teardown
79
+ `ifconfig -a`.split("\n").each do |each|
80
+ next unless /^(#{Veth::PREFIX}\S+)/ =~ each
81
+ system "sudo ip link delete #{Regexp.last_match(1)} 2>/dev/null"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/array/access'
4
+ require 'minitest/autorun'
5
+ require 'phut/link'
6
+ require 'phut/netns'
7
+
8
+ module Phut
9
+ class NetnsTest < Minitest::Test
10
+ def test_netns_all
11
+ assert Netns.all.empty?
12
+
13
+ link = Link.create('host1', 'host2')
14
+
15
+ host1 = Netns.create(name: 'host1', ip_address: '192.168.0.1')
16
+ host1.device = link.device('host1')
17
+ assert_equal 1, Netns.all.size
18
+ assert_equal 'host1', Netns.all.first.name
19
+ assert_equal '192.168.0.1', Netns.all.first.ip_address
20
+
21
+ host2 = Netns.create(name: 'host2', ip_address: '192.168.0.1')
22
+ host2.device = link.device('host2')
23
+ assert_equal 2, Netns.all.size
24
+ assert_equal 'host2', Netns.all.second.name
25
+ assert_equal '192.168.0.1', Netns.all.second.ip_address
26
+ end
27
+
28
+ def test_netns_create
29
+ netns = Netns.create(name: 'netns',
30
+ ip_address: '192.168.8.6',
31
+ netmask: '255.255.255.0',
32
+ route: { net: '0.0.0.0', gateway: '192.168.8.1' })
33
+ assert_equal 'netns', netns.name
34
+ assert_equal '192.168.8.6', netns.ip_address
35
+ end
36
+
37
+ def test_device
38
+ link = Link.create('host', 'switch')
39
+ netns = Netns.create(name: 'netns', ip_address: '192.168.0.1')
40
+
41
+ netns.device = link.device('host')
42
+
43
+ assert_equal 'host', netns.device.name
44
+ end
45
+
46
+ private
47
+
48
+ def setup
49
+ Netns.destroy_all
50
+ Link.destroy_all
51
+ end
52
+
53
+ def teardown
54
+ Netns.destroy_all
55
+ Link.destroy_all
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'phut/open_vswitch'
5
+
6
+ module Phut
7
+ class OpenVswitchTest < Minitest::Test
8
+ def test_open_vswitch_all
9
+ assert OpenVswitch.all.empty?
10
+
11
+ OpenVswitch.create(dpid: 0xc001)
12
+ assert_equal 1, OpenVswitch.all.size
13
+ assert_equal 0xc001, OpenVswitch.all.first.dpid
14
+ assert_equal '0xc001', OpenVswitch.all.first.name
15
+ assert_equal '0xc001', OpenVswitch.all.first.bridge
16
+ assert_equal 1.0, OpenVswitch.all.first.openflow_version
17
+ assert_equal 6653, OpenVswitch.all.first.tcp_port
18
+
19
+ OpenVswitch.create(dpid: 0xdad1)
20
+ assert_equal 2, OpenVswitch.all.size
21
+ assert_equal 0xdad1, OpenVswitch.all.second.dpid
22
+ assert_equal '0xdad1', OpenVswitch.all.second.name
23
+ assert_equal '0xdad1', OpenVswitch.all.second.bridge
24
+ assert_equal 1.0, OpenVswitch.all.second.openflow_version
25
+ assert_equal 6653, OpenVswitch.all.second.tcp_port
26
+ end
27
+
28
+ def test_open_vswitch_create_with_dpid
29
+ vswitch = OpenVswitch.create(dpid: 0xc001)
30
+ assert_equal 0xc001, vswitch.dpid
31
+ assert_equal '0xc001', vswitch.name
32
+ assert_equal '0xc001', vswitch.bridge
33
+ assert_equal 1.0, vswitch.openflow_version
34
+ assert_equal 6653, vswitch.tcp_port
35
+
36
+ assert_raises(RuntimeError) do
37
+ OpenVswitch.create(dpid: 0xc001)
38
+ end
39
+ end
40
+
41
+ def test_open_vswitch_create_with_name_and_dpid
42
+ vswitch = OpenVswitch.create(name: 'dadi', dpid: 0xc001)
43
+ assert_equal 0xc001, vswitch.dpid
44
+ assert_equal 'dadi', vswitch.name
45
+ assert_equal 'dadi', vswitch.bridge
46
+ assert_equal 1.0, vswitch.openflow_version
47
+ assert_equal 6653, vswitch.tcp_port
48
+
49
+ assert_raises(RuntimeError) do
50
+ OpenVswitch.create(name: 'dadi', dpid: 0xc001)
51
+ end
52
+ end
53
+
54
+ def test_open_vswitch_create_exceptions
55
+ assert_raises(RuntimeError) do
56
+ OpenVswitch.create(dpid: 0xdad1, name: '1234567890123456')
57
+ end
58
+
59
+ assert_raises(RuntimeError) do
60
+ OpenVswitch.create(dpid: 0xdad1, openflow_version: 999)
61
+ end
62
+
63
+ assert_raises(RuntimeError) do
64
+ OpenVswitch.create(dpid: 0xdad1, tcp_port: -999)
65
+ end
66
+ end
67
+
68
+ def test_open_vswitch_find_by
69
+ OpenVswitch.create(dpid: 0xc001)
70
+ vswitch = OpenVswitch.find_by(dpid: 0xc001)
71
+ assert_equal '0xc001', vswitch.name
72
+ assert_equal 0xc001, vswitch.dpid
73
+ end
74
+
75
+ def test_open_vswitch_destroy
76
+ OpenVswitch.create(dpid: 0xc001)
77
+ OpenVswitch.destroy('0xc001')
78
+ assert OpenVswitch.all.empty?
79
+ end
80
+
81
+ def test_open_vswitch_destroy_all
82
+ OpenVswitch.create(dpid: 0xc001)
83
+ OpenVswitch.destroy_all
84
+ assert OpenVswitch.all.empty?
85
+ end
86
+
87
+ def test_new
88
+ assert_raises(NoMethodError) do
89
+ OpenVswitch.new
90
+ end
91
+ end
92
+
93
+ def test_destroy
94
+ vswitch = OpenVswitch.create(dpid: 0xc001)
95
+ vswitch.destroy
96
+ assert OpenVswitch.all.empty?
97
+ end
98
+
99
+ def test_stop
100
+ vswitch = OpenVswitch.create(dpid: 0xc001)
101
+ vswitch.stop
102
+ assert vswitch.tcp_port.nil?
103
+ end
104
+
105
+ def test_dump_flows
106
+ vswitch = OpenVswitch.create(dpid: 0xc001)
107
+ assert_equal '', vswitch.dump_flows
108
+ end
109
+
110
+ def test_add_port
111
+ vswitch = OpenVswitch.create(dpid: 0xc001)
112
+ vswitch.add_port 'port1'
113
+ assert_equal ['port1'], vswitch.ports
114
+ end
115
+
116
+ private
117
+
118
+ def teardown
119
+ `sudo ovs-vsctl list-br`.chomp.split.each do |each|
120
+ next unless /^#{OpenVswitch.bridge_prefix}/ =~ each
121
+ system "sudo ovs-vsctl del-br #{each}"
122
+ end
123
+ end
124
+ end
125
+ end