phut 0.7.7 → 0.7.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rubocop.yml +14 -1
- data/.travis.yml +2 -6
- data/Gemfile +30 -2
- data/Gemfile.lock +156 -0
- data/README.md +7 -2
- data/Rakefile +4 -3
- data/bin/phut +35 -83
- data/bin/vhost +28 -26
- data/features/{dsl.feature → dsl/error.feature} +8 -6
- data/features/{dsl_link.feature → dsl/link.feature} +11 -14
- data/features/dsl/netns.feature +115 -0
- data/features/dsl/vhost.feature +37 -0
- data/features/{dsl_vswitch.feature → dsl/vswitch.feature} +12 -12
- data/features/phut_run.feature +15 -0
- data/features/shell/vswitch#destroy.feature +10 -0
- data/features/shell/vswitch#ports.feature +36 -0
- data/features/shell/vswitch.all.feature +26 -0
- data/features/shell/vswitch.create.feature +30 -0
- data/features/shell/vswitch.destroy.feature +19 -0
- data/features/shell/vswitch.destroy_all.feature +18 -0
- data/features/step_definitions/link_steps.rb +5 -0
- data/features/step_definitions/netns_steps.rb +31 -0
- data/features/step_definitions/phut_steps.rb +5 -34
- data/features/step_definitions/vhost_steps.rb +5 -0
- data/features/step_definitions/vswitch_steps.rb +17 -0
- data/features/support/env.rb +3 -3
- data/features/support/hooks.rb +23 -15
- data/lib/phut.rb +3 -0
- data/lib/phut/finder.rb +19 -0
- data/lib/phut/link.rb +84 -0
- data/lib/phut/netns.rb +111 -22
- data/lib/phut/open_vswitch.rb +98 -96
- data/lib/phut/parser.rb +39 -8
- data/lib/phut/raw_socket.rb +4 -0
- data/lib/phut/route.rb +34 -0
- data/lib/phut/setting.rb +21 -4
- data/lib/phut/shell_runner.rb +13 -2
- data/lib/phut/syntax.rb +31 -14
- data/lib/phut/syntax/directive.rb +9 -1
- data/lib/phut/syntax/netns_directive.rb +13 -2
- data/lib/phut/syntax/vhost_directive.rb +2 -0
- data/lib/phut/syntax/vswitch_directive.rb +3 -1
- data/lib/phut/version.rb +3 -1
- data/lib/phut/veth.rb +68 -0
- data/lib/phut/vhost.rb +99 -58
- data/lib/phut/vhost_daemon.rb +53 -11
- data/lib/phut/vsctl.rb +125 -0
- data/lib/phut/vswitch.rb +10 -0
- data/phut.gemspec +9 -31
- data/tasks/cucumber.rake +5 -1
- data/tasks/flay.rake +2 -0
- data/tasks/flog.rake +3 -1
- data/tasks/gem.rake +2 -0
- data/tasks/minitest.rake +7 -0
- data/tasks/reek.rake +2 -0
- data/tasks/rubocop.rake +2 -0
- data/tasks/yard.rake +2 -0
- data/test/phut/link_test.rb +85 -0
- data/test/phut/netns_test.rb +58 -0
- data/test/phut/open_vswitch_test.rb +125 -0
- data/test/phut/veth_test.rb +48 -0
- data/test/phut/vhost_test.rb +56 -0
- metadata +41 -287
- data/.rspec +0 -3
- data/Guardfile +0 -29
- data/features/dsl_vhost.feature +0 -37
- data/features/phut_kill.feature +0 -27
- data/features/shell.feature +0 -39
- data/lib/phut/configuration.rb +0 -92
- data/lib/phut/null_logger.rb +0 -14
- data/lib/phut/virtual_link.rb +0 -109
- data/spec/phut/parser_spec.rb +0 -66
- data/spec/phut_spec.rb +0 -45
- data/spec/spec_helper.rb +0 -14
- data/tasks/LICENSE +0 -675
- data/tasks/relish.rake +0 -8
- data/tasks/rspec.rake +0 -8
data/.rspec
DELETED
data/Guardfile
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
guard :rspec, cmd: 'bundle exec rspec' do
|
2
|
-
watch(%r{^spec/phut/.+_spec\.rb$})
|
3
|
-
watch(%r{^lib/phut/(.+)\.rb$}) { |m| "spec/phut/#{m[1]}_spec.rb" }
|
4
|
-
watch('spec/spec_helper.rb') { 'spec' }
|
5
|
-
end
|
6
|
-
|
7
|
-
guard :bundler do
|
8
|
-
watch('Gemfile')
|
9
|
-
watch(/^.+\.gemspec/)
|
10
|
-
end
|
11
|
-
|
12
|
-
guard :rubocop, all_on_start: false do
|
13
|
-
watch('Gemfile')
|
14
|
-
watch('Guardfile')
|
15
|
-
watch('Rakefile')
|
16
|
-
watch('bin/phut')
|
17
|
-
watch(/.+\.rake$/)
|
18
|
-
watch(/.+\.rb$/)
|
19
|
-
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
20
|
-
end
|
21
|
-
|
22
|
-
guard 'cucumber', cli: '--tags ~@sudo --tags ~@shell' do
|
23
|
-
watch('bin/phut') { 'features' }
|
24
|
-
watch(%r{^features/.+\.feature$})
|
25
|
-
watch(%r{^features/support/.+$}) { 'features' }
|
26
|
-
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) do |m|
|
27
|
-
Dir[File.join("**/#{m[1]}.feature")][0] || 'features'
|
28
|
-
end
|
29
|
-
end
|
data/features/dsl_vhost.feature
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
Feature: The vhost DSL directive.
|
2
|
-
@sudo
|
3
|
-
Scenario: phut run with "vhost { ip ... }"
|
4
|
-
Given a file named "network.conf" with:
|
5
|
-
"""
|
6
|
-
vhost { ip '192.168.0.1' }
|
7
|
-
vhost { ip '192.168.0.2' }
|
8
|
-
link '192.168.0.1', '192.168.0.2'
|
9
|
-
"""
|
10
|
-
When I do phut run "network.conf"
|
11
|
-
Then a vhost named "192.168.0.1" launches
|
12
|
-
And a vhost named "192.168.0.2" launches
|
13
|
-
|
14
|
-
@sudo
|
15
|
-
Scenario: phut run with "vhost(alias) { ... }"
|
16
|
-
Given a file named "network.conf" with:
|
17
|
-
"""
|
18
|
-
vhost('host1') { ip '192.168.0.1' }
|
19
|
-
vhost('host2') { ip '192.168.0.2' }
|
20
|
-
link 'host1', 'host2'
|
21
|
-
"""
|
22
|
-
When I do phut run "network.conf"
|
23
|
-
Then a vhost named "host1" launches
|
24
|
-
And a vhost named "host2" launches
|
25
|
-
|
26
|
-
@sudo
|
27
|
-
Scenario: phut run with "vhost(alias)"
|
28
|
-
Given a file named "network.conf" with:
|
29
|
-
"""
|
30
|
-
vhost('host1')
|
31
|
-
vhost('host2')
|
32
|
-
link 'host1', 'host2'
|
33
|
-
"""
|
34
|
-
When I do phut run "network.conf"
|
35
|
-
Then a vhost named "host1" launches
|
36
|
-
And a vhost named "host2" launches
|
37
|
-
|
data/features/phut_kill.feature
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
Feature: phut kill command
|
2
|
-
Background:
|
3
|
-
Given a file named "network.conf" with:
|
4
|
-
"""
|
5
|
-
vswitch { datapath_id 0xabc }
|
6
|
-
|
7
|
-
vhost('host1') { ip '192.168.0.1' }
|
8
|
-
vhost('host2') { ip '192.168.0.2' }
|
9
|
-
|
10
|
-
link '0xabc', 'host1'
|
11
|
-
link '0xabc', 'host2'
|
12
|
-
"""
|
13
|
-
And I do phut run "network.conf"
|
14
|
-
|
15
|
-
@sudo
|
16
|
-
Scenario: phut kill vswitch_name
|
17
|
-
When I do phut kill "0xabc"
|
18
|
-
And I run `sudo ovs-vsctl list-br`
|
19
|
-
Then the output from "sudo ovs-vsctl list-br" should not contain "br0xabc"
|
20
|
-
|
21
|
-
@sudo
|
22
|
-
Scenario: phut kill vhost_name
|
23
|
-
When I do phut kill "host1"
|
24
|
-
And I successfully run `sleep 5`
|
25
|
-
Then the following files should not exist:
|
26
|
-
| vhost.host1.pid |
|
27
|
-
| vhost.host1.ctl |
|
data/features/shell.feature
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
Feature: Shell
|
2
|
-
Background:
|
3
|
-
Given I wait 5 seconds for a command to start up
|
4
|
-
And I run `phut -v` interactively
|
5
|
-
|
6
|
-
@shell
|
7
|
-
Scenario: vswitch NUMBER
|
8
|
-
When I type "vswitch 0xabc"
|
9
|
-
And I type "quit"
|
10
|
-
And sleep 1
|
11
|
-
Then a vswitch named "0xabc" should be running
|
12
|
-
|
13
|
-
@shell
|
14
|
-
Scenario: vswitch STRING
|
15
|
-
When I type "vswitch '0xabc'"
|
16
|
-
And I type "quit"
|
17
|
-
And sleep 1
|
18
|
-
Then a vswitch named "0xabc" should be running
|
19
|
-
|
20
|
-
@shell
|
21
|
-
Scenario: vswitch twice and fail
|
22
|
-
And I type "vswitch 0xabc"
|
23
|
-
When I type "vswitch 0xabc"
|
24
|
-
And I type "quit"
|
25
|
-
Then the output should contain "Open vSwitch (dpid = 0xabc) is already running!"
|
26
|
-
|
27
|
-
@shell
|
28
|
-
Scenario: Kill and .pid is deleted
|
29
|
-
And I type "vswitch 0xabc"
|
30
|
-
When I type "kill 0xabc"
|
31
|
-
And I type "quit"
|
32
|
-
And sleep 1
|
33
|
-
Then a vswitch named "0xabc" should not be running
|
34
|
-
|
35
|
-
@shell
|
36
|
-
Scenario: Kill without run and fail
|
37
|
-
When I type "kill 0xabc"
|
38
|
-
And I type "quit"
|
39
|
-
Then the output should contain "Open vSwitch (dpid = 0xabc) is not running!"
|
data/lib/phut/configuration.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'phut/null_logger'
|
2
|
-
require 'phut/open_vswitch'
|
3
|
-
|
4
|
-
module Phut
|
5
|
-
# Parsed DSL data.
|
6
|
-
class Configuration
|
7
|
-
def initialize(&block)
|
8
|
-
OpenVswitch.all.clear
|
9
|
-
Vhost.all.clear
|
10
|
-
Netns.all.clear
|
11
|
-
VirtualLink.all.clear
|
12
|
-
block.call self
|
13
|
-
end
|
14
|
-
|
15
|
-
# rubocop:disable MethodLength
|
16
|
-
def fetch(key)
|
17
|
-
case key
|
18
|
-
when String
|
19
|
-
[OpenVswitch, Vhost, Netns].each do |each|
|
20
|
-
found = each.find_by(name: key)
|
21
|
-
return found if found
|
22
|
-
end
|
23
|
-
fail "Invalid key: #{key.inspect}"
|
24
|
-
when Array
|
25
|
-
VirtualLink.each do |each|
|
26
|
-
return each if [each.name_a, each.name_b].sort == key.sort
|
27
|
-
end
|
28
|
-
fail "link #{key.join ' '} not found."
|
29
|
-
else
|
30
|
-
fail "Invalid key: #{key.inspect}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
# rubocop:enable MethodLength
|
34
|
-
|
35
|
-
def update_connections
|
36
|
-
update_vswitch_ports
|
37
|
-
update_vhost_interfaces
|
38
|
-
update_netns_interfaces
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
def run
|
43
|
-
[VirtualLink, Vhost, Netns, OpenVswitch].each do |klass|
|
44
|
-
klass.each(&:run)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def stop
|
49
|
-
[OpenVswitch, Vhost, Netns, VirtualLink].each do |klass|
|
50
|
-
klass.each(&:stop)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def update_vswitch_ports
|
57
|
-
VirtualLink.each do |each|
|
58
|
-
maybe_connect_link_to_vswitch each
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def maybe_connect_link_to_vswitch(link)
|
63
|
-
vswitches_connected_to(link).each do |each|
|
64
|
-
each.add_network_device link.find_network_device(each)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def vswitches_connected_to(link)
|
69
|
-
OpenVswitch.select { |each| link.connect_to?(each) }
|
70
|
-
end
|
71
|
-
|
72
|
-
def update_vhost_interfaces
|
73
|
-
Vhost.each do |each|
|
74
|
-
each.network_device = find_network_device(each)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def update_netns_interfaces
|
79
|
-
Netns.each do |each|
|
80
|
-
each.network_device = find_network_device(each)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def find_network_device(vhost)
|
85
|
-
VirtualLink.each do |each|
|
86
|
-
device = each.find_network_device(vhost)
|
87
|
-
return device if device
|
88
|
-
end
|
89
|
-
fail "No network device found for #{vhost}."
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
data/lib/phut/null_logger.rb
DELETED
data/lib/phut/virtual_link.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/class/attribute_accessors'
|
2
|
-
require 'phut/null_logger'
|
3
|
-
require 'phut/shell_runner'
|
4
|
-
|
5
|
-
module Phut
|
6
|
-
# Network virtual link.
|
7
|
-
class VirtualLink
|
8
|
-
cattr_accessor(:all, instance_reader: false) { [] }
|
9
|
-
|
10
|
-
def self.create(name_a, name_b, logger = NullLogger.new)
|
11
|
-
new(name_a, name_b, logger).tap { |vlink| all << vlink }
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.each(&block)
|
15
|
-
all.each(&block)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Creates a valid network device name.
|
19
|
-
class NetworkDeviceName
|
20
|
-
attr_reader :name
|
21
|
-
attr_writer :port_number
|
22
|
-
|
23
|
-
def initialize(name)
|
24
|
-
@name = name
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_s
|
28
|
-
@name.tr('.', '_') + port_number_string
|
29
|
-
end
|
30
|
-
|
31
|
-
def inspect
|
32
|
-
to_s
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def port_number_string
|
38
|
-
@port_number ? '_' + @port_number.to_s : ''
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
include ShellRunner
|
43
|
-
|
44
|
-
attr_reader :name_a
|
45
|
-
attr_reader :name_b
|
46
|
-
attr_reader :device_a
|
47
|
-
attr_reader :device_b
|
48
|
-
|
49
|
-
def initialize(name_a, name_b, logger)
|
50
|
-
fail if name_a == name_b
|
51
|
-
@name_a = name_a
|
52
|
-
@name_b = name_b
|
53
|
-
@device_a = NetworkDeviceName.new(name_a)
|
54
|
-
@device_b = NetworkDeviceName.new(name_b)
|
55
|
-
@logger = logger
|
56
|
-
end
|
57
|
-
|
58
|
-
def ==(other)
|
59
|
-
@name_a == other.name_a &&
|
60
|
-
@name_b == other.name_b &&
|
61
|
-
@device_a == other.device_a &&
|
62
|
-
@device_b == other.device_b
|
63
|
-
end
|
64
|
-
|
65
|
-
def run
|
66
|
-
stop if up?
|
67
|
-
add
|
68
|
-
up
|
69
|
-
end
|
70
|
-
|
71
|
-
def stop
|
72
|
-
return unless up?
|
73
|
-
stop!
|
74
|
-
end
|
75
|
-
|
76
|
-
def stop!
|
77
|
-
sh "sudo ip link delete #{@device_a}"
|
78
|
-
rescue
|
79
|
-
raise "link #{@name_a} #{@name_b} does not exist!"
|
80
|
-
end
|
81
|
-
|
82
|
-
def up?
|
83
|
-
/^#{@device_a}\s+Link encap:Ethernet/ =~ `LANG=C ifconfig -a` || false
|
84
|
-
end
|
85
|
-
|
86
|
-
def connect_to?(vswitch)
|
87
|
-
find_network_device(vswitch) || false
|
88
|
-
end
|
89
|
-
|
90
|
-
def find_network_device(vswitch_or_vhost)
|
91
|
-
[@device_a, @device_b].detect do |each|
|
92
|
-
each.name == vswitch_or_vhost.name
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
def add
|
99
|
-
sh "sudo ip link add name #{@device_a} type veth peer name #{@device_b}"
|
100
|
-
sh "sudo /sbin/sysctl -q -w net.ipv6.conf.#{@device_a}.disable_ipv6=1"
|
101
|
-
sh "sudo /sbin/sysctl -q -w net.ipv6.conf.#{@device_b}.disable_ipv6=1"
|
102
|
-
end
|
103
|
-
|
104
|
-
def up
|
105
|
-
sh "sudo /sbin/ifconfig #{@device_a} up"
|
106
|
-
sh "sudo /sbin/ifconfig #{@device_b} up"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
data/spec/phut/parser_spec.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'phut'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
describe Phut::Parser do
|
5
|
-
describe '#parse' do
|
6
|
-
Given do
|
7
|
-
allow(IO).to receive(:read).with('CONFIGURATION_FILE').and_return(string)
|
8
|
-
end
|
9
|
-
Given(:configuration) { Phut::Parser.new.parse 'CONFIGURATION_FILE' }
|
10
|
-
|
11
|
-
context "with 'vswitch { dpid '0xabc' }'" do
|
12
|
-
When(:string) { "vswitch { dpid '0xabc' }" }
|
13
|
-
|
14
|
-
describe '#vswitch' do
|
15
|
-
Then { configuration.fetch('0xabc').datapath_id == 0xabc }
|
16
|
-
Then { configuration.fetch('0xabc').dpid == 0xabc }
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "with 'vswitch { datapath_id '0xabc' }" do
|
21
|
-
When(:string) { "vswitch { datapath_id '0xabc' }" }
|
22
|
-
|
23
|
-
describe '#vswitch' do
|
24
|
-
Then { configuration.fetch('0xabc').dpid == 0xabc }
|
25
|
-
Then { configuration.fetch('0xabc').datapath_id == 0xabc }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "with 'vswitch('my_controller') { dpid '0xabc' }'" do
|
30
|
-
When(:string) { "vswitch('my_controller') { dpid '0xabc' }" }
|
31
|
-
|
32
|
-
describe '#vswitch' do
|
33
|
-
Then { configuration.fetch('my_controller').dpid == 0xabc }
|
34
|
-
Then { configuration.fetch('my_controller').datapath_id == 0xabc }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context "with 'vhost { ip '192.168.0.1' }' ..." do
|
39
|
-
When(:string) do
|
40
|
-
<<-CONFIGURATION
|
41
|
-
vhost { ip '192.168.0.1' }
|
42
|
-
vhost { ip '192.168.0.2' }
|
43
|
-
link '192.168.0.1', '192.168.0.2'
|
44
|
-
CONFIGURATION
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '#vhost' do
|
48
|
-
Then { configuration.fetch('192.168.0.1').ip_address == '192.168.0.1' }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "with 'vhost('host1') { ip '192.168.0.1' }' ..." do
|
53
|
-
When(:string) do
|
54
|
-
<<-CONFIGURATION
|
55
|
-
vhost('host1') { ip '192.168.0.1' }
|
56
|
-
vhost('host2') { ip '192.168.0.2' }
|
57
|
-
link 'host1', 'host2'
|
58
|
-
CONFIGURATION
|
59
|
-
end
|
60
|
-
|
61
|
-
describe '#vhost' do
|
62
|
-
Then { configuration.fetch('host1').ip_address == '192.168.0.1' }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
data/spec/phut_spec.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'phut/setting'
|
2
|
-
|
3
|
-
describe Phut do
|
4
|
-
Given { allow(FileTest).to receive(:directory?).and_return(true) }
|
5
|
-
|
6
|
-
describe '.pid_dir' do
|
7
|
-
Given(:result) { Phut.pid_dir }
|
8
|
-
Then { result == Dir.tmpdir }
|
9
|
-
|
10
|
-
context "pid_dir = '/tmp/pid'" do
|
11
|
-
Given { Phut.pid_dir = '/tmp/pid' }
|
12
|
-
Then { result == '/tmp/pid' }
|
13
|
-
end
|
14
|
-
|
15
|
-
context "pid_dir = '.'" do
|
16
|
-
Given { Phut.pid_dir = '.' }
|
17
|
-
Then { result == File.expand_path('.') }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '.log_dir' do
|
22
|
-
Given(:result) { Phut.log_dir }
|
23
|
-
Then { result == Dir.tmpdir }
|
24
|
-
|
25
|
-
context "log_dir = '/tmp/log'" do
|
26
|
-
Given { Phut.log_dir = '/tmp/log' }
|
27
|
-
Then { result == '/tmp/log' }
|
28
|
-
end
|
29
|
-
|
30
|
-
context "log_dir = '.'" do
|
31
|
-
Given { Phut.log_dir = '.' }
|
32
|
-
Then { result == File.expand_path('.') }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '.socket_dir' do
|
37
|
-
Given(:result) { Phut.socket_dir }
|
38
|
-
Then { result == Dir.tmpdir }
|
39
|
-
|
40
|
-
context "socket_dir = '/tmp/socket'" do
|
41
|
-
Given { Phut.socket_dir = '/tmp/socket' }
|
42
|
-
Then { result == '/tmp/socket' }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|