phut 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 976e821178942cdc0a5ce7aae154ebbfc0f3f1bd
4
- data.tar.gz: de76db53ba5388fb53a75ee06eb55157f8ffd55a
3
+ metadata.gz: 681a58fd291ea016d0ffc8d56a9c62fb3ab38568
4
+ data.tar.gz: 48d70fb96ecac1cbddb1868172d4b8a0af0163ed
5
5
  SHA512:
6
- metadata.gz: 8b633f79a7e4057b6818d75313409ec16207a4ba73dd8a89a1664576caac6f6ac0033e330792b0cd85a690dc5b2c3d24f29a9fb4ee15d87003ed8319a85b23fd
7
- data.tar.gz: d2533b9a48e4d5ebe38958ca2fc41076012cbb61cb0387fcca29a56a86565698c7f74abceefedead44917d3a89ab19be1985a3421f036d4ee9ea86a2a3519aba
6
+ metadata.gz: e2eab81e9e6b03c262a5debdcec17eb12aa3f565e99fcf27f8e904f68f84b0d1fedf1c29e6deee08a6e4e9a471c937fe8a2d9f76e0a9340e9b69009e82b63427
7
+ data.tar.gz: bb22c24a34980bc1f7b7284b2f81d04efac05e2345bb41bda36deb105c84a69a04108fdf0d1842b6a955eb79d452c3e9a8904aa53b7f2af72a6b3afe4736ecfc
data/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  ## develop (unreleased)
4
4
 
5
5
 
6
+ ## 0.4.0 (3/19/2015)
7
+ ### New features
8
+ * Add `phut show` command.
9
+
10
+ ### Changes
11
+ * [#14](https://github.com/trema/phut/issues/14): Switch port number
12
+ to which a virtual link is attached is implicitly determined by the
13
+ ordering of `link` directives in DSL file.
14
+
15
+
6
16
  ## 0.3.1 (3/17/2015)
7
17
  ### Bugs fixed
8
18
  * Set switch's dpid before connecting to a controller.
@@ -10,7 +20,8 @@
10
20
 
11
21
  ## 0.3.0 (3/17/2015)
12
22
  ### Changes
13
- * [#20](https://github.com/trema/phut/pull/20): Use apt installed version of Open vSwitch.
23
+ * [#20](https://github.com/trema/phut/pull/20): Use apt installed
24
+ version of Open vSwitch.
14
25
 
15
26
 
16
27
  ## 0.2.4 (3/12/2015)
data/Rakefile CHANGED
@@ -2,9 +2,11 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
2
2
 
3
3
  require 'rake/clean'
4
4
 
5
+ RELISH_PROJECT = 'trema/phut'
6
+
5
7
  task default: :test
6
8
  task test: [:spec, :cucumber, :quality]
7
- task quality: [:rubocop, :reek, :flog]
8
9
  task travis: [:spec, 'cucumber:travis', :quality]
10
+ task quality: [:rubocop, :reek, :flog, :flay]
9
11
 
10
12
  Dir.glob('tasks/*.rake').each { |each| import each }
data/bin/phut CHANGED
@@ -72,6 +72,14 @@ module Phut
72
72
  end
73
73
  end
74
74
 
75
+ desc 'Shows information on switch'
76
+ arg_name 'SWITCH'
77
+ command :show do |c|
78
+ c.action do |_global_options, _options, args|
79
+ system "sudo ovs-ofctl show br#{args[0]}"
80
+ end
81
+ end
82
+
75
83
  desc 'Stops a virtual network'
76
84
  arg_name 'FILE'
77
85
  command :stop do |c|
@@ -1,22 +1,51 @@
1
- Feature: The link DSL directive.
1
+ Feature: The link directive of phut DSL
2
2
  @sudo
3
- Scenario: phut run with "link ..."
3
+ Scenario: link name_a, name_b
4
4
  Given a file named "network.conf" with:
5
- """
6
- vswitch { dpid '0xabc' }
7
- vhost { ip '192.168.0.1' }
8
- link '0xabc', '192.168.0.1'
9
- """
5
+ """
6
+ vswitch { dpid 0xabc }
7
+ vhost { ip '192.168.0.1' }
8
+ link '0xabc', '192.168.0.1'
9
+ """
10
10
  When I do phut run "network.conf"
11
11
  Then a link is created between "0xabc" and "192.168.0.1"
12
12
 
13
13
  @sudo
14
- Scenario: phut run with "link alias1, alias2"
14
+ Scenario: link alias_a, alias_b
15
15
  Given a file named "network.conf" with:
16
- """
17
- vswitch('my_switch') { dpid '0xabc' }
18
- vhost('host1') { ip '192.168.0.1' }
19
- link 'my_switch', 'host1'
20
- """
16
+ """
17
+ vswitch('my_switch') { dpid 0xabc }
18
+ vhost('host1') { ip '192.168.0.1' }
19
+ link 'my_switch', 'host1'
20
+ """
21
21
  When I do phut run "network.conf"
22
22
  Then a link is created between "my_switch" and "host1"
23
+
24
+ @sudo
25
+ Scenario: connect multiple links to a switch
26
+ Given a file named "network.conf" with:
27
+ """
28
+ vswitch { datapath_id 0xabc }
29
+
30
+ vhost('host1') {
31
+ ip '192.168.0.1'
32
+ }
33
+ vhost('host2') {
34
+ ip '192.168.0.2'
35
+ }
36
+ vhost('host3') {
37
+ ip '192.168.0.3'
38
+ }
39
+
40
+ link '0xabc', 'host1'
41
+ link '0xabc', 'host2'
42
+ link '0xabc', 'host3'
43
+ """
44
+ When I do phut run "network.conf"
45
+ And I run `phut show 0xabc`
46
+ Then a link is created between "0xabc" and "host1"
47
+ And a link is created between "0xabc" and "host2"
48
+ And a link is created between "0xabc" and "host3"
49
+ And the output from "phut show 0xabc" should contain "1(0xabc_1)"
50
+ And the output from "phut show 0xabc" should contain "2(0xabc_2)"
51
+ And the output from "phut show 0xabc" should contain "3(0xabc_3)"
@@ -37,6 +37,7 @@ Feature: Shell
37
37
  And I type "vswitch 0xabc"
38
38
  When I type "kill 0xabc"
39
39
  And I type "quit"
40
+ And I run `sleep 1`
40
41
  Then a vswitch named "0xabc" should not be running
41
42
 
42
43
  @shell
@@ -7,11 +7,11 @@ When(/^I do phut run "(.*?)"$/) do |file_name|
7
7
  end
8
8
 
9
9
  Then(/^a vswitch named "(.*?)" should be running$/) do |name|
10
- expect(system("sudo ovs-vsctl br-exists #{name}")).to be(true)
10
+ expect(system("sudo ovs-vsctl br-exists br#{name}")).to be_truthy
11
11
  end
12
12
 
13
13
  Then(/^a vswitch named "(.*?)" should not be running$/) do |name|
14
- expect(system("sudo ovs-vsctl br-exists #{name}")).to be(false)
14
+ expect(system("sudo ovs-vsctl br-exists br#{name}")).to be_falsey
15
15
  end
16
16
 
17
17
  Then(/^a vhost named "(.*?)" launches$/) do |name|
@@ -23,9 +23,7 @@ end
23
23
 
24
24
  Then(/^a link is created between "(.*?)" and "(.*?)"$/) do |name_a, name_b|
25
25
  in_current_dir do
26
- link = Phut::Parser.new.parse(@config_file).links.find do |each|
27
- each.name_a == name_a && each.name_b == name_b
28
- end
26
+ link = Phut::Parser.new.parse(@config_file).fetch([name_a, name_b].sort)
29
27
  expect(link).to be_up
30
28
  end
31
29
  end
@@ -1,19 +1,41 @@
1
- require 'forwardable'
2
1
  require 'phut/null_logger'
3
2
  require 'phut/open_vswitch'
4
3
 
5
4
  module Phut
6
5
  # Parsed DSL data.
7
6
  class Configuration
8
- extend Forwardable
9
-
10
- def_delegators :@all, :fetch, :[]
7
+ attr_reader :links
11
8
 
12
9
  def initialize(logger = NullLogger.new)
13
10
  @all = {}
11
+ @links = []
14
12
  @logger = logger
15
13
  end
16
14
 
15
+ # rubocop:disable MethodLength
16
+ def fetch(key)
17
+ case key
18
+ when String
19
+ @all.fetch(key)
20
+ when Array
21
+ @links.each do |each|
22
+ return each if [each.name_a, each.name_b].sort == key.sort
23
+ end
24
+ fail "link #{key.join ' '} not found."
25
+ else
26
+ fail "Invalid key: #{key.inspect}"
27
+ end
28
+ end
29
+ # rubocop:enable MethodLength
30
+
31
+ def find_network_device_by_name(name)
32
+ @links.each do |each|
33
+ device = each.find_network_device_by_name(name)
34
+ return device if device
35
+ end
36
+ fail "No network device found for #{name}."
37
+ end
38
+
17
39
  def vswitches
18
40
  @all.values.select { |each| each.is_a? OpenVswitch }
19
41
  end
@@ -22,10 +44,6 @@ module Phut
22
44
  @all.values.select { |each| each.is_a? Vhost }
23
45
  end
24
46
 
25
- def links
26
- @all.values.select { |each| each.is_a? VirtualLink }
27
- end
28
-
29
47
  def run
30
48
  links.each(&:run)
31
49
  vhosts.each { |each| each.run vhosts }
@@ -49,10 +67,8 @@ module Phut
49
67
  Vhost.new(attrs[:ip], attrs[:mac], attrs[:promisc], name, @logger)
50
68
  end
51
69
 
52
- # This method smells of :reek:LongParameterList
53
- def add_link(name_a, device_a, name_b, device_b)
54
- @all[[name_a, name_b]] =
55
- VirtualLink.new(name_a, device_a, name_b, device_b, @logger)
70
+ def add_link(name_a, name_b)
71
+ @links << VirtualLink.new(name_a, name_b, @logger)
56
72
  end
57
73
 
58
74
  private
@@ -9,12 +9,12 @@ module Phut
9
9
 
10
10
  attr_reader :dpid
11
11
  alias_method :datapath_id, :dpid
12
- attr_writer :interfaces
12
+ attr_reader :network_devices
13
13
 
14
14
  def initialize(dpid, name = nil, logger = NullLogger.new)
15
15
  @dpid = dpid
16
16
  @name = name
17
- @interfaces = []
17
+ @network_devices = []
18
18
  @logger = logger
19
19
  end
20
20
 
@@ -26,25 +26,29 @@ module Phut
26
26
  "vswitch (name = #{name}, dpid = #{format('%#x', @dpid)})"
27
27
  end
28
28
 
29
+ # rubocop:disable MethodLength
29
30
  # rubocop:disable AbcSize
30
31
  def run
31
- sh "sudo ovs-vsctl add-br #{name}"
32
- sh "sudo /sbin/sysctl -w net.ipv6.conf.#{name}.disable_ipv6=1 -q"
33
- @interfaces.each { |each| sh "sudo ovs-vsctl add-port #{name} #{each}" }
34
- sh "sudo ovs-vsctl set bridge #{name} protocols=OpenFlow10" \
35
- " other-config:datapath-id=#{dpid_zero_filled}"
36
- sh "sudo ovs-vsctl set-controller #{name} tcp:127.0.0.1:6633"\
37
- " -- set controller #{name} connection-mode=out-of-band"
38
- sh "sudo ovs-vsctl set-fail-mode #{name} secure"
32
+ sh "sudo ovs-vsctl add-br #{bridge_name}"
33
+ sh "sudo /sbin/sysctl -w net.ipv6.conf.#{bridge_name}.disable_ipv6=1 -q"
34
+ @network_devices.each do |each|
35
+ sh "sudo ovs-vsctl add-port #{bridge_name} #{each}"
36
+ end
37
+ sh "sudo ovs-vsctl set bridge #{bridge_name} protocols=OpenFlow10" \
38
+ " other-config:datapath-id=#{dpid_zero_filled}"
39
+ sh "sudo ovs-vsctl set-controller #{bridge_name} tcp:127.0.0.1:6633"\
40
+ " -- set controller #{bridge_name} connection-mode=out-of-band"
41
+ sh "sudo ovs-vsctl set-fail-mode #{bridge_name} secure"
39
42
  rescue
40
43
  raise "Open vSwitch (dpid = #{@dpid}) is already running!"
41
44
  end
42
45
  alias_method :start, :run
46
+ # rubocop:enable MethodLength
43
47
  # rubocop:enable AbcSize
44
48
 
45
49
  def stop
46
50
  fail "Open vSwitch (dpid = #{@dpid}) is not running!" unless running?
47
- sh "sudo ovs-vsctl del-br #{name}"
51
+ sh "sudo ovs-vsctl del-br #{bridge_name}"
48
52
  end
49
53
  alias_method :shutdown, :stop
50
54
 
@@ -54,23 +58,27 @@ module Phut
54
58
  end
55
59
 
56
60
  def bring_port_up(port_number)
57
- sh "sudo ovs-ofctl mod-port #{name} #{port_number} up"
61
+ sh "sudo ovs-ofctl mod-port #{bridge_name} #{port_number} up"
58
62
  end
59
63
 
60
64
  def bring_port_down(port_number)
61
- sh "sudo ovs-ofctl mod-port #{name} #{port_number} down"
65
+ sh "sudo ovs-ofctl mod-port #{bridge_name} #{port_number} down"
62
66
  end
63
67
 
64
68
  def dump_flows
65
- `sudo ovs-ofctl dump-flows #{name}`
69
+ `sudo ovs-ofctl dump-flows #{bridge_name}`
66
70
  end
67
71
 
68
72
  def running?
69
- system "sudo ovs-vsctl br-exists #{name}"
73
+ system "sudo ovs-vsctl br-exists #{bridge_name}"
70
74
  end
71
75
 
72
76
  private
73
77
 
78
+ def bridge_name
79
+ 'br' + name
80
+ end
81
+
74
82
  def restart
75
83
  stop
76
84
  start
data/lib/phut/parser.rb CHANGED
@@ -7,45 +7,42 @@ module Phut
7
7
  class Parser
8
8
  def initialize(logger = NullLogger.new)
9
9
  @config = Configuration.new(logger)
10
+ @port_number = Hash.new(0)
10
11
  end
11
12
 
12
13
  def parse(file)
13
14
  Syntax.new(@config).instance_eval IO.read(file), file
14
- assign_vswitch_interfaces
15
- assign_vhost_interface
15
+ connect_links_to_switches
16
+ connect_links_to_vhosts
16
17
  @config
17
18
  end
18
19
 
19
20
  private
20
21
 
21
- def assign_vswitch_interfaces
22
- @config.vswitches.each do |each|
23
- each.interfaces = find_interfaces_by_name(each.name)
22
+ def connect_links_to_switches
23
+ @config.links.each do |each|
24
+ maybe_assign_network_device_to_vswitch each
24
25
  end
25
26
  end
26
27
 
27
- def assign_vhost_interface
28
+ def connect_links_to_vhosts
28
29
  @config.vhosts.each do |each|
29
- each.interface = find_host_interface_by_name(each.name)
30
+ each.network_device = @config.find_network_device_by_name(each.name)
30
31
  end
31
32
  end
32
33
 
33
- def find_interfaces_by_name(name)
34
- find_device_by_name(name, :name_a, :device_a) +
35
- find_device_by_name(name, :name_b, :device_b)
36
- end
37
-
38
- def find_host_interface_by_name(name)
39
- find_interfaces_by_name(name).tap do |interface|
40
- fail "No link found for host #{name}" if interface.empty?
41
- fail "Multiple links connect to host #{name}" if interface.size > 1
42
- end.first
34
+ def maybe_assign_network_device_to_vswitch(link)
35
+ @config.vswitches.each do |each|
36
+ switch_name = each.name
37
+ network_device = link.find_network_device_by_name(switch_name)
38
+ next unless network_device
39
+ network_device.port_number = new_port_number(switch_name)
40
+ each.network_devices << network_device
41
+ end
43
42
  end
44
43
 
45
- def find_device_by_name(name, name_type, device_type)
46
- @config.links.select do |each|
47
- each.__send__(name_type) == name
48
- end.map(&device_type)
44
+ def new_port_number(switch_name)
45
+ @port_number[switch_name] += 1
49
46
  end
50
47
  end
51
48
  end
data/lib/phut/syntax.rb CHANGED
@@ -71,42 +71,8 @@ module Phut
71
71
  end
72
72
  end
73
73
 
74
- # The 'link name_a, name_b' directive.
75
- class LinkDirective
76
- # Generates an unique Link ID
77
- class LinkId
78
- def initialize
79
- init
80
- end
81
-
82
- def init
83
- @index = 0
84
- end
85
-
86
- def generate
87
- @index += 1
88
- end
89
- end
90
-
91
- LinkIdSingleton = LinkId.new
92
-
93
- def initialize(name_a, name_b, link_id)
94
- @attributes = {}
95
- @attributes[:name_a] = name_a
96
- @attributes[:name_b] = name_b
97
- link_id = LinkIdSingleton.generate
98
- @attributes[:device_a] = "link#{link_id}-0"
99
- @attributes[:device_b] = "link#{link_id}-1"
100
- end
101
-
102
- def [](key)
103
- @attributes[key]
104
- end
105
- end
106
-
107
74
  def initialize(config)
108
75
  @config = config
109
- LinkDirective::LinkIdSingleton.init
110
76
  end
111
77
 
112
78
  def vswitch(alias_name = nil, &block)
@@ -120,9 +86,7 @@ module Phut
120
86
  end
121
87
 
122
88
  def link(name_a, name_b)
123
- link_id = @config.links.size
124
- attrs = LinkDirective.new(name_a, name_b, link_id)
125
- @config.add_link name_a, attrs[:device_a], name_b, attrs[:device_b]
89
+ @config.add_link name_a, name_b
126
90
  end
127
91
  end
128
92
  end
data/lib/phut/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Base module.
2
2
  module Phut
3
- VERSION = '0.3.1'
3
+ VERSION = '0.4.0'
4
4
  end