vagrant-openstack-illuin-provider 0.12.0
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +40 -0
- data/CHANGELOG.md +282 -0
- data/Gemfile +18 -0
- data/RELEASE.md +15 -0
- data/Rakefile +25 -0
- data/Vagrantfile +20 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/functional_tests/Vagrantfile +58 -0
- data/functional_tests/keys/vagrant-openstack +27 -0
- data/functional_tests/keys/vagrant-openstack.pub +1 -0
- data/functional_tests/run_tests.sh +142 -0
- data/lib/vagrant-openstack-illuin-provider.rb +29 -0
- data/lib/vagrant-openstack-illuin-provider/action.rb +344 -0
- data/lib/vagrant-openstack-illuin-provider/action/abstract_action.rb +22 -0
- data/lib/vagrant-openstack-illuin-provider/action/connect_openstack.rb +60 -0
- data/lib/vagrant-openstack-illuin-provider/action/create_server.rb +187 -0
- data/lib/vagrant-openstack-illuin-provider/action/create_stack.rb +76 -0
- data/lib/vagrant-openstack-illuin-provider/action/delete_server.rb +53 -0
- data/lib/vagrant-openstack-illuin-provider/action/delete_stack.rb +73 -0
- data/lib/vagrant-openstack-illuin-provider/action/message.rb +19 -0
- data/lib/vagrant-openstack-illuin-provider/action/provision.rb +60 -0
- data/lib/vagrant-openstack-illuin-provider/action/read_ssh_info.rb +74 -0
- data/lib/vagrant-openstack-illuin-provider/action/read_state.rb +43 -0
- data/lib/vagrant-openstack-illuin-provider/action/resume.rb +24 -0
- data/lib/vagrant-openstack-illuin-provider/action/snapshot_cleanup.rb +32 -0
- data/lib/vagrant-openstack-illuin-provider/action/snapshot_delete.rb +32 -0
- data/lib/vagrant-openstack-illuin-provider/action/snapshot_list.rb +22 -0
- data/lib/vagrant-openstack-illuin-provider/action/snapshot_restore.rb +29 -0
- data/lib/vagrant-openstack-illuin-provider/action/snapshot_save.rb +51 -0
- data/lib/vagrant-openstack-illuin-provider/action/start_server.rb +24 -0
- data/lib/vagrant-openstack-illuin-provider/action/stop_server.rb +25 -0
- data/lib/vagrant-openstack-illuin-provider/action/suspend.rb +24 -0
- data/lib/vagrant-openstack-illuin-provider/action/sync_folders.rb +138 -0
- data/lib/vagrant-openstack-illuin-provider/action/wait_active.rb +33 -0
- data/lib/vagrant-openstack-illuin-provider/action/wait_stop.rb +33 -0
- data/lib/vagrant-openstack-illuin-provider/cap/snapshot_list.rb +15 -0
- data/lib/vagrant-openstack-illuin-provider/catalog/openstack_catalog.rb +90 -0
- data/lib/vagrant-openstack-illuin-provider/client/cinder.rb +39 -0
- data/lib/vagrant-openstack-illuin-provider/client/domain.rb +163 -0
- data/lib/vagrant-openstack-illuin-provider/client/glance.rb +65 -0
- data/lib/vagrant-openstack-illuin-provider/client/heat.rb +49 -0
- data/lib/vagrant-openstack-illuin-provider/client/http_utils.rb +116 -0
- data/lib/vagrant-openstack-illuin-provider/client/keystone.rb +128 -0
- data/lib/vagrant-openstack-illuin-provider/client/neutron.rb +48 -0
- data/lib/vagrant-openstack-illuin-provider/client/nova.rb +303 -0
- data/lib/vagrant-openstack-illuin-provider/client/openstack.rb +59 -0
- data/lib/vagrant-openstack-illuin-provider/client/request_logger.rb +23 -0
- data/lib/vagrant-openstack-illuin-provider/client/rest_utils.rb +28 -0
- data/lib/vagrant-openstack-illuin-provider/command/abstract_command.rb +51 -0
- data/lib/vagrant-openstack-illuin-provider/command/flavor_list.rb +24 -0
- data/lib/vagrant-openstack-illuin-provider/command/floatingip_list.rb +32 -0
- data/lib/vagrant-openstack-illuin-provider/command/image_list.rb +29 -0
- data/lib/vagrant-openstack-illuin-provider/command/main.rb +52 -0
- data/lib/vagrant-openstack-illuin-provider/command/network_list.rb +25 -0
- data/lib/vagrant-openstack-illuin-provider/command/openstack_command.rb +16 -0
- data/lib/vagrant-openstack-illuin-provider/command/reset.rb +20 -0
- data/lib/vagrant-openstack-illuin-provider/command/subnet_list.rb +22 -0
- data/lib/vagrant-openstack-illuin-provider/command/utils.rb +22 -0
- data/lib/vagrant-openstack-illuin-provider/command/volume_list.rb +25 -0
- data/lib/vagrant-openstack-illuin-provider/config.rb +505 -0
- data/lib/vagrant-openstack-illuin-provider/config/http.rb +39 -0
- data/lib/vagrant-openstack-illuin-provider/config_resolver.rb +334 -0
- data/lib/vagrant-openstack-illuin-provider/errors.rb +187 -0
- data/lib/vagrant-openstack-illuin-provider/logging.rb +39 -0
- data/lib/vagrant-openstack-illuin-provider/plugin.rb +58 -0
- data/lib/vagrant-openstack-illuin-provider/provider.rb +50 -0
- data/lib/vagrant-openstack-illuin-provider/utils.rb +81 -0
- data/lib/vagrant-openstack-illuin-provider/version.rb +15 -0
- data/lib/vagrant-openstack-illuin-provider/version_checker.rb +76 -0
- data/locales/en.yml +412 -0
- data/spec/vagrant-openstack-illuin-provider/action/connect_openstack_spec.rb +770 -0
- data/spec/vagrant-openstack-illuin-provider/action/create_server_spec.rb +260 -0
- data/spec/vagrant-openstack-illuin-provider/action/create_stack_spec.rb +99 -0
- data/spec/vagrant-openstack-illuin-provider/action/delete_server_spec.rb +89 -0
- data/spec/vagrant-openstack-illuin-provider/action/delete_stack_spec.rb +63 -0
- data/spec/vagrant-openstack-illuin-provider/action/message_spec.rb +33 -0
- data/spec/vagrant-openstack-illuin-provider/action/provision_spec.rb +97 -0
- data/spec/vagrant-openstack-illuin-provider/action/read_ssh_info_spec.rb +202 -0
- data/spec/vagrant-openstack-illuin-provider/action/read_state_spec.rb +81 -0
- data/spec/vagrant-openstack-illuin-provider/action/resume_server_spec.rb +49 -0
- data/spec/vagrant-openstack-illuin-provider/action/start_server_spec.rb +49 -0
- data/spec/vagrant-openstack-illuin-provider/action/stop_server_spec.rb +49 -0
- data/spec/vagrant-openstack-illuin-provider/action/suspend_server_spec.rb +49 -0
- data/spec/vagrant-openstack-illuin-provider/action/sync_folders_spec.rb +155 -0
- data/spec/vagrant-openstack-illuin-provider/action/wait_active_spec.rb +53 -0
- data/spec/vagrant-openstack-illuin-provider/action/wait_stop_spec.rb +53 -0
- data/spec/vagrant-openstack-illuin-provider/action_spec.rb +120 -0
- data/spec/vagrant-openstack-illuin-provider/client/cinder_spec.rb +129 -0
- data/spec/vagrant-openstack-illuin-provider/client/glance_spec.rb +145 -0
- data/spec/vagrant-openstack-illuin-provider/client/heat_spec.rb +130 -0
- data/spec/vagrant-openstack-illuin-provider/client/keystone_spec.rb +226 -0
- data/spec/vagrant-openstack-illuin-provider/client/neutron_spec.rb +173 -0
- data/spec/vagrant-openstack-illuin-provider/client/nova_spec.rb +760 -0
- data/spec/vagrant-openstack-illuin-provider/client/utils_spec.rb +176 -0
- data/spec/vagrant-openstack-illuin-provider/command/flavor_list_spec.rb +43 -0
- data/spec/vagrant-openstack-illuin-provider/command/floatingip_list_spec.rb +74 -0
- data/spec/vagrant-openstack-illuin-provider/command/image_list_spec.rb +95 -0
- data/spec/vagrant-openstack-illuin-provider/command/network_list_spec.rb +65 -0
- data/spec/vagrant-openstack-illuin-provider/command/reset_spec.rb +24 -0
- data/spec/vagrant-openstack-illuin-provider/command/subnet_list_spec.rb +45 -0
- data/spec/vagrant-openstack-illuin-provider/command/volume_list_spec.rb +40 -0
- data/spec/vagrant-openstack-illuin-provider/config_resolver_spec.rb +879 -0
- data/spec/vagrant-openstack-illuin-provider/config_spec.rb +416 -0
- data/spec/vagrant-openstack-illuin-provider/e2e_spec.rb.save +27 -0
- data/spec/vagrant-openstack-illuin-provider/provider_spec.rb +13 -0
- data/spec/vagrant-openstack-illuin-provider/spec_helper.rb +37 -0
- data/spec/vagrant-openstack-illuin-provider/utils_spec.rb +197 -0
- data/spec/vagrant-openstack-illuin-provider/version_checker_spec.rb +39 -0
- data/stackrc +25 -0
- data/vagrant-openstack-illuin-provider.gemspec +35 -0
- metadata +379 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-openstack-illuin-provider/client/http_utils'
|
|
5
|
+
require 'vagrant-openstack-illuin-provider/client/rest_utils'
|
|
6
|
+
require 'vagrant-openstack-illuin-provider/client/domain'
|
|
7
|
+
|
|
8
|
+
module VagrantPlugins
|
|
9
|
+
module Openstack
|
|
10
|
+
class GlanceClient
|
|
11
|
+
include Singleton
|
|
12
|
+
include VagrantPlugins::Openstack::HttpUtils
|
|
13
|
+
include VagrantPlugins::Openstack::Domain
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@logger = Log4r::Logger.new('vagrant_openstack::glance')
|
|
17
|
+
@session = VagrantPlugins::Openstack.session
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get_api_version_list(env)
|
|
21
|
+
json = RestUtils.get(env, @session.endpoints[:image],
|
|
22
|
+
'X-Auth-Token' => @session.token,
|
|
23
|
+
:accept => :json) do |response|
|
|
24
|
+
log_response(response)
|
|
25
|
+
case response.code
|
|
26
|
+
when 200, 300
|
|
27
|
+
response
|
|
28
|
+
when 401
|
|
29
|
+
fail Errors::AuthenticationFailed
|
|
30
|
+
else
|
|
31
|
+
fail Errors::VagrantOpenstackError, message: response.to_s
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
JSON.parse(json)['versions']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Endpoint /images exists on both v1 and v2 API
|
|
38
|
+
# The attribute 'visibility' is used to detect
|
|
39
|
+
# if the call has been made on v1 or v2
|
|
40
|
+
#
|
|
41
|
+
# In case of v2 we have all the needed information,
|
|
42
|
+
# but in case of v1 we don't and we have to call
|
|
43
|
+
# /images/detail to get full details
|
|
44
|
+
#
|
|
45
|
+
def get_all_images(env)
|
|
46
|
+
images_json = get(env, "#{@session.endpoints[:image]}/images")
|
|
47
|
+
images = JSON.parse(images_json)['images']
|
|
48
|
+
|
|
49
|
+
return images if images.empty?
|
|
50
|
+
|
|
51
|
+
is_v1 = false
|
|
52
|
+
unless images[0].key? 'visibility'
|
|
53
|
+
is_v1 = true
|
|
54
|
+
images_json = get(env, "#{@session.endpoints[:image]}/images/detail")
|
|
55
|
+
images = JSON.parse(images_json)['images']
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
images.map do |i|
|
|
59
|
+
i['visibility'] = i['is_public'] ? 'public' : 'private' if is_v1
|
|
60
|
+
Image.new(i['id'], i['name'], i['visibility'], i['size'], i['min_ram'], i['min_disk'])
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-openstack-illuin-provider/client/http_utils'
|
|
5
|
+
require 'vagrant-openstack-illuin-provider/client/domain'
|
|
6
|
+
|
|
7
|
+
module VagrantPlugins
|
|
8
|
+
module Openstack
|
|
9
|
+
class HeatClient
|
|
10
|
+
include Singleton
|
|
11
|
+
include VagrantPlugins::Openstack::HttpUtils
|
|
12
|
+
include VagrantPlugins::Openstack::Domain
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::glance')
|
|
16
|
+
@session = VagrantPlugins::Openstack.session
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_stack(env, options)
|
|
20
|
+
stack = {}.tap do |s|
|
|
21
|
+
s['stack_name'] = options[:name] if options[:name]
|
|
22
|
+
s['template'] = options[:template]
|
|
23
|
+
end
|
|
24
|
+
stack_res = post(env, "#{@session.endpoints[:orchestration]}/stacks", stack.to_json)
|
|
25
|
+
JSON.parse(stack_res)['stack']['id']
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get_stack_details(env, stack_name, stack_id)
|
|
29
|
+
stack_exists do
|
|
30
|
+
server_details = get(env, "#{@session.endpoints[:orchestration]}/stacks/#{stack_name}/#{stack_id}")
|
|
31
|
+
JSON.parse(server_details)['stack']
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete_stack(env, stack_name, stack_id)
|
|
36
|
+
stack_exists do
|
|
37
|
+
delete(env, "#{@session.endpoints[:orchestration]}/stacks/#{stack_name}/#{stack_id}")
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def stack_exists
|
|
42
|
+
return yield
|
|
43
|
+
rescue Errors::VagrantOpenstackError => e
|
|
44
|
+
raise Errors::StackNotFound if e.extra_data[:code] == 404
|
|
45
|
+
raise e
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-openstack-illuin-provider/client/keystone'
|
|
5
|
+
require 'vagrant-openstack-illuin-provider/client/request_logger'
|
|
6
|
+
require 'vagrant-openstack-illuin-provider/client/rest_utils'
|
|
7
|
+
|
|
8
|
+
module VagrantPlugins
|
|
9
|
+
module Openstack
|
|
10
|
+
module HttpUtils
|
|
11
|
+
include VagrantPlugins::Openstack::HttpUtils::RequestLogger
|
|
12
|
+
|
|
13
|
+
def get(env, url, headers = {})
|
|
14
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
|
15
|
+
@logger.debug("#{calling_method} - start")
|
|
16
|
+
|
|
17
|
+
headers.merge!('X-Auth-Token' => @session.token, :accept => :json)
|
|
18
|
+
|
|
19
|
+
log_request(:GET, url, headers)
|
|
20
|
+
|
|
21
|
+
authenticated(env) do
|
|
22
|
+
RestUtils.get(env, url, headers) { |res| handle_response(res) }.tap do
|
|
23
|
+
@logger.debug("#{calling_method} - end")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def post(env, url, body = nil, headers = {})
|
|
29
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
|
30
|
+
@logger.debug("#{calling_method} - start")
|
|
31
|
+
|
|
32
|
+
headers.merge!('X-Auth-Token' => @session.token, :accept => :json, :content_type => :json)
|
|
33
|
+
|
|
34
|
+
log_request(:POST, url, body, headers)
|
|
35
|
+
|
|
36
|
+
authenticated(env) do
|
|
37
|
+
RestUtils.post(env, url, body, headers) { |res| handle_response(res) }.tap do
|
|
38
|
+
@logger.debug("#{calling_method} - end")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def delete(env, url, headers = {})
|
|
44
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
|
45
|
+
@logger.debug("#{calling_method} - start")
|
|
46
|
+
|
|
47
|
+
headers.merge!('X-Auth-Token' => @session.token, :accept => :json, :content_type => :json)
|
|
48
|
+
|
|
49
|
+
log_request(:DELETE, url, headers)
|
|
50
|
+
|
|
51
|
+
authenticated(env) do
|
|
52
|
+
RestUtils.delete(env, url, headers) { |res| handle_response(res) }.tap do
|
|
53
|
+
@logger.debug("#{calling_method} - end")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_api_version_list(env, service_type)
|
|
59
|
+
url = @session.endpoints[service_type]
|
|
60
|
+
headers = { 'X-Auth-Token' => @session.token, :accept => :json }
|
|
61
|
+
log_request(:GET, url, headers)
|
|
62
|
+
|
|
63
|
+
json = RestUtils.get(env, url, headers) do |response|
|
|
64
|
+
log_response(response)
|
|
65
|
+
case response.code
|
|
66
|
+
when 200, 300
|
|
67
|
+
response
|
|
68
|
+
when 401
|
|
69
|
+
fail Errors::AuthenticationFailed
|
|
70
|
+
else
|
|
71
|
+
fail Errors::VagrantOpenstackError, message: response.to_s
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
JSON.parse(json)['versions']
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
ERRORS =
|
|
80
|
+
{
|
|
81
|
+
'400' => 'badRequest',
|
|
82
|
+
'404' => 'itemNotFound',
|
|
83
|
+
'409' => 'conflictingRequest'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
def handle_response(response)
|
|
87
|
+
log_response(response)
|
|
88
|
+
case response.code
|
|
89
|
+
when 200, 201, 202, 204
|
|
90
|
+
response
|
|
91
|
+
when 401
|
|
92
|
+
fail Errors::AuthenticationRequired
|
|
93
|
+
when 400, 404, 409
|
|
94
|
+
message = JSON.parse(response.to_s)[ERRORS[response.code.to_s]]['message']
|
|
95
|
+
fail Errors::VagrantOpenstackError, message: message, code: response.code
|
|
96
|
+
else
|
|
97
|
+
fail Errors::VagrantOpenstackError, message: response.to_s, code: response.code
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def authenticated(env)
|
|
102
|
+
nb_retry = 0
|
|
103
|
+
begin
|
|
104
|
+
return yield
|
|
105
|
+
rescue Errors::AuthenticationRequired => e
|
|
106
|
+
nb_retry += 1
|
|
107
|
+
env[:ui].warn(e)
|
|
108
|
+
env[:ui].warn(I18n.t('vagrant_openstack.trying_authentication'))
|
|
109
|
+
env[:openstack_client].keystone.authenticate(env)
|
|
110
|
+
retry if nb_retry < 3
|
|
111
|
+
raise e
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-openstack-illuin-provider/client/request_logger'
|
|
5
|
+
|
|
6
|
+
module VagrantPlugins
|
|
7
|
+
module Openstack
|
|
8
|
+
class KeystoneClient
|
|
9
|
+
include Singleton
|
|
10
|
+
include VagrantPlugins::Openstack::HttpUtils::RequestLogger
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@logger = Log4r::Logger.new('vagrant_openstack::keystone')
|
|
14
|
+
@session = VagrantPlugins::Openstack.session
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def authenticate(env)
|
|
18
|
+
@logger.info('Authenticating on Keystone')
|
|
19
|
+
config = env[:machine].provider_config
|
|
20
|
+
@logger.info(I18n.t('vagrant_openstack.client.authentication', project: config.tenant_name, user: config.username))
|
|
21
|
+
|
|
22
|
+
if config.identity_api_version == '2'
|
|
23
|
+
post_body = get_body_2 config
|
|
24
|
+
auth_url = get_auth_url_2 env
|
|
25
|
+
elsif config.identity_api_version == '3'
|
|
26
|
+
post_body = get_body_3 config
|
|
27
|
+
auth_url = get_auth_url_3 env
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
headers = {
|
|
31
|
+
content_type: :json,
|
|
32
|
+
accept: :json
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
log_request(:POST, auth_url, post_body.to_json, headers)
|
|
36
|
+
|
|
37
|
+
if config.identity_api_version == '2'
|
|
38
|
+
post_body[:auth][:passwordCredentials][:password] = config.password
|
|
39
|
+
elsif config.identity_api_version == '3'
|
|
40
|
+
post_body[:auth][:identity][:password][:user][:password] = config.password
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
authentication = RestUtils.post(env, auth_url, post_body.to_json, headers) do |response|
|
|
44
|
+
log_response(response)
|
|
45
|
+
case response.code
|
|
46
|
+
when 200
|
|
47
|
+
response
|
|
48
|
+
when 201
|
|
49
|
+
response
|
|
50
|
+
when 401
|
|
51
|
+
fail Errors::AuthenticationFailed
|
|
52
|
+
when 404
|
|
53
|
+
fail Errors::BadAuthenticationEndpoint
|
|
54
|
+
else
|
|
55
|
+
fail Errors::VagrantOpenstackError, message: response.to_s
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if config.identity_api_version == '2'
|
|
60
|
+
access = JSON.parse(authentication)['access']
|
|
61
|
+
response_token = access['token']
|
|
62
|
+
@session.token = response_token['id']
|
|
63
|
+
@session.project_id = response_token['tenant']['id']
|
|
64
|
+
return access['serviceCatalog']
|
|
65
|
+
elsif config.identity_api_version == '3'
|
|
66
|
+
body = JSON.parse(authentication)
|
|
67
|
+
@session.token = authentication.headers[:x_subject_token]
|
|
68
|
+
@session.project_id = body['token']['project']['id']
|
|
69
|
+
return body['token']['catalog']
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def get_body_2(config)
|
|
76
|
+
{
|
|
77
|
+
auth:
|
|
78
|
+
{
|
|
79
|
+
tenantName: config.tenant_name,
|
|
80
|
+
passwordCredentials:
|
|
81
|
+
{
|
|
82
|
+
username: config.username,
|
|
83
|
+
password: '****'
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def get_body_3(config)
|
|
90
|
+
{
|
|
91
|
+
auth:
|
|
92
|
+
{
|
|
93
|
+
identity: {
|
|
94
|
+
methods: ['password'],
|
|
95
|
+
password: {
|
|
96
|
+
user: {
|
|
97
|
+
name: config.username,
|
|
98
|
+
domain: {
|
|
99
|
+
name: config.domain_name
|
|
100
|
+
},
|
|
101
|
+
password: '****'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
scope: {
|
|
106
|
+
project: {
|
|
107
|
+
name: config.project_name,
|
|
108
|
+
domain: { name: config.domain_name }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def get_auth_url_3(env)
|
|
116
|
+
url = env[:machine].provider_config.openstack_auth_url
|
|
117
|
+
return url if url.match(%r{/tokens/*$})
|
|
118
|
+
"#{url}/auth/tokens"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def get_auth_url_2(env)
|
|
122
|
+
url = env[:machine].provider_config.openstack_auth_url
|
|
123
|
+
return url if url.match(%r{/tokens/*$})
|
|
124
|
+
"#{url}/tokens"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-openstack-illuin-provider/client/http_utils'
|
|
5
|
+
require 'vagrant-openstack-illuin-provider/client/domain'
|
|
6
|
+
|
|
7
|
+
module VagrantPlugins
|
|
8
|
+
module Openstack
|
|
9
|
+
class NeutronClient
|
|
10
|
+
include Singleton
|
|
11
|
+
include VagrantPlugins::Openstack::HttpUtils
|
|
12
|
+
include VagrantPlugins::Openstack::Domain
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::neutron')
|
|
16
|
+
@session = VagrantPlugins::Openstack.session
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_private_networks(env)
|
|
20
|
+
get_networks(env, false)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def get_all_networks(env)
|
|
24
|
+
get_networks(env, true)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def get_subnets(env)
|
|
28
|
+
subnets_json = get(env, "#{@session.endpoints[:network]}/subnets")
|
|
29
|
+
subnets = []
|
|
30
|
+
JSON.parse(subnets_json)['subnets'].each do |n|
|
|
31
|
+
subnets << Subnet.new(n['id'], n['name'], n['cidr'], n['enable_dhcp'], n['network_id'])
|
|
32
|
+
end
|
|
33
|
+
subnets
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def get_networks(env, all)
|
|
39
|
+
networks_json = get(env, "#{@session.endpoints[:network]}/networks")
|
|
40
|
+
networks = []
|
|
41
|
+
JSON.parse(networks_json)['networks'].each do |n|
|
|
42
|
+
networks << Item.new(n['id'], n['name']) if all || n['tenant_id'].eql?(@session.project_id)
|
|
43
|
+
end
|
|
44
|
+
networks
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-openstack-illuin-provider/client/http_utils'
|
|
5
|
+
require 'vagrant-openstack-illuin-provider/client/domain'
|
|
6
|
+
|
|
7
|
+
module VagrantPlugins
|
|
8
|
+
module Openstack
|
|
9
|
+
class NovaClient
|
|
10
|
+
include Singleton
|
|
11
|
+
include VagrantPlugins::Openstack::HttpUtils
|
|
12
|
+
include VagrantPlugins::Openstack::Domain
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::nova')
|
|
16
|
+
@session = VagrantPlugins::Openstack.session
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_all_flavors(env)
|
|
20
|
+
flavors_json = get(env, "#{@session.endpoints[:compute]}/flavors/detail")
|
|
21
|
+
JSON.parse(flavors_json)['flavors'].map do |fl|
|
|
22
|
+
Flavor.new(fl['id'], fl['name'], fl['vcpus'], fl['ram'], fl['disk'])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def get_all_floating_ips(env)
|
|
27
|
+
ips_json = get(env, "#{@session.endpoints[:compute]}/os-floating-ips",
|
|
28
|
+
'X-Auth-Token' => @session.token,
|
|
29
|
+
:accept => :json)
|
|
30
|
+
JSON.parse(ips_json)['floating_ips'].map { |n| FloatingIP.new(n['ip'], n['pool'], n['instance_id']) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def allocate_floating_ip(env, pool)
|
|
34
|
+
ips_json = post(env, "#{@session.endpoints[:compute]}/os-floating-ips",
|
|
35
|
+
{
|
|
36
|
+
pool: pool
|
|
37
|
+
}.to_json,
|
|
38
|
+
'X-Auth-Token' => @session.token,
|
|
39
|
+
:accept => :json,
|
|
40
|
+
:content_type => :json)
|
|
41
|
+
floating_ip = JSON.parse(ips_json)['floating_ip']
|
|
42
|
+
FloatingIP.new(floating_ip['ip'], floating_ip['pool'], floating_ip['instance_id'])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def get_all_images(env, headers = {})
|
|
46
|
+
images_json = get(env, "#{@session.endpoints[:compute]}/images/detail", headers)
|
|
47
|
+
JSON.parse(images_json)['images'].map do |fl|
|
|
48
|
+
Image.new(
|
|
49
|
+
fl['id'],
|
|
50
|
+
fl['name'],
|
|
51
|
+
'unknown',
|
|
52
|
+
nil,
|
|
53
|
+
fl['minRam'],
|
|
54
|
+
fl['minDisk'],
|
|
55
|
+
fl['metadata']
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Get detailed information about an image
|
|
61
|
+
#
|
|
62
|
+
# @param env [Hash] Vagrant action environment
|
|
63
|
+
# @param image_id [String] Image UUID
|
|
64
|
+
#
|
|
65
|
+
# @return [Hash]
|
|
66
|
+
def get_image_details(env, image_id)
|
|
67
|
+
image_json = get(env, "#{@session.endpoints[:compute]}/images/#{image_id}")
|
|
68
|
+
JSON.parse(image_json)['image']
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def create_server(env, options)
|
|
72
|
+
server = {}.tap do |s|
|
|
73
|
+
s['name'] = options[:name]
|
|
74
|
+
if options[:image_ref].nil?
|
|
75
|
+
s['block_device_mapping'] = [{ volume_id: options[:volume_boot][:id],
|
|
76
|
+
device_name: options[:volume_boot][:device] }] if options[:volume_boot].key?(:id)
|
|
77
|
+
s['block_device_mapping_v2'] = [{ boot_index: '0',
|
|
78
|
+
volume_size: options[:volume_boot][:size],
|
|
79
|
+
uuid: options[:volume_boot][:image],
|
|
80
|
+
device_name: options[:volume_boot][:device],
|
|
81
|
+
source_type: 'image',
|
|
82
|
+
destination_type: 'volume',
|
|
83
|
+
delete_on_termination: options[:volume_boot][:delete_on_destroy] }]\
|
|
84
|
+
if options[:volume_boot].key?(:image)
|
|
85
|
+
else
|
|
86
|
+
s['imageRef'] = options[:image_ref]
|
|
87
|
+
end
|
|
88
|
+
s['flavorRef'] = options[:flavor_ref]
|
|
89
|
+
s['key_name'] = options[:keypair] unless options[:keypair].nil?
|
|
90
|
+
s['availability_zone'] = options[:availability_zone] unless options[:availability_zone].nil?
|
|
91
|
+
s['security_groups'] = options[:security_groups] unless options[:security_groups].nil?
|
|
92
|
+
s['user_data'] = Base64.encode64(options[:user_data]) unless options[:user_data].nil?
|
|
93
|
+
s['metadata'] = options[:metadata] unless options[:metadata].nil?
|
|
94
|
+
s['networks'] = options[:networks] unless options[:networks].nil? || options[:networks].empty?
|
|
95
|
+
end
|
|
96
|
+
object = { server: server }
|
|
97
|
+
object['os:scheduler_hints'] = options[:scheduler_hints] unless options[:scheduler_hints].nil?
|
|
98
|
+
server = post(env, "#{@session.endpoints[:compute]}/servers", object.to_json)
|
|
99
|
+
JSON.parse(server)['server']['id']
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def delete_server(env, server_id)
|
|
103
|
+
instance_exists do
|
|
104
|
+
delete(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def suspend_server(env, server_id)
|
|
109
|
+
instance_exists do
|
|
110
|
+
change_server_state(env, server_id, :suspend)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def resume_server(env, server_id)
|
|
115
|
+
instance_exists do
|
|
116
|
+
change_server_state(env, server_id, :resume)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def stop_server(env, server_id)
|
|
121
|
+
instance_exists do
|
|
122
|
+
change_server_state(env, server_id, :stop)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def start_server(env, server_id)
|
|
127
|
+
instance_exists do
|
|
128
|
+
change_server_state(env, server_id, :start)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def get_server_details(env, server_id)
|
|
133
|
+
instance_exists do
|
|
134
|
+
server_details = get(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
|
|
135
|
+
JSON.parse(server_details)['server']
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def add_floating_ip(env, server_id, floating_ip)
|
|
140
|
+
instance_exists do
|
|
141
|
+
check_floating_ip(env, floating_ip)
|
|
142
|
+
|
|
143
|
+
post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
|
|
144
|
+
{ addFloatingIp: { address: floating_ip } }.to_json)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def check_assigned_floating_ip(env, server_id, floating_ip)
|
|
149
|
+
instance_exists do
|
|
150
|
+
addresses = get_server_details(env, server_id)['addresses']
|
|
151
|
+
addresses.each do |_, network|
|
|
152
|
+
network.each do |network_detail|
|
|
153
|
+
return true if network_detail['addr'] == floating_ip
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
return false
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def import_keypair(env, public_key)
|
|
162
|
+
keyname = "vagrant-generated-#{Kernel.rand(36**8).to_s(36)}"
|
|
163
|
+
|
|
164
|
+
key_details = post(env, "#{@session.endpoints[:compute]}/os-keypairs",
|
|
165
|
+
{ keypair:
|
|
166
|
+
{
|
|
167
|
+
name: keyname,
|
|
168
|
+
public_key: public_key
|
|
169
|
+
}
|
|
170
|
+
}.to_json)
|
|
171
|
+
JSON.parse(key_details)['keypair']['name']
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def import_keypair_from_file(env, public_key_path)
|
|
175
|
+
fail "File specified in public_key_path #{public_key_path} doesn't exist" unless File.exist?(public_key_path)
|
|
176
|
+
file = File.open(public_key_path)
|
|
177
|
+
import_keypair(env, file.read)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def delete_keypair_if_vagrant(env, server_id)
|
|
181
|
+
instance_exists do
|
|
182
|
+
keyname = get_server_details(env, server_id)['key_name']
|
|
183
|
+
if keyname
|
|
184
|
+
delete(env, "#{@session.endpoints[:compute]}/os-keypairs/#{keyname}") if keyname.start_with?('vagrant-generated-')
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def get_floating_ip_pools(env)
|
|
190
|
+
floating_ips = get(env, "#{@session.endpoints[:compute]}/os-floating-ip-pools")
|
|
191
|
+
JSON.parse(floating_ips)['floating_ip_pools']
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def get_floating_ips(env)
|
|
195
|
+
floating_ips = get(env, "#{@session.endpoints[:compute]}/os-floating-ips")
|
|
196
|
+
JSON.parse(floating_ips)['floating_ips']
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def attach_volume(env, server_id, volume_id, device = nil)
|
|
200
|
+
instance_exists do
|
|
201
|
+
attachment = post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/os-volume_attachments",
|
|
202
|
+
{
|
|
203
|
+
volumeAttachment: {
|
|
204
|
+
volumeId: volume_id,
|
|
205
|
+
device: device
|
|
206
|
+
}
|
|
207
|
+
}.to_json)
|
|
208
|
+
JSON.parse(attachment)['volumeAttachment']
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# List snapshot images associated with a particular server
|
|
213
|
+
#
|
|
214
|
+
# @param env [Hash] Vagrant action environment
|
|
215
|
+
# @param server_id [String] Server UUID
|
|
216
|
+
#
|
|
217
|
+
# @return [Array<VagrantPlugins::Openstack::Domain::Image>]
|
|
218
|
+
def list_snapshots(env, server_id)
|
|
219
|
+
get_all_images(env, params: { server: server_id })
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Create a named snapsot for a given VM
|
|
223
|
+
#
|
|
224
|
+
# @param env [Hash] Vagrant action environment
|
|
225
|
+
# @param server_id [String] Server UUID
|
|
226
|
+
# @param snapshot_name [String]
|
|
227
|
+
#
|
|
228
|
+
# @return [void]
|
|
229
|
+
def create_snapshot(env, server_id, snapshot_name)
|
|
230
|
+
instance_exists do
|
|
231
|
+
post(
|
|
232
|
+
env,
|
|
233
|
+
"#{@session.endpoints[:compute]}/servers/#{server_id}/action",
|
|
234
|
+
{ createImage: {
|
|
235
|
+
name: snapshot_name,
|
|
236
|
+
metadata: { vagrant_snapshot: 'true' }
|
|
237
|
+
} }.to_json)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Delete an identified snapshot
|
|
242
|
+
#
|
|
243
|
+
# @param env [Hash] Vagrant action environment
|
|
244
|
+
# @param snapshot_id [String] Snapshot UUID
|
|
245
|
+
#
|
|
246
|
+
# @return [void]
|
|
247
|
+
def delete_snapshot(env, snapshot_id)
|
|
248
|
+
delete(
|
|
249
|
+
env,
|
|
250
|
+
"#{@session.endpoints[:compute]}/images/#{snapshot_id}")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Restore a VM to an identified snapshot
|
|
254
|
+
#
|
|
255
|
+
# @param env [Hash] Vagrant action environment
|
|
256
|
+
# @param server_id [String] Server UUID
|
|
257
|
+
# @param snapshot_id [String] Snapshot UUID
|
|
258
|
+
#
|
|
259
|
+
# @return [void]
|
|
260
|
+
def restore_snapshot(env, server_id, snapshot_id)
|
|
261
|
+
instance_exists do
|
|
262
|
+
post(
|
|
263
|
+
env,
|
|
264
|
+
"#{@session.endpoints[:compute]}/servers/#{server_id}/action",
|
|
265
|
+
{ rebuild: { imageRef: snapshot_id } }.to_json)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
private
|
|
270
|
+
|
|
271
|
+
VM_STATES =
|
|
272
|
+
{
|
|
273
|
+
suspend: 'suspend',
|
|
274
|
+
resume: 'resume',
|
|
275
|
+
start: 'os-start',
|
|
276
|
+
stop: 'os-stop'
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
def instance_exists
|
|
280
|
+
return yield
|
|
281
|
+
rescue Errors::VagrantOpenstackError => e
|
|
282
|
+
raise Errors::InstanceNotFound if e.extra_data[:code] == 404
|
|
283
|
+
raise e
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def change_server_state(env, server_id, new_state)
|
|
287
|
+
post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
|
|
288
|
+
{ :"#{VM_STATES[new_state.to_sym]}" => nil }.to_json)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def check_floating_ip(env, floating_ip)
|
|
292
|
+
ip_details = get(env, "#{@session.endpoints[:compute]}/os-floating-ips")
|
|
293
|
+
|
|
294
|
+
JSON.parse(ip_details)['floating_ips'].each do |ip|
|
|
295
|
+
next unless ip['ip'] == floating_ip
|
|
296
|
+
return if ip['instance_id'].nil?
|
|
297
|
+
fail Errors::FloatingIPAlreadyAssigned, floating_ip: floating_ip
|
|
298
|
+
end
|
|
299
|
+
fail Errors::FloatingIPNotAvailable, floating_ip: floating_ip
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|