vagrant-conoha 0.1.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 +35 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +19 -0
- data/LICENSE +23 -0
- data/Rakefile +25 -0
- data/Vagrantfile +71 -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-conoha.rb +29 -0
- data/lib/vagrant-conoha/action.rb +227 -0
- data/lib/vagrant-conoha/action/abstract_action.rb +22 -0
- data/lib/vagrant-conoha/action/connect_openstack.rb +60 -0
- data/lib/vagrant-conoha/action/create_server.rb +154 -0
- data/lib/vagrant-conoha/action/create_stack.rb +68 -0
- data/lib/vagrant-conoha/action/delete_server.rb +53 -0
- data/lib/vagrant-conoha/action/delete_stack.rb +73 -0
- data/lib/vagrant-conoha/action/message.rb +19 -0
- data/lib/vagrant-conoha/action/provision.rb +60 -0
- data/lib/vagrant-conoha/action/read_ssh_info.rb +72 -0
- data/lib/vagrant-conoha/action/read_state.rb +43 -0
- data/lib/vagrant-conoha/action/resume.rb +24 -0
- data/lib/vagrant-conoha/action/start_server.rb +24 -0
- data/lib/vagrant-conoha/action/stop_server.rb +25 -0
- data/lib/vagrant-conoha/action/suspend.rb +24 -0
- data/lib/vagrant-conoha/action/sync_folders.rb +129 -0
- data/lib/vagrant-conoha/action/wait_accessible.rb +61 -0
- data/lib/vagrant-conoha/action/wait_active.rb +33 -0
- data/lib/vagrant-conoha/action/wait_stop.rb +33 -0
- data/lib/vagrant-conoha/catalog/openstack_catalog.rb +67 -0
- data/lib/vagrant-conoha/client/cinder.rb +39 -0
- data/lib/vagrant-conoha/client/domain.rb +159 -0
- data/lib/vagrant-conoha/client/glance.rb +65 -0
- data/lib/vagrant-conoha/client/heat.rb +49 -0
- data/lib/vagrant-conoha/client/http_utils.rb +116 -0
- data/lib/vagrant-conoha/client/keystone.rb +77 -0
- data/lib/vagrant-conoha/client/neutron.rb +48 -0
- data/lib/vagrant-conoha/client/nova.rb +212 -0
- data/lib/vagrant-conoha/client/openstack.rb +59 -0
- data/lib/vagrant-conoha/client/request_logger.rb +23 -0
- data/lib/vagrant-conoha/client/rest_utils.rb +25 -0
- data/lib/vagrant-conoha/command/abstract_command.rb +51 -0
- data/lib/vagrant-conoha/command/flavor_list.rb +24 -0
- data/lib/vagrant-conoha/command/image_list.rb +29 -0
- data/lib/vagrant-conoha/command/main.rb +51 -0
- data/lib/vagrant-conoha/command/network_list.rb +25 -0
- data/lib/vagrant-conoha/command/openstack_command.rb +16 -0
- data/lib/vagrant-conoha/command/reset.rb +20 -0
- data/lib/vagrant-conoha/command/subnet_list.rb +22 -0
- data/lib/vagrant-conoha/command/utils.rb +22 -0
- data/lib/vagrant-conoha/command/volume_list.rb +25 -0
- data/lib/vagrant-conoha/config.rb +390 -0
- data/lib/vagrant-conoha/config/http.rb +39 -0
- data/lib/vagrant-conoha/config_resolver.rb +285 -0
- data/lib/vagrant-conoha/errors.rb +187 -0
- data/lib/vagrant-conoha/logging.rb +39 -0
- data/lib/vagrant-conoha/plugin.rb +48 -0
- data/lib/vagrant-conoha/provider.rb +50 -0
- data/lib/vagrant-conoha/utils.rb +26 -0
- data/lib/vagrant-conoha/version.rb +15 -0
- data/lib/vagrant-conoha/version_checker.rb +76 -0
- data/locales/en.yml +393 -0
- data/spec/vagrant-conoha/action/connect_openstack_spec.rb +695 -0
- data/spec/vagrant-conoha/action/create_server_spec.rb +225 -0
- data/spec/vagrant-conoha/action/create_stack_spec.rb +99 -0
- data/spec/vagrant-conoha/action/delete_server_spec.rb +89 -0
- data/spec/vagrant-conoha/action/delete_stack_spec.rb +63 -0
- data/spec/vagrant-conoha/action/message_spec.rb +33 -0
- data/spec/vagrant-conoha/action/provision_spec.rb +104 -0
- data/spec/vagrant-conoha/action/read_ssh_info_spec.rb +190 -0
- data/spec/vagrant-conoha/action/read_state_spec.rb +81 -0
- data/spec/vagrant-conoha/action/resume_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/start_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/stop_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/suspend_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/sync_folders_spec.rb +155 -0
- data/spec/vagrant-conoha/action/wait_accessible_spec.rb +67 -0
- data/spec/vagrant-conoha/action/wait_active_spec.rb +53 -0
- data/spec/vagrant-conoha/action/wait_stop_spec.rb +53 -0
- data/spec/vagrant-conoha/action_spec.rb +120 -0
- data/spec/vagrant-conoha/client/cinder_spec.rb +127 -0
- data/spec/vagrant-conoha/client/glance_spec.rb +143 -0
- data/spec/vagrant-conoha/client/heat_spec.rb +128 -0
- data/spec/vagrant-conoha/client/keystone_spec.rb +150 -0
- data/spec/vagrant-conoha/client/neutron_spec.rb +171 -0
- data/spec/vagrant-conoha/client/nova_spec.rb +757 -0
- data/spec/vagrant-conoha/client/utils_spec.rb +176 -0
- data/spec/vagrant-conoha/command/flavor_list_spec.rb +43 -0
- data/spec/vagrant-conoha/command/image_list_spec.rb +95 -0
- data/spec/vagrant-conoha/command/network_list_spec.rb +65 -0
- data/spec/vagrant-conoha/command/reset_spec.rb +24 -0
- data/spec/vagrant-conoha/command/subnet_list_spec.rb +45 -0
- data/spec/vagrant-conoha/command/volume_list_spec.rb +40 -0
- data/spec/vagrant-conoha/config_resolver_spec.rb +860 -0
- data/spec/vagrant-conoha/config_spec.rb +373 -0
- data/spec/vagrant-conoha/e2e_spec.rb.save +27 -0
- data/spec/vagrant-conoha/provider_spec.rb +13 -0
- data/spec/vagrant-conoha/spec_helper.rb +37 -0
- data/spec/vagrant-conoha/utils_spec.rb +129 -0
- data/spec/vagrant-conoha/version_checker_spec.rb +39 -0
- data/stackrc +25 -0
- data/vagrant-conoha.gemspec +32 -0
- metadata +343 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-conoha/client/http_utils'
|
|
5
|
+
require 'vagrant-conoha/client/rest_utils'
|
|
6
|
+
require 'vagrant-conoha/client/domain'
|
|
7
|
+
|
|
8
|
+
module VagrantPlugins
|
|
9
|
+
module ConoHa
|
|
10
|
+
class GlanceClient
|
|
11
|
+
include Singleton
|
|
12
|
+
include VagrantPlugins::ConoHa::HttpUtils
|
|
13
|
+
include VagrantPlugins::ConoHa::Domain
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@logger = Log4r::Logger.new('vagrant_openstack::glance')
|
|
17
|
+
@session = VagrantPlugins::ConoHa.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-conoha/client/http_utils'
|
|
5
|
+
require 'vagrant-conoha/client/domain'
|
|
6
|
+
|
|
7
|
+
module VagrantPlugins
|
|
8
|
+
module ConoHa
|
|
9
|
+
class HeatClient
|
|
10
|
+
include Singleton
|
|
11
|
+
include VagrantPlugins::ConoHa::HttpUtils
|
|
12
|
+
include VagrantPlugins::ConoHa::Domain
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::glance')
|
|
16
|
+
@session = VagrantPlugins::ConoHa.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-conoha/client/keystone'
|
|
5
|
+
require 'vagrant-conoha/client/request_logger'
|
|
6
|
+
require 'vagrant-conoha/client/rest_utils'
|
|
7
|
+
|
|
8
|
+
module VagrantPlugins
|
|
9
|
+
module ConoHa
|
|
10
|
+
module HttpUtils
|
|
11
|
+
include VagrantPlugins::ConoHa::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,77 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-conoha/client/request_logger'
|
|
5
|
+
|
|
6
|
+
module VagrantPlugins
|
|
7
|
+
module ConoHa
|
|
8
|
+
class KeystoneClient
|
|
9
|
+
include Singleton
|
|
10
|
+
include VagrantPlugins::ConoHa::HttpUtils::RequestLogger
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@logger = Log4r::Logger.new('vagrant_openstack::keystone')
|
|
14
|
+
@session = VagrantPlugins::ConoHa.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
|
+
post_body =
|
|
23
|
+
{
|
|
24
|
+
auth:
|
|
25
|
+
{
|
|
26
|
+
tenantName: config.tenant_name,
|
|
27
|
+
passwordCredentials:
|
|
28
|
+
{
|
|
29
|
+
username: config.username,
|
|
30
|
+
password: '****'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
auth_url = get_auth_url_v2 env
|
|
36
|
+
|
|
37
|
+
headers = {
|
|
38
|
+
content_type: :json,
|
|
39
|
+
accept: :json
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
log_request(:POST, auth_url, post_body.to_json, headers)
|
|
43
|
+
|
|
44
|
+
post_body[:auth][:passwordCredentials][:password] = config.password
|
|
45
|
+
|
|
46
|
+
authentication = RestUtils.post(env, auth_url, post_body.to_json, headers) do |response|
|
|
47
|
+
log_response(response)
|
|
48
|
+
case response.code
|
|
49
|
+
when 200
|
|
50
|
+
response
|
|
51
|
+
when 401
|
|
52
|
+
fail Errors::AuthenticationFailed
|
|
53
|
+
when 404
|
|
54
|
+
fail Errors::BadAuthenticationEndpoint
|
|
55
|
+
else
|
|
56
|
+
fail Errors::VagrantOpenstackError, message: response.to_s
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
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
|
+
|
|
65
|
+
access['serviceCatalog']
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def get_auth_url_v2(env)
|
|
71
|
+
url = env[:machine].provider_config.openstack_auth_url
|
|
72
|
+
return url if url.match(%r{/tokens/*$})
|
|
73
|
+
"#{url}/tokens"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-conoha/client/http_utils'
|
|
5
|
+
require 'vagrant-conoha/client/domain'
|
|
6
|
+
|
|
7
|
+
module VagrantPlugins
|
|
8
|
+
module ConoHa
|
|
9
|
+
class NeutronClient
|
|
10
|
+
include Singleton
|
|
11
|
+
include VagrantPlugins::ConoHa::HttpUtils
|
|
12
|
+
include VagrantPlugins::ConoHa::Domain
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::neutron')
|
|
16
|
+
@session = VagrantPlugins::ConoHa.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,212 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-conoha/client/http_utils'
|
|
5
|
+
require 'vagrant-conoha/client/domain'
|
|
6
|
+
|
|
7
|
+
module VagrantPlugins
|
|
8
|
+
module ConoHa
|
|
9
|
+
class NovaClient
|
|
10
|
+
include Singleton
|
|
11
|
+
include VagrantPlugins::ConoHa::HttpUtils
|
|
12
|
+
include VagrantPlugins::ConoHa::Domain
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@logger = Log4r::Logger.new('vagrant_openstack::nova')
|
|
16
|
+
@session = VagrantPlugins::ConoHa.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)
|
|
46
|
+
images_json = get(env, "#{@session.endpoints[:compute]}/images")
|
|
47
|
+
JSON.parse(images_json)['images'].map { |fl| Image.new(fl['id'], fl['name'], 'unknown') }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def create_server(env, options)
|
|
51
|
+
server = {}.tap do |s|
|
|
52
|
+
s['name'] = options[:name]
|
|
53
|
+
if options[:image_ref].nil?
|
|
54
|
+
s['block_device_mapping'] = [{ volume_id: options[:volume_boot][:id],
|
|
55
|
+
device_name: options[:volume_boot][:device] }] if options[:volume_boot].key?(:id)
|
|
56
|
+
s['block_device_mapping_v2'] = [{ boot_index: '0',
|
|
57
|
+
volume_size: options[:volume_boot][:size],
|
|
58
|
+
uuid: options[:volume_boot][:image],
|
|
59
|
+
device_name: options[:volume_boot][:device],
|
|
60
|
+
source_type: 'image',
|
|
61
|
+
destination_type: 'volume',
|
|
62
|
+
delete_on_termination: options[:volume_boot][:delete_on_destroy] }]\
|
|
63
|
+
if options[:volume_boot].key?(:image)
|
|
64
|
+
else
|
|
65
|
+
s['imageRef'] = options[:image_ref]
|
|
66
|
+
end
|
|
67
|
+
s['flavorRef'] = options[:flavor_ref]
|
|
68
|
+
s['key_name'] = options[:keypair]
|
|
69
|
+
s['availability_zone'] = options[:availability_zone] unless options[:availability_zone].nil?
|
|
70
|
+
s['security_groups'] = options[:security_groups] unless options[:security_groups].nil?
|
|
71
|
+
s['user_data'] = Base64.encode64(options[:user_data]) unless options[:user_data].nil?
|
|
72
|
+
s['metadata'] = options[:metadata] unless options[:metadata].nil?
|
|
73
|
+
s['networks'] = options[:networks] unless options[:networks].nil? || options[:networks].empty?
|
|
74
|
+
end
|
|
75
|
+
object = { server: server }
|
|
76
|
+
object['os:scheduler_hints'] = options[:scheduler_hints] unless options[:scheduler_hints].nil?
|
|
77
|
+
server = post(env, "#{@session.endpoints[:compute]}/servers", object.to_json)
|
|
78
|
+
JSON.parse(server)['server']['id']
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def delete_server(env, server_id)
|
|
82
|
+
instance_exists do
|
|
83
|
+
delete(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def suspend_server(env, server_id)
|
|
88
|
+
instance_exists do
|
|
89
|
+
change_server_state(env, server_id, :suspend)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def resume_server(env, server_id)
|
|
94
|
+
instance_exists do
|
|
95
|
+
change_server_state(env, server_id, :resume)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def stop_server(env, server_id)
|
|
100
|
+
instance_exists do
|
|
101
|
+
change_server_state(env, server_id, :stop)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def start_server(env, server_id)
|
|
106
|
+
instance_exists do
|
|
107
|
+
change_server_state(env, server_id, :start)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def get_server_details(env, server_id)
|
|
112
|
+
instance_exists do
|
|
113
|
+
server_details = get(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
|
|
114
|
+
JSON.parse(server_details)['server']
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def add_floating_ip(env, server_id, floating_ip)
|
|
119
|
+
instance_exists do
|
|
120
|
+
check_floating_ip(env, floating_ip)
|
|
121
|
+
|
|
122
|
+
post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
|
|
123
|
+
{ addFloatingIp: { address: floating_ip } }.to_json)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def import_keypair(env, public_key)
|
|
128
|
+
keyname = "vagrant-generated-#{Kernel.rand(36**8).to_s(36)}"
|
|
129
|
+
|
|
130
|
+
key_details = post(env, "#{@session.endpoints[:compute]}/os-keypairs",
|
|
131
|
+
{ keypair:
|
|
132
|
+
{
|
|
133
|
+
name: keyname,
|
|
134
|
+
public_key: public_key
|
|
135
|
+
}
|
|
136
|
+
}.to_json)
|
|
137
|
+
JSON.parse(key_details)['keypair']['name']
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def import_keypair_from_file(env, public_key_path)
|
|
141
|
+
fail "File specified in public_key_path #{public_key_path} doesn't exist" unless File.exist?(public_key_path)
|
|
142
|
+
file = File.open(public_key_path)
|
|
143
|
+
import_keypair(env, file.read)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def delete_keypair_if_vagrant(env, server_id)
|
|
147
|
+
instance_exists do
|
|
148
|
+
keyname = get_server_details(env, server_id)['key_name']
|
|
149
|
+
if keyname
|
|
150
|
+
delete(env, "#{@session.endpoints[:compute]}/os-keypairs/#{keyname}") if keyname.start_with?('vagrant-generated-')
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def get_floating_ip_pools(env)
|
|
156
|
+
floating_ips = get(env, "#{@session.endpoints[:compute]}/os-floating-ip-pools")
|
|
157
|
+
JSON.parse(floating_ips)['floating_ip_pools']
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def get_floating_ips(env)
|
|
161
|
+
floating_ips = get(env, "#{@session.endpoints[:compute]}/os-floating-ips")
|
|
162
|
+
JSON.parse(floating_ips)['floating_ips']
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def attach_volume(env, server_id, volume_id, device = nil)
|
|
166
|
+
instance_exists do
|
|
167
|
+
attachment = post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/os-volume_attachments",
|
|
168
|
+
{
|
|
169
|
+
volumeAttachment: {
|
|
170
|
+
volumeId: volume_id,
|
|
171
|
+
device: device
|
|
172
|
+
}
|
|
173
|
+
}.to_json)
|
|
174
|
+
JSON.parse(attachment)['volumeAttachment']
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
VM_STATES =
|
|
181
|
+
{
|
|
182
|
+
suspend: 'suspend',
|
|
183
|
+
resume: 'resume',
|
|
184
|
+
start: 'os-start',
|
|
185
|
+
stop: 'os-stop'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
def instance_exists
|
|
189
|
+
return yield
|
|
190
|
+
rescue Errors::VagrantOpenstackError => e
|
|
191
|
+
raise Errors::InstanceNotFound if e.extra_data[:code] == 404
|
|
192
|
+
raise e
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def change_server_state(env, server_id, new_state)
|
|
196
|
+
post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
|
|
197
|
+
{ :"#{VM_STATES[new_state.to_sym]}" => nil }.to_json)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def check_floating_ip(env, floating_ip)
|
|
201
|
+
ip_details = get(env, "#{@session.endpoints[:compute]}/os-floating-ips")
|
|
202
|
+
|
|
203
|
+
JSON.parse(ip_details)['floating_ips'].each do |ip|
|
|
204
|
+
next unless ip['ip'] == floating_ip
|
|
205
|
+
return if ip['instance_id'].nil?
|
|
206
|
+
fail Errors::FloatingIPAlreadyAssigned, floating_ip: floating_ip
|
|
207
|
+
end
|
|
208
|
+
fail Errors::FloatingIPNotAvailable, floating_ip: floating_ip
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|