vagrant-openstack-illuin-provider 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|