fog-openstack 0.1.31 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +4 -1
- data/.travis.yml +5 -5
- data/.zuul.yaml +8 -8
- data/Rakefile +14 -4
- data/fog-openstack.gemspec +3 -2
- data/lib/fog/baremetal/openstack.rb +6 -24
- data/lib/fog/compute/openstack.rb +6 -27
- data/lib/fog/compute/openstack/requests/create_security_group.rb +1 -1
- data/lib/fog/compute/openstack/requests/create_server.rb +1 -1
- data/lib/fog/compute/openstack/requests/evacuate_server.rb +1 -5
- data/lib/fog/container_infra/openstack.rb +6 -25
- data/lib/fog/dns/openstack/v1.rb +5 -17
- data/lib/fog/dns/openstack/v2.rb +5 -22
- data/lib/fog/event/openstack.rb +5 -24
- data/lib/fog/identity/openstack.rb +24 -71
- data/lib/fog/identity/openstack/v2.rb +6 -4
- data/lib/fog/identity/openstack/v3.rb +5 -11
- data/lib/fog/image/openstack/v1.rb +8 -21
- data/lib/fog/image/openstack/v2.rb +8 -21
- data/lib/fog/image/openstack/v2/models/image.rb +1 -1
- data/lib/fog/introspection/openstack.rb +4 -19
- data/lib/fog/key_manager/openstack.rb +5 -47
- data/lib/fog/metering/openstack.rb +8 -23
- data/lib/fog/metric/openstack.rb +7 -26
- data/lib/fog/monitoring/openstack.rb +3 -12
- data/lib/fog/network/openstack.rb +5 -26
- data/lib/fog/network/openstack/requests/set_tenant.rb +0 -1
- data/lib/fog/nfv/openstack.rb +4 -24
- data/lib/fog/openstack.rb +17 -431
- data/lib/fog/openstack/auth/catalog.rb +64 -0
- data/lib/fog/openstack/auth/catalog/v2.rb +23 -0
- data/lib/fog/openstack/auth/catalog/v3.rb +23 -0
- data/lib/fog/openstack/auth/name.rb +65 -0
- data/lib/fog/openstack/auth/token.rb +69 -0
- data/lib/fog/openstack/auth/token/v2.rb +70 -0
- data/lib/fog/openstack/auth/token/v3.rb +116 -0
- data/lib/fog/openstack/core.rb +100 -76
- data/lib/fog/openstack/version.rb +1 -1
- data/lib/fog/orchestration/openstack.rb +4 -21
- data/lib/fog/planning/openstack.rb +13 -23
- data/lib/fog/shared_file_system/openstack.rb +10 -27
- data/lib/fog/storage/openstack.rb +6 -11
- data/lib/fog/volume/openstack.rb +1 -1
- data/lib/fog/volume/openstack/models/backup.rb +2 -2
- data/lib/fog/volume/openstack/requests/restore_backup.rb +2 -2
- data/lib/fog/volume/openstack/requests/update_volume.rb +12 -1
- data/lib/fog/volume/openstack/v1.rb +4 -21
- data/lib/fog/volume/openstack/v1/models/volume.rb +1 -2
- data/lib/fog/volume/openstack/v1/requests/update_volume.rb +0 -17
- data/lib/fog/volume/openstack/v2.rb +4 -21
- data/lib/fog/volume/openstack/v2/models/volume.rb +1 -1
- data/lib/fog/volume/openstack/v2/requests/update_volume.rb +0 -18
- data/lib/fog/workflow/openstack/v2.rb +5 -22
- data/playbooks/fog-openstack-unittest-spec/run.yaml +2 -1
- data/playbooks/fog-openstack-unittest-test/run.yaml +2 -1
- data/unit/auth/catalog_test.rb +252 -0
- data/unit/auth/name_test.rb +115 -0
- data/unit/auth/token_test.rb +478 -0
- data/unit/auth_helper.rb +102 -0
- data/unit/test_helper.rb +6 -0
- metadata +41 -16
- data/lib/fog/compute/openstack/requests/list_tenants.rb +0 -43
@@ -12,7 +12,7 @@ module Fog
|
|
12
12
|
:openstack_project_name, :openstack_project_id,
|
13
13
|
:openstack_project_domain, :openstack_user_domain, :openstack_domain_name,
|
14
14
|
:openstack_project_domain_id, :openstack_user_domain_id, :openstack_domain_id,
|
15
|
-
:
|
15
|
+
:openstack_identity_api_version, :openstack_temp_url_key, :openstack_cache_ttl
|
16
16
|
|
17
17
|
model_path 'fog/monitoring/openstack/models'
|
18
18
|
model :metric
|
@@ -78,17 +78,8 @@ module Fog
|
|
78
78
|
Fog::Monitoring::OpenStack::NotFound
|
79
79
|
end
|
80
80
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
@openstack_service_type = options[:openstack_service_type] || ['monitoring']
|
85
|
-
@openstack_service_name = options[:openstack_service_name]
|
86
|
-
|
87
|
-
@connection_options = options[:connection_options] || {}
|
88
|
-
|
89
|
-
authenticate
|
90
|
-
@persistent = options[:persistent] || false
|
91
|
-
@connection = Fog::Core::Connection.new("#{@scheme}://#{@host}:#{@port}", @persistent, @connection_options)
|
81
|
+
def default_service_type
|
82
|
+
%w[monitoring]
|
92
83
|
end
|
93
84
|
end
|
94
85
|
end
|
@@ -3,8 +3,6 @@
|
|
3
3
|
module Fog
|
4
4
|
module Network
|
5
5
|
class OpenStack < Fog::Service
|
6
|
-
SUPPORTED_VERSIONS = /v2(\.0)*/
|
7
|
-
|
8
6
|
requires :openstack_auth_url
|
9
7
|
recognizes :openstack_auth_token, :openstack_management_url,
|
10
8
|
:persistent, :openstack_service_type, :openstack_service_name,
|
@@ -15,7 +13,7 @@ module Fog
|
|
15
13
|
:openstack_project_name, :openstack_project_id,
|
16
14
|
:openstack_project_domain, :openstack_user_domain, :openstack_domain_name,
|
17
15
|
:openstack_project_domain_id, :openstack_user_domain_id, :openstack_domain_id,
|
18
|
-
:
|
16
|
+
:openstack_identity_api_version
|
19
17
|
|
20
18
|
## MODELS
|
21
19
|
#
|
@@ -429,8 +427,6 @@ module Fog
|
|
429
427
|
def initialize(options = {})
|
430
428
|
@auth_token = Fog::Mock.random_base64(64)
|
431
429
|
@auth_token_expiration = (Time.now.utc + 86400).iso8601
|
432
|
-
|
433
|
-
initialize_identity options
|
434
430
|
end
|
435
431
|
|
436
432
|
def data
|
@@ -449,29 +445,12 @@ module Fog
|
|
449
445
|
Fog::Network::OpenStack::NotFound
|
450
446
|
end
|
451
447
|
|
452
|
-
def
|
453
|
-
|
454
|
-
|
455
|
-
@openstack_service_type = options[:openstack_service_type] || ['network']
|
456
|
-
@openstack_service_name = options[:openstack_service_name]
|
457
|
-
|
458
|
-
@connection_options = options[:connection_options] || {}
|
459
|
-
|
460
|
-
authenticate
|
461
|
-
set_api_path
|
462
|
-
|
463
|
-
@persistent = options[:persistent] || false
|
464
|
-
@connection = Fog::Core::Connection.new("#{@scheme}://#{@host}:#{@port}", @persistent, @connection_options)
|
448
|
+
def default_path_prefix
|
449
|
+
'v2.0'
|
465
450
|
end
|
466
451
|
|
467
|
-
def
|
468
|
-
|
469
|
-
unless @path.match(SUPPORTED_VERSIONS)
|
470
|
-
@path = Fog::OpenStack.get_supported_version_path(SUPPORTED_VERSIONS,
|
471
|
-
@openstack_management_uri,
|
472
|
-
@auth_token,
|
473
|
-
@connection_options)
|
474
|
-
end
|
452
|
+
def default_service_type
|
453
|
+
%w[network]
|
475
454
|
end
|
476
455
|
end
|
477
456
|
end
|
data/lib/fog/nfv/openstack.rb
CHANGED
@@ -82,8 +82,6 @@ module Fog
|
|
82
82
|
def initialize(options = {})
|
83
83
|
@auth_token = Fog::Mock.random_base64(64)
|
84
84
|
@auth_token_expiration = (Time.now.utc + 86_400).iso8601
|
85
|
-
|
86
|
-
initialize_identity options
|
87
85
|
end
|
88
86
|
|
89
87
|
def data
|
@@ -102,30 +100,12 @@ module Fog
|
|
102
100
|
Fog::NFV::OpenStack::NotFound
|
103
101
|
end
|
104
102
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
@openstack_service_type = options[:openstack_service_type] || ['servicevm']
|
109
|
-
@openstack_service_name = options[:openstack_service_name]
|
110
|
-
|
111
|
-
@connection_options = options[:connection_options] || {}
|
112
|
-
|
113
|
-
authenticate
|
114
|
-
set_api_path
|
115
|
-
|
116
|
-
@persistent = options[:persistent] || false
|
117
|
-
@connection = Fog::Core::Connection.new("#{@scheme}://#{@host}:#{@port}", @persistent, @connection_options)
|
103
|
+
def default_path_prefix
|
104
|
+
'v1.0'
|
118
105
|
end
|
119
106
|
|
120
|
-
def
|
121
|
-
|
122
|
-
@path = "/" + Fog::OpenStack.get_supported_version(
|
123
|
-
SUPPORTED_VERSIONS,
|
124
|
-
@openstack_management_uri,
|
125
|
-
@auth_token,
|
126
|
-
@connection_options
|
127
|
-
)
|
128
|
-
end
|
107
|
+
def default_service_type
|
108
|
+
%w[servicevm]
|
129
109
|
end
|
130
110
|
end
|
131
111
|
end
|
data/lib/fog/openstack.rb
CHANGED
@@ -84,6 +84,8 @@ module Fog
|
|
84
84
|
end
|
85
85
|
|
86
86
|
module OpenStack
|
87
|
+
require 'fog/openstack/auth/token'
|
88
|
+
|
87
89
|
autoload :VERSION, 'fog/openstack/version'
|
88
90
|
|
89
91
|
autoload :Core, 'fog/openstack/core'
|
@@ -123,425 +125,10 @@ module Fog
|
|
123
125
|
Fog::OpenStack.token_cache = {}
|
124
126
|
end
|
125
127
|
|
126
|
-
def self.authenticate(options, connection_options = {})
|
127
|
-
case options[:openstack_auth_uri].path
|
128
|
-
when /v1(\.\d+)?/
|
129
|
-
authenticate_v1(options, connection_options)
|
130
|
-
when /v2(\.\d+)?/
|
131
|
-
authenticate_v2(options, connection_options)
|
132
|
-
when /v3(\.\d+)?/
|
133
|
-
authenticate_v3(options, connection_options)
|
134
|
-
else
|
135
|
-
authenticate_v2(options, connection_options)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# legacy v1.0 style auth
|
140
|
-
def self.authenticate_v1(options, connection_options = {})
|
141
|
-
uri = options[:openstack_auth_uri]
|
142
|
-
connection = Fog::Core::Connection.new(uri.to_s, false, connection_options)
|
143
|
-
@openstack_api_key = options[:openstack_api_key]
|
144
|
-
@openstack_username = options[:openstack_username]
|
145
|
-
|
146
|
-
response = connection.request({
|
147
|
-
:expects => [200, 204],
|
148
|
-
:headers => {
|
149
|
-
'X-Auth-Key' => @openstack_api_key,
|
150
|
-
'X-Auth-User' => @openstack_username
|
151
|
-
},
|
152
|
-
:method => 'GET',
|
153
|
-
:path => (uri.path and not uri.path.empty?) ? uri.path : 'v1.0'
|
154
|
-
})
|
155
|
-
|
156
|
-
return {
|
157
|
-
:token => response.headers['X-Auth-Token'],
|
158
|
-
:server_management_url => response.headers['X-Server-Management-Url'] || response.headers['X-Storage-Url'],
|
159
|
-
:identity_public_endpoint => response.headers['X-Keystone']
|
160
|
-
}
|
161
|
-
end
|
162
|
-
|
163
|
-
# Keystone Style Auth
|
164
|
-
def self.authenticate_v2(options, connection_options = {})
|
165
|
-
uri = options[:openstack_auth_uri]
|
166
|
-
tenant_name = options[:openstack_tenant]
|
167
|
-
service_type = options[:openstack_service_type]
|
168
|
-
service_name = options[:openstack_service_name]
|
169
|
-
identity_service_type = options[:openstack_identity_service_type]
|
170
|
-
endpoint_type = (options[:openstack_endpoint_type] || 'publicURL').to_s
|
171
|
-
openstack_region = options[:openstack_region]
|
172
|
-
|
173
|
-
body = retrieve_tokens_v2(options, connection_options)
|
174
|
-
service = get_service(body, service_type, service_name)
|
175
|
-
|
176
|
-
options[:unscoped_token] = body['access']['token']['id']
|
177
|
-
|
178
|
-
unless service
|
179
|
-
unless tenant_name
|
180
|
-
response = Fog::Core::Connection.new(
|
181
|
-
"#{uri.scheme}://#{uri.host}:#{uri.port}/v2.0/tenants", false, connection_options).request({
|
182
|
-
:expects => [200, 204],
|
183
|
-
:headers => {'Content-Type' => 'application/json',
|
184
|
-
'Accept' => 'application/json',
|
185
|
-
'X-Auth-Token' => body['access']['token']['id']},
|
186
|
-
:method => 'GET'
|
187
|
-
})
|
188
|
-
|
189
|
-
body = Fog::JSON.decode(response.body)
|
190
|
-
if body['tenants'].empty?
|
191
|
-
raise Fog::Errors::NotFound.new('No Tenant Found')
|
192
|
-
else
|
193
|
-
options[:openstack_tenant] = body['tenants'].first['name']
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
body = retrieve_tokens_v2(options, connection_options)
|
198
|
-
service = get_service(body, service_type, service_name)
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
unless service
|
203
|
-
available = body['access']['serviceCatalog'].map { |endpoint|
|
204
|
-
endpoint['type']
|
205
|
-
}.sort.join ', '
|
206
|
-
|
207
|
-
missing = service_type.join ', '
|
208
|
-
|
209
|
-
message = "Could not find service #{missing}. Have #{available}"
|
210
|
-
|
211
|
-
raise Fog::Errors::NotFound, message
|
212
|
-
end
|
213
|
-
|
214
|
-
service['endpoints'] = service['endpoints'].select do |endpoint|
|
215
|
-
endpoint['region'] == openstack_region
|
216
|
-
end if openstack_region
|
217
|
-
|
218
|
-
if service['endpoints'].empty?
|
219
|
-
raise Fog::Errors::NotFound.new("No endpoints available for region '#{openstack_region}'")
|
220
|
-
end if openstack_region
|
221
|
-
|
222
|
-
regions = service["endpoints"].map{ |e| e['region'] }.uniq
|
223
|
-
if regions.count > 1
|
224
|
-
raise Fog::Errors::NotFound.new("Multiple regions available choose one of these '#{regions.join(',')}'")
|
225
|
-
end
|
226
|
-
|
227
|
-
identity_service = get_service(body, identity_service_type) if identity_service_type
|
228
|
-
tenant = body['access']['token']['tenant']
|
229
|
-
user = body['access']['user']
|
230
|
-
|
231
|
-
management_url = service['endpoints'].find{|s| s[endpoint_type]}[endpoint_type]
|
232
|
-
identity_url = identity_service['endpoints'].find{|s| s['publicURL']}['publicURL'] if identity_service
|
233
|
-
|
234
|
-
{
|
235
|
-
:user => user,
|
236
|
-
:tenant => tenant,
|
237
|
-
:identity_public_endpoint => identity_url,
|
238
|
-
:server_management_url => management_url,
|
239
|
-
:token => body['access']['token']['id'],
|
240
|
-
:expires => body['access']['token']['expires'],
|
241
|
-
:current_user_id => body['access']['user']['id'],
|
242
|
-
:unscoped_token => options[:unscoped_token]
|
243
|
-
}
|
244
|
-
end
|
245
|
-
|
246
|
-
# Keystone Style Auth
|
247
|
-
def self.authenticate_v3(options, connection_options = {})
|
248
|
-
uri = options[:openstack_auth_uri]
|
249
|
-
project_name = options[:openstack_project_name]
|
250
|
-
service_type = options[:openstack_service_type]
|
251
|
-
service_name = options[:openstack_service_name]
|
252
|
-
identity_service_type = options[:openstack_identity_service_type]
|
253
|
-
endpoint_type = map_endpoint_type(options[:openstack_endpoint_type] || 'publicURL')
|
254
|
-
openstack_region = options[:openstack_region]
|
255
|
-
|
256
|
-
token, body = retrieve_tokens_v3 options, connection_options
|
257
|
-
|
258
|
-
service = get_service_v3(body, service_type, service_name, openstack_region, options)
|
259
|
-
|
260
|
-
options[:unscoped_token] = token
|
261
|
-
|
262
|
-
unless service
|
263
|
-
unless project_name
|
264
|
-
request_body = {
|
265
|
-
:expects => [200],
|
266
|
-
:headers => {'Content-Type' => 'application/json',
|
267
|
-
'Accept' => 'application/json',
|
268
|
-
'X-Auth-Token' => token},
|
269
|
-
:method => 'GET'
|
270
|
-
}
|
271
|
-
user_id = body['token']['user']['id']
|
272
|
-
project_uri = uri.clone
|
273
|
-
project_uri.path = uri.path.sub('/auth/tokens', "/users/#{user_id}/projects")
|
274
|
-
project_uri_param = "#{project_uri.scheme}://#{project_uri.host}:#{project_uri.port}#{project_uri.path}"
|
275
|
-
response = Fog::Core::Connection.new(project_uri_param, false, connection_options).request(request_body)
|
276
|
-
|
277
|
-
projects_body = Fog::JSON.decode(response.body)
|
278
|
-
if projects_body['projects'].empty?
|
279
|
-
options[:openstack_domain_id] = body['token']['user']['domain']['id']
|
280
|
-
else
|
281
|
-
options[:openstack_project_id] = projects_body['projects'].first['id']
|
282
|
-
options[:openstack_project_name] = projects_body['projects'].first['name']
|
283
|
-
options[:openstack_domain_id] = projects_body['projects'].first['domain_id']
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
token, body = retrieve_tokens_v3(options, connection_options)
|
288
|
-
service = get_service_v3(body, service_type, service_name, openstack_region, options)
|
289
|
-
end
|
290
|
-
|
291
|
-
# If no identity endpoint is found, try the auth uri (slicing /auth/tokens)
|
292
|
-
# It covers the case where identityv3 endpoint is not present in the catalog but we have to use it
|
293
|
-
unless service
|
294
|
-
if service_type.include? "identity"
|
295
|
-
identity_uri = uri.to_s.sub('/auth/tokens', '')
|
296
|
-
response = Fog::Core::Connection.new(identity_uri, false, connection_options).request({:method => 'GET'})
|
297
|
-
if response.status == 200
|
298
|
-
service = {
|
299
|
-
"endpoints" => [{
|
300
|
-
"url" => identity_uri,
|
301
|
-
"region" => openstack_region,
|
302
|
-
"interface" => endpoint_type
|
303
|
-
}],
|
304
|
-
"type" => service_type,
|
305
|
-
"name" => service_name
|
306
|
-
}
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
unless service
|
312
|
-
available_services = body['token']['catalog'].map { |service|
|
313
|
-
service['type']
|
314
|
-
}.sort.join ', '
|
315
|
-
|
316
|
-
available_regions = body['token']['catalog'].map { |service|
|
317
|
-
service['endpoints'].map { |endpoint|
|
318
|
-
endpoint['region']
|
319
|
-
}.uniq
|
320
|
-
}.uniq.sort.join ', '
|
321
|
-
|
322
|
-
missing = service_type.join ', '
|
323
|
-
|
324
|
-
message = "Could not find service #{missing}#{(' in region '+openstack_region) if openstack_region}."+
|
325
|
-
" Have #{available_services}#{(' in regions '+available_regions) if openstack_region}"
|
326
|
-
|
327
|
-
raise Fog::Errors::NotFound, message
|
328
|
-
end
|
329
|
-
|
330
|
-
service['endpoints'] = service['endpoints'].select do |endpoint|
|
331
|
-
endpoint['region'] == openstack_region && endpoint['interface'] == endpoint_type
|
332
|
-
end if openstack_region
|
333
|
-
|
334
|
-
if service['endpoints'].empty?
|
335
|
-
raise Fog::Errors::NotFound.new("No endpoints available for region '#{openstack_region}'")
|
336
|
-
end if openstack_region
|
337
|
-
|
338
|
-
regions = service["endpoints"].map { |e| e['region'] }.uniq
|
339
|
-
if regions.count > 1
|
340
|
-
raise Fog::Errors::NotFound.new("Multiple regions available choose one of these '#{regions.join(',')}'")
|
341
|
-
end
|
342
|
-
|
343
|
-
identity_service = get_service_v3(body, identity_service_type, nil, nil, :openstack_endpoint_path_matches => /\/v3/) if identity_service_type
|
344
|
-
|
345
|
-
management_url = service['endpoints'].find { |e| e['interface']==endpoint_type }['url']
|
346
|
-
identity_url = identity_service['endpoints'].find { |e| e['interface']=='public' }['url'] if identity_service
|
347
|
-
|
348
|
-
if body['token']['project']
|
349
|
-
tenant = body['token']['project']
|
350
|
-
elsif body['token']['user']['project']
|
351
|
-
tenant = body['token']['user']['project']
|
352
|
-
end
|
353
|
-
|
354
|
-
return {
|
355
|
-
:user => body['token']['user']['name'],
|
356
|
-
:tenant => tenant,
|
357
|
-
:identity_public_endpoint => identity_url,
|
358
|
-
:server_management_url => management_url,
|
359
|
-
:token => token,
|
360
|
-
:expires => body['token']['expires_at'],
|
361
|
-
:current_user_id => body['token']['user']['id'],
|
362
|
-
:unscoped_token => options[:unscoped_token]
|
363
|
-
}
|
364
|
-
end
|
365
|
-
|
366
|
-
def self.get_service(body, service_type=[], service_name=nil)
|
367
|
-
if not body['access'].nil?
|
368
|
-
body['access']['serviceCatalog'].find do |s|
|
369
|
-
if service_name.nil? or service_name.empty?
|
370
|
-
service_type.include?(s['type'])
|
371
|
-
else
|
372
|
-
service_type.include?(s['type']) and s['name'] == service_name
|
373
|
-
end
|
374
|
-
end
|
375
|
-
elsif not body['token']['catalog'].nil?
|
376
|
-
body['token']['catalog'].find do |s|
|
377
|
-
if service_name.nil? or service_name.empty?
|
378
|
-
service_type.include?(s['type'])
|
379
|
-
else
|
380
|
-
service_type.include?(s['type']) and s['name'] == service_name
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
def self.retrieve_tokens_v2(options, connection_options = {})
|
388
|
-
api_key = options[:openstack_api_key].to_s
|
389
|
-
username = options[:openstack_username].to_s
|
390
|
-
tenant_name = options[:openstack_tenant].to_s
|
391
|
-
auth_token = options[:openstack_auth_token] || options[:unscoped_token]
|
392
|
-
uri = options[:openstack_auth_uri]
|
393
|
-
omit_default_port = options[:openstack_auth_omit_default_port]
|
394
|
-
|
395
|
-
identity_v2_connection = Fog::Core::Connection.new(uri.to_s, false, connection_options)
|
396
|
-
request_body = {:auth => Hash.new}
|
397
|
-
|
398
|
-
if auth_token
|
399
|
-
request_body[:auth][:token] = {
|
400
|
-
:id => auth_token
|
401
|
-
}
|
402
|
-
else
|
403
|
-
request_body[:auth][:passwordCredentials] = {
|
404
|
-
:username => username,
|
405
|
-
:password => api_key
|
406
|
-
}
|
407
|
-
end
|
408
|
-
request_body[:auth][:tenantName] = tenant_name if tenant_name
|
409
|
-
|
410
|
-
request = {
|
411
|
-
:expects => [200, 204],
|
412
|
-
:headers => {'Content-Type' => 'application/json'},
|
413
|
-
:body => Fog::JSON.encode(request_body),
|
414
|
-
:method => 'POST',
|
415
|
-
:path => (uri.path and not uri.path.empty?) ? uri.path : 'v2.0'
|
416
|
-
}
|
417
|
-
request[:omit_default_port] = omit_default_port unless omit_default_port.nil?
|
418
|
-
|
419
|
-
response = identity_v2_connection.request(request)
|
420
|
-
|
421
|
-
Fog::JSON.decode(response.body)
|
422
|
-
end
|
423
|
-
|
424
|
-
def self.retrieve_tokens_v3(options, connection_options = {})
|
425
|
-
|
426
|
-
api_key = options[:openstack_api_key].to_s
|
427
|
-
username = options[:openstack_username].to_s
|
428
|
-
userid = options[:openstack_userid]
|
429
|
-
domain_id = options[:openstack_domain_id]
|
430
|
-
domain_name = options[:openstack_domain_name]
|
431
|
-
project_domain = options[:openstack_project_domain]
|
432
|
-
project_domain_id = options[:openstack_project_domain_id]
|
433
|
-
user_domain = options[:openstack_user_domain]
|
434
|
-
user_domain_id = options[:openstack_user_domain_id]
|
435
|
-
project_name = options[:openstack_project_name]
|
436
|
-
project_id = options[:openstack_project_id]
|
437
|
-
auth_token = options[:openstack_auth_token] || options[:unscoped_token]
|
438
|
-
uri = options[:openstack_auth_uri]
|
439
|
-
omit_default_port = options[:openstack_auth_omit_default_port]
|
440
|
-
cache_ttl = options[:openstack_cache_ttl] || 0
|
441
|
-
|
442
|
-
connection = Fog::Core::Connection.new(uri.to_s, false, connection_options)
|
443
|
-
request_body = {:auth => {}}
|
444
|
-
|
445
|
-
scope = {}
|
446
|
-
|
447
|
-
if project_name || project_id
|
448
|
-
scope[:project] = if project_id.nil? then
|
449
|
-
if project_domain || project_domain_id
|
450
|
-
{:name => project_name, :domain => project_domain_id.nil? ? {:name => project_domain} : {:id => project_domain_id}}
|
451
|
-
else
|
452
|
-
{:name => project_name, :domain => domain_id.nil? ? {:name => domain_name} : {:id => domain_id}}
|
453
|
-
end
|
454
|
-
else
|
455
|
-
{:id => project_id}
|
456
|
-
end
|
457
|
-
elsif domain_name || domain_id
|
458
|
-
scope[:domain] = domain_id.nil? ? {:name => domain_name} : {:id => domain_id}
|
459
|
-
else
|
460
|
-
# unscoped token
|
461
|
-
end
|
462
|
-
|
463
|
-
if auth_token
|
464
|
-
request_body[:auth][:identity] = {
|
465
|
-
:methods => %w{token},
|
466
|
-
:token => {
|
467
|
-
:id => auth_token
|
468
|
-
}
|
469
|
-
}
|
470
|
-
else
|
471
|
-
request_body[:auth][:identity] = {
|
472
|
-
:methods => %w{password},
|
473
|
-
:password => {
|
474
|
-
:user => {
|
475
|
-
:password => api_key
|
476
|
-
}
|
477
|
-
}
|
478
|
-
}
|
479
|
-
|
480
|
-
if userid
|
481
|
-
request_body[:auth][:identity][:password][:user][:id] = userid
|
482
|
-
else
|
483
|
-
if user_domain || user_domain_id
|
484
|
-
request_body[:auth][:identity][:password][:user].merge! :domain => user_domain_id.nil? ? {:name => user_domain} : {:id => user_domain_id}
|
485
|
-
elsif domain_name || domain_id
|
486
|
-
request_body[:auth][:identity][:password][:user].merge! :domain => domain_id.nil? ? {:name => domain_name} : {:id => domain_id}
|
487
|
-
end
|
488
|
-
request_body[:auth][:identity][:password][:user][:name] = username
|
489
|
-
end
|
490
|
-
|
491
|
-
end
|
492
|
-
request_body[:auth][:scope] = scope unless scope.empty?
|
493
|
-
|
494
|
-
path = (uri.path and not uri.path.empty?) ? uri.path : 'v3'
|
495
|
-
|
496
|
-
response, expires = Fog::OpenStack.token_cache[{:body => request_body, :path => path}] if cache_ttl > 0
|
497
|
-
|
498
|
-
unless response && expires > Time.now
|
499
|
-
request = {
|
500
|
-
:expects => [201],
|
501
|
-
:headers => {'Content-Type' => 'application/json'},
|
502
|
-
:body => Fog::JSON.encode(request_body),
|
503
|
-
:method => 'POST',
|
504
|
-
:path => path
|
505
|
-
}
|
506
|
-
request[:omit_default_port] = omit_default_port unless omit_default_port.nil?
|
507
|
-
|
508
|
-
response = connection.request(request)
|
509
|
-
if cache_ttl > 0
|
510
|
-
cache = Fog::OpenStack.token_cache
|
511
|
-
cache[{:body => request_body, :path => path}] = response, Time.now + cache_ttl
|
512
|
-
Fog::OpenStack.token_cache = cache
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
[response.headers["X-Subject-Token"], Fog::JSON.decode(response.body)]
|
517
|
-
end
|
518
|
-
|
519
|
-
def self.get_service_v3(hash, service_type=[], service_name=nil, region=nil, options={})
|
520
|
-
|
521
|
-
# Find all services matching any of the types in service_type, filtered by service_name if it's non-nil
|
522
|
-
services = hash['token']['catalog'].find_all do |s|
|
523
|
-
if service_name.nil? or service_name.empty?
|
524
|
-
service_type.include?(s['type'])
|
525
|
-
else
|
526
|
-
service_type.include?(s['type']) and s['name'] == service_name
|
527
|
-
end
|
528
|
-
end if hash['token']['catalog']
|
529
|
-
|
530
|
-
# Filter the found services by region (if specified) and whether the endpoint path matches the given regex (e.g. /\/v3/)
|
531
|
-
services.find do |s|
|
532
|
-
s['endpoints'].any? { |ep| endpoint_region?(ep, region) && endpoint_path_match?(ep, options[:openstack_endpoint_path_matches])}
|
533
|
-
end if services
|
534
|
-
|
535
|
-
end
|
536
|
-
|
537
128
|
def self.endpoint_region?(endpoint, region)
|
538
129
|
region.nil? || endpoint['region'] == region
|
539
130
|
end
|
540
131
|
|
541
|
-
def self.endpoint_path_match?(endpoint, match_regex)
|
542
|
-
match_regex.nil? || URI(endpoint['url']).path =~ match_regex
|
543
|
-
end
|
544
|
-
|
545
132
|
def self.get_supported_version(supported_versions, uri, auth_token, connection_options = {})
|
546
133
|
supported_version = get_version(supported_versions, uri, auth_token, connection_options)
|
547
134
|
version = supported_version['id'] if supported_version
|
@@ -571,22 +158,14 @@ module Fog
|
|
571
158
|
end
|
572
159
|
end
|
573
160
|
|
574
|
-
def self.map_endpoint_type type
|
575
|
-
case type
|
576
|
-
when "publicURL"
|
577
|
-
"public"
|
578
|
-
when "internalURL"
|
579
|
-
"internal"
|
580
|
-
when "adminURL"
|
581
|
-
"admin"
|
582
|
-
end
|
583
|
-
|
584
|
-
end
|
585
|
-
|
586
161
|
def self.get_version(supported_versions, uri, auth_token, connection_options = {})
|
587
162
|
version_cache = "#{uri}#{supported_versions}"
|
588
163
|
return @version[version_cache] if @version && @version[version_cache]
|
589
|
-
|
164
|
+
|
165
|
+
# To allow version discovery we need a "version less" endpoint
|
166
|
+
path = uri.path.gsub(/\/v([1-9]+\d*)(\.[1-9]+\d*)*.*$/, '/')
|
167
|
+
url = "#{uri.scheme}://#{uri.host}:#{uri.port}#{path}"
|
168
|
+
connection = Fog::Core::Connection.new(url, false, connection_options)
|
590
169
|
response = connection.request(
|
591
170
|
:expects => [200, 204, 300],
|
592
171
|
:headers => {'Content-Type' => 'application/json',
|
@@ -602,10 +181,17 @@ module Fog
|
|
602
181
|
end
|
603
182
|
|
604
183
|
def self.extract_version_from_body(body, supported_versions)
|
605
|
-
|
606
|
-
|
184
|
+
versions = []
|
185
|
+
unless body['versions'].nil? || body['versions'].empty?
|
186
|
+
versions = body['versions'].kind_of?(Array) ? body['versions'] : body['versions']['values']
|
187
|
+
end
|
188
|
+
# Some version API would return single endpoint rather than endpoints list, try to get it via 'version'.
|
189
|
+
unless body['version'].nil? or versions.length != 0
|
190
|
+
versions = [body['version']]
|
191
|
+
end
|
607
192
|
version = nil
|
608
|
-
|
193
|
+
|
194
|
+
# order is important, preferred status should be first
|
609
195
|
%w(CURRENT stable SUPPORTED DEPRECATED).each do |status|
|
610
196
|
version = versions.find { |x| x['id'].match(supported_versions) && (x['status'] == status) }
|
611
197
|
break if version
|