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 +4 -4
- data/CHANGELOG.md +12 -1
- data/Rakefile +3 -1
- data/bin/phut +8 -0
- data/features/dsl_link.feature +42 -13
- data/features/shell.feature +1 -0
- data/features/step_definitions/phut_steps.rb +3 -5
- data/lib/phut/configuration.rb +28 -12
- data/lib/phut/open_vswitch.rb +23 -15
- data/lib/phut/parser.rb +18 -21
- data/lib/phut/syntax.rb +1 -37
- data/lib/phut/version.rb +1 -1
- data/lib/phut/vhost.rb +2 -2
- data/lib/phut/virtual_link.rb +29 -4
- data/phut.gemspec +1 -0
- data/spec/phut/open_vswitch_spec.rb +1 -1
- data/tasks/.gitignore +34 -0
- data/tasks/LICENSE +675 -0
- data/tasks/README.md +6 -0
- data/tasks/cucumber.rake +1 -3
- data/tasks/flay.rake +15 -0
- data/tasks/gem.rake +3 -1
- data/tasks/relish.rake +5 -1
- data/tasks/rspec.rake +0 -1
- data/tasks/yard.rake +11 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 681a58fd291ea016d0ffc8d56a9c62fb3ab38568
|
4
|
+
data.tar.gz: 48d70fb96ecac1cbddb1868172d4b8a0af0163ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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|
|
data/features/dsl_link.feature
CHANGED
@@ -1,22 +1,51 @@
|
|
1
|
-
Feature: The link DSL
|
1
|
+
Feature: The link directive of phut DSL
|
2
2
|
@sudo
|
3
|
-
Scenario:
|
3
|
+
Scenario: link name_a, name_b
|
4
4
|
Given a file named "network.conf" with:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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:
|
14
|
+
Scenario: link alias_a, alias_b
|
15
15
|
Given a file named "network.conf" with:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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)"
|
data/features/shell.feature
CHANGED
@@ -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
|
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
|
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).
|
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
|
data/lib/phut/configuration.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
53
|
-
|
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
|
data/lib/phut/open_vswitch.rb
CHANGED
@@ -9,12 +9,12 @@ module Phut
|
|
9
9
|
|
10
10
|
attr_reader :dpid
|
11
11
|
alias_method :datapath_id, :dpid
|
12
|
-
|
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
|
-
@
|
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 #{
|
32
|
-
sh "sudo /sbin/sysctl -w net.ipv6.conf.#{
|
33
|
-
@
|
34
|
-
|
35
|
-
|
36
|
-
sh "sudo ovs-vsctl set
|
37
|
-
"
|
38
|
-
sh "sudo ovs-vsctl set-
|
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 #{
|
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 #{
|
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 #{
|
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 #{
|
69
|
+
`sudo ovs-ofctl dump-flows #{bridge_name}`
|
66
70
|
end
|
67
71
|
|
68
72
|
def running?
|
69
|
-
system "sudo ovs-vsctl br-exists #{
|
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
|
-
|
15
|
-
|
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
|
22
|
-
@config.
|
23
|
-
|
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
|
28
|
+
def connect_links_to_vhosts
|
28
29
|
@config.vhosts.each do |each|
|
29
|
-
each.
|
30
|
+
each.network_device = @config.find_network_device_by_name(each.name)
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
46
|
-
@
|
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
|
-
|
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