vagrant-openstack-provider 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/.rubocop.yml +28 -0
- data/Appraisals +3 -3
- data/CHANGELOG.md +4 -0
- data/Gemfile +3 -0
- data/Rakefile +6 -2
- data/Vagrantfile +4 -15
- data/gemfiles/latest_stable.gemfile +2 -0
- data/gemfiles/oldest_current.gemfile +2 -0
- data/gemfiles/previous_release.gemfile +2 -0
- data/lib/vagrant-openstack-provider.rb +18 -13
- data/lib/vagrant-openstack-provider/action.rb +112 -46
- data/lib/vagrant-openstack-provider/action/connect_openstack.rb +9 -10
- data/lib/vagrant-openstack-provider/action/create_server.rb +86 -57
- data/lib/vagrant-openstack-provider/action/delete_server.rb +5 -6
- data/lib/vagrant-openstack-provider/action/{is_created.rb → message.rb} +4 -3
- data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +7 -27
- data/lib/vagrant-openstack-provider/action/read_state.rb +7 -9
- data/lib/vagrant-openstack-provider/action/resume.rb +20 -0
- data/lib/vagrant-openstack-provider/action/start_server.rb +22 -0
- data/lib/vagrant-openstack-provider/action/stop_server.rb +22 -0
- data/lib/vagrant-openstack-provider/action/suspend.rb +20 -0
- data/lib/vagrant-openstack-provider/action/sync_folders.rb +27 -38
- data/lib/vagrant-openstack-provider/action/wait_stop.rb +29 -0
- data/lib/vagrant-openstack-provider/client/keystone.rb +76 -0
- data/lib/vagrant-openstack-provider/client/neutron.rb +32 -0
- data/lib/vagrant-openstack-provider/client/nova.rb +166 -0
- data/lib/vagrant-openstack-provider/client/openstack.rb +41 -0
- data/lib/vagrant-openstack-provider/client/utils.rb +38 -0
- data/lib/vagrant-openstack-provider/config.rb +38 -110
- data/lib/vagrant-openstack-provider/errors.rb +7 -3
- data/lib/vagrant-openstack-provider/plugin.rb +8 -8
- data/lib/vagrant-openstack-provider/provider.rb +6 -6
- data/lib/vagrant-openstack-provider/version.rb +1 -1
- data/locales/en.yml +83 -5
- data/numergyrc +22 -0
- data/spec/vagrant-openstack-provider/action/create_server_spec.rb +89 -0
- data/spec/vagrant-openstack-provider/client/keystone_spec.rb +140 -0
- data/spec/vagrant-openstack-provider/client/neutron_spec.rb +53 -0
- data/spec/vagrant-openstack-provider/client/nova_spec.rb +373 -0
- data/spec/vagrant-openstack-provider/client/utils_spec.rb +125 -0
- data/spec/vagrant-openstack-provider/config_spec.rb +117 -0
- data/spec/vagrant-openstack-provider/provider_spec.rb +13 -0
- data/spec/vagrant-openstack-provider/spec_helper.rb +23 -0
- data/vagrant-openstack-provider.gemspec +13 -14
- metadata +40 -30
- data/features/provision.feature +0 -35
- data/features/steps/sdk_steps.rb +0 -13
- data/features/steps/server_steps.rb +0 -25
- data/features/support/env.rb +0 -37
- data/features/support/fog_mock.rb +0 -19
- data/features/vagrant-openstack-provider.feature +0 -70
- data/lib/vagrant-openstack-provider/action/message_already_created.rb +0 -16
- data/lib/vagrant-openstack-provider/action/message_not_created.rb +0 -16
- data/lib/vagrant-openstack-provider/openstack_client.rb +0 -98
- data/spec/vagrant-openstack/config_spec.rb +0 -184
- data/stackrc +0 -31
@@ -1,7 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
|
1
|
+
require 'log4r'
|
2
|
+
require 'restclient'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require 'vagrant-openstack-provider/client/openstack'
|
5
6
|
|
6
7
|
module VagrantPlugins
|
7
8
|
module Openstack
|
@@ -10,17 +11,15 @@ module VagrantPlugins
|
|
10
11
|
# puts the Openstack connection object into the `:openstack_compute` key
|
11
12
|
# in the environment.
|
12
13
|
class ConnectOpenstack
|
13
|
-
def initialize(app,
|
14
|
+
def initialize(app, _env)
|
14
15
|
@app = app
|
15
|
-
@logger = Log4r::Logger.new(
|
16
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::connect_openstack')
|
16
17
|
end
|
17
18
|
|
18
19
|
def call(env)
|
19
|
-
|
20
|
-
config = env[:machine].provider_config
|
21
|
-
client = OpenstackClient::new()
|
20
|
+
client = VagrantPlugins::Openstack
|
22
21
|
env[:openstack_client] = client
|
23
|
-
client.authenticate(env)
|
22
|
+
client.keystone.authenticate(env) if client.session.token.nil?
|
24
23
|
@app.call(env)
|
25
24
|
end
|
26
25
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require 'log4r'
|
2
2
|
require 'socket'
|
3
|
-
require
|
3
|
+
require 'timeout'
|
4
4
|
|
5
5
|
require 'vagrant/util/retryable'
|
6
6
|
|
@@ -10,108 +10,137 @@ module VagrantPlugins
|
|
10
10
|
class CreateServer
|
11
11
|
include Vagrant::Util::Retryable
|
12
12
|
|
13
|
-
def initialize(app,
|
13
|
+
def initialize(app, _env)
|
14
14
|
@app = app
|
15
|
-
@logger = Log4r::Logger.new(
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::create_server')
|
16
16
|
end
|
17
17
|
|
18
18
|
def call(env)
|
19
19
|
config = env[:machine].provider_config
|
20
|
-
|
20
|
+
nova = env[:openstack_client].nova
|
21
21
|
|
22
|
-
|
23
|
-
env
|
24
|
-
|
25
|
-
flavor = find_matching(flavors, config.flavor)
|
26
|
-
raise Errors::NoMatchingFlavor if !flavor
|
27
|
-
|
28
|
-
# Find the image
|
29
|
-
env[:ui].info(I18n.t("vagrant_openstack.finding_image"))
|
30
|
-
images = client.get_all_images(env)
|
31
|
-
image = find_matching(images, config.image)
|
32
|
-
raise Errors::NoMatchingImage if !image
|
33
|
-
|
34
|
-
# Figure out the name for the server
|
22
|
+
flavor = resolve_flavor(env)
|
23
|
+
image = resolve_image(env)
|
24
|
+
networks = resolve_networks(env)
|
35
25
|
server_name = config.server_name || env[:machine].name
|
36
26
|
|
37
|
-
|
38
|
-
env[:ui].info(
|
39
|
-
env[:ui].info(" --
|
40
|
-
env[:ui].info(" --
|
41
|
-
env[:ui].info(" --
|
42
|
-
env[:ui].info(" --
|
43
|
-
env[:ui].info(" -- ImageRef
|
44
|
-
env[:ui].info(" --
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
server_id =
|
54
|
-
|
55
|
-
#TODO(julienvey) Find a network if provided
|
56
|
-
#if config.network
|
57
|
-
# network = find_matching(env[:openstack_network].networks, config.network)
|
58
|
-
# options[:nics] = [{"net_id" => network.id}] if network
|
59
|
-
#end
|
27
|
+
env[:ui].info(I18n.t('vagrant_openstack.launching_server'))
|
28
|
+
env[:ui].info(" -- Tenant : #{config.tenant_name}")
|
29
|
+
env[:ui].info(" -- Name : #{server_name}")
|
30
|
+
env[:ui].info(" -- Flavor : #{flavor.name}")
|
31
|
+
env[:ui].info(" -- FlavorRef : #{flavor.id}")
|
32
|
+
env[:ui].info(" -- Image : #{image.name}")
|
33
|
+
env[:ui].info(" -- ImageRef : #{image.id}")
|
34
|
+
env[:ui].info(" -- KeyPair : #{config.keypair_name}")
|
35
|
+
unless networks.empty?
|
36
|
+
if networks.size == 1
|
37
|
+
env[:ui].info(" -- Network : #{config.networks[0]}")
|
38
|
+
else
|
39
|
+
env[:ui].info(" -- Networks : #{config.networks}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
server_id = nova.create_server(env, server_name, image.id, flavor.id, networks, config.keypair_name)
|
60
44
|
|
61
45
|
# Store the ID right away so we can track it
|
62
46
|
env[:machine].id = server_id
|
63
47
|
|
64
48
|
# Wait for the server to finish building
|
65
|
-
env[:ui].info(I18n.t(
|
49
|
+
env[:ui].info(I18n.t('vagrant_openstack.waiting_for_build'))
|
66
50
|
timeout(200) do
|
67
|
-
while
|
51
|
+
while nova.get_server_details(env, server_id)['status'] != 'ACTIVE'
|
68
52
|
sleep 3
|
69
|
-
@logger.debug(
|
53
|
+
@logger.debug('Waiting for server to be ACTIVE')
|
70
54
|
end
|
71
55
|
end
|
72
56
|
|
73
57
|
if config.floating_ip
|
74
58
|
env[:ui].info("Using floating IP #{config.floating_ip}")
|
75
|
-
|
59
|
+
nova.add_floating_ip(env, server_id, config.floating_ip)
|
76
60
|
end
|
77
61
|
|
78
|
-
|
62
|
+
unless env[:interrupted]
|
79
63
|
# Clear the line one more time so the progress is removed
|
80
64
|
env[:ui].clear_line
|
81
65
|
|
82
66
|
# Wait for SSH to become available
|
83
67
|
host = env[:machine].provider_config.floating_ip
|
84
68
|
ssh_timeout = env[:machine].provider_config.ssh_timeout
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
raise Errors::SshUnavailable,
|
89
|
-
:host => host,
|
90
|
-
:timeout => ssh_timeout
|
69
|
+
unless port_open?(env, host, 22, ssh_timeout)
|
70
|
+
env[:ui].error(I18n.t('vagrant_openstack.timeout'))
|
71
|
+
fail Errors::SshUnavailable, host: host, timeout: ssh_timeout
|
91
72
|
end
|
92
73
|
|
93
|
-
env[:ui].info(I18n.t(
|
74
|
+
env[:ui].info(I18n.t('vagrant_openstack.ready'))
|
94
75
|
end
|
95
76
|
|
96
77
|
@app.call(env)
|
97
78
|
end
|
98
79
|
|
99
|
-
|
80
|
+
private
|
81
|
+
|
82
|
+
def resolve_flavor(env)
|
83
|
+
config = env[:machine].provider_config
|
84
|
+
nova = env[:openstack_client].nova
|
85
|
+
env[:ui].info(I18n.t('vagrant_openstack.finding_flavor'))
|
86
|
+
flavors = nova.get_all_flavors(env)
|
87
|
+
flavor = find_matching(flavors, config.flavor)
|
88
|
+
fail Errors::NoMatchingFlavor unless flavor
|
89
|
+
flavor
|
90
|
+
end
|
91
|
+
|
92
|
+
def resolve_image(env)
|
93
|
+
config = env[:machine].provider_config
|
94
|
+
nova = env[:openstack_client].nova
|
95
|
+
env[:ui].info(I18n.t('vagrant_openstack.finding_image'))
|
96
|
+
images = nova.get_all_images(env)
|
97
|
+
image = find_matching(images, config.image)
|
98
|
+
fail Errors::NoMatchingImage unless image
|
99
|
+
image
|
100
|
+
end
|
101
|
+
|
102
|
+
def resolve_networks(env)
|
103
|
+
config = env[:machine].provider_config
|
104
|
+
return [] if config.networks.nil? || config.networks.empty?
|
105
|
+
env[:ui].info(I18n.t('vagrant_openstack.finding_networks'))
|
106
|
+
|
107
|
+
private_networks = env[:openstack_client].neutron.get_private_networks(env)
|
108
|
+
private_network_ids = private_networks.map { |n| n[:id] }
|
109
|
+
|
110
|
+
networks = []
|
111
|
+
config.networks.each do |network|
|
112
|
+
if private_network_ids.include?(network)
|
113
|
+
networks << network
|
114
|
+
next
|
115
|
+
end
|
116
|
+
net_id = nil
|
117
|
+
private_networks.each do |n| # Bad algorithm complexity, but here we don't care...
|
118
|
+
next unless n[:name].eql? network
|
119
|
+
fail "Multiple networks with name '#{n[:name]}'" unless net_id.nil?
|
120
|
+
net_id = n[:id]
|
121
|
+
end
|
122
|
+
fail "No matching network with name '#{network}'" if net_id.nil?
|
123
|
+
networks << net_id
|
124
|
+
end
|
125
|
+
networks
|
126
|
+
end
|
100
127
|
|
101
128
|
def port_open?(env, ip, port, timeout)
|
102
129
|
start_time = Time.now
|
103
130
|
current_time = start_time
|
131
|
+
nb_retry = 0
|
104
132
|
while (current_time - start_time) <= timeout
|
105
133
|
begin
|
106
|
-
env[:ui].info(I18n.t(
|
134
|
+
env[:ui].info(I18n.t('vagrant_openstack.waiting_for_ssh')) if nb_retry % 5 == 0
|
107
135
|
TCPSocket.new(ip, port)
|
108
136
|
return true
|
109
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
137
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT
|
138
|
+
nb_retry += 1
|
110
139
|
sleep 1
|
111
140
|
end
|
112
141
|
current_time = Time.now
|
113
142
|
end
|
114
|
-
|
143
|
+
false
|
115
144
|
end
|
116
145
|
|
117
146
|
# This method finds a matching _thing_ in a collection of
|
@@ -1,20 +1,19 @@
|
|
1
|
-
require
|
1
|
+
require 'log4r'
|
2
2
|
|
3
3
|
module VagrantPlugins
|
4
4
|
module Openstack
|
5
5
|
module Action
|
6
6
|
# This deletes the running server, if there is one.
|
7
7
|
class DeleteServer
|
8
|
-
def initialize(app,
|
8
|
+
def initialize(app, _env)
|
9
9
|
@app = app
|
10
|
-
@logger = Log4r::Logger.new(
|
10
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::delete_server')
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(env)
|
14
14
|
if env[:machine].id
|
15
|
-
env[:ui].info(I18n.t(
|
16
|
-
|
17
|
-
client.delete_server(env, env[:machine].id)
|
15
|
+
env[:ui].info(I18n.t('vagrant_openstack.deleting_server'))
|
16
|
+
env[:openstack_client].nova.delete_server(env, env[:machine].id)
|
18
17
|
env[:machine].id = nil
|
19
18
|
end
|
20
19
|
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module VagrantPlugins
|
2
2
|
module Openstack
|
3
3
|
module Action
|
4
|
-
class
|
5
|
-
def initialize(app,
|
4
|
+
class Message
|
5
|
+
def initialize(app, _env, message)
|
6
6
|
@app = app
|
7
|
+
@message = message
|
7
8
|
end
|
8
9
|
|
9
10
|
def call(env)
|
10
|
-
env[:
|
11
|
+
env[:ui].info(@message)
|
11
12
|
@app.call(env)
|
12
13
|
end
|
13
14
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'log4r'
|
2
2
|
|
3
3
|
module VagrantPlugins
|
4
4
|
module Openstack
|
@@ -6,9 +6,9 @@ module VagrantPlugins
|
|
6
6
|
# This action reads the SSH info for the machine and puts it into the
|
7
7
|
# `:machine_ssh_info` key in the environment.
|
8
8
|
class ReadSSHInfo
|
9
|
-
def initialize(app,
|
9
|
+
def initialize(app, _env)
|
10
10
|
@app = app
|
11
|
-
@logger = Log4r::Logger.new(
|
11
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::read_ssh_info')
|
12
12
|
end
|
13
13
|
|
14
14
|
def call(env)
|
@@ -18,32 +18,12 @@ module VagrantPlugins
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def read_ssh_info(env)
|
21
|
-
client = env[:openstack_client]
|
22
|
-
machine = env[:machine]
|
23
21
|
config = env[:machine].provider_config
|
24
|
-
|
25
|
-
return nil if machine.id.nil?
|
26
|
-
begin
|
27
|
-
details = client.get_server_details(env, machine.id)
|
28
|
-
rescue Exception => e
|
29
|
-
# The machine can't be found
|
30
|
-
@logger.error(e)
|
31
|
-
@logger.info("Machine couldn't be found, assuming it got destroyed.")
|
32
|
-
machine.id = nil
|
33
|
-
return nil
|
34
|
-
end
|
35
|
-
|
36
|
-
for addr in details['addresses']['private']
|
37
|
-
if addr['OS-EXT-IPS:type'] == 'floating'
|
38
|
-
host = addr['addr']
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
return {
|
22
|
+
{
|
43
23
|
# Usually there should only be one public IP
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
24
|
+
host: config.floating_ip,
|
25
|
+
port: 22,
|
26
|
+
username: config.ssh_username
|
47
27
|
}
|
48
28
|
end
|
49
29
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'log4r'
|
2
2
|
|
3
3
|
module VagrantPlugins
|
4
4
|
module Openstack
|
@@ -6,33 +6,31 @@ module VagrantPlugins
|
|
6
6
|
# This action reads the state of the machine and puts it in the
|
7
7
|
# `:machine_state_id` key in the environment.
|
8
8
|
class ReadState
|
9
|
-
def initialize(app,
|
9
|
+
def initialize(app, _env)
|
10
10
|
@app = app
|
11
|
-
@logger = Log4r::Logger.new(
|
11
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::read_state')
|
12
12
|
end
|
13
13
|
|
14
14
|
def call(env)
|
15
15
|
env[:machine_state_id] = read_state(env)
|
16
|
-
|
17
16
|
@app.call(env)
|
18
17
|
end
|
19
18
|
|
20
19
|
def read_state(env)
|
21
20
|
machine = env[:machine]
|
22
|
-
client = env[:openstack_client]
|
23
21
|
return :not_created if machine.id.nil?
|
24
22
|
|
25
23
|
# Find the machine
|
26
|
-
server =
|
27
|
-
if server.nil? || server['status'] ==
|
24
|
+
server = env[:openstack_client].nova.get_server_details(env, machine.id)
|
25
|
+
if server.nil? || server['status'] == 'DELETED'
|
28
26
|
# The machine can't be found
|
29
|
-
@logger.info(
|
27
|
+
@logger.info('Machine not found or deleted, assuming it got destroyed.')
|
30
28
|
machine.id = nil
|
31
29
|
return :not_created
|
32
30
|
end
|
33
31
|
|
34
32
|
# Return the state
|
35
|
-
|
33
|
+
server['status'].downcase.to_sym
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Openstack
|
3
|
+
module Action
|
4
|
+
class Resume
|
5
|
+
def initialize(app, _env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
if env[:machine].id
|
11
|
+
env[:ui].info I18n.t('vagrant.actions.vm.resume.resuming')
|
12
|
+
env[:openstack_client].nova.resume_server(env, env[:machine].id)
|
13
|
+
end
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Openstack
|
5
|
+
module Action
|
6
|
+
class StartServer
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::start_server')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if env[:machine].id
|
14
|
+
env[:ui].info(I18n.t('vagrant_openstack.starting_server'))
|
15
|
+
env[:openstack_client].nova.start_server(env, env[:machine].id)
|
16
|
+
end
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Openstack
|
5
|
+
module Action
|
6
|
+
class StopServer
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::stop_server')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if env[:machine].id
|
14
|
+
env[:ui].info(I18n.t('vagrant_openstack.stopping_server'))
|
15
|
+
env[:openstack_client].nova.stop_server(env, env[:machine].id)
|
16
|
+
end
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|