def self.authenticate_v3(options, connection_options = {})
uri = options[:openstack_auth_uri]
project_name = options[:openstack_project_name]
service_type = options[:openstack_service_type]
service_name = options[:openstack_service_name]
identity_service_type = options[:openstack_identity_service_type]
endpoint_type = map_endpoint_type(options[:openstack_endpoint_type] || 'publicURL')
openstack_region = options[:openstack_region]
token, body = retrieve_tokens_v3 options, connection_options
service = get_service_v3(body, service_type, service_name, openstack_region, options)
options[:unscoped_token] = token
unless service
unless project_name
request_body = {
:expects => [200],
:headers => {'Content-Type' => 'application/json',
'Accept' => 'application/json',
'X-Auth-Token' => token},
:method => 'GET'
}
user_id = body['token']['user']['id']
project_uri = uri.clone
project_uri.path = uri.path.sub('/auth/tokens', "/users/#{user_id}/projects")
project_uri_param = "#{project_uri.scheme}://#{project_uri.host}:#{project_uri.port}#{project_uri.path}"
response = Fog::Core::Connection.new(project_uri_param, false, connection_options).request(request_body)
projects_body = Fog::JSON.decode(response.body)
if projects_body['projects'].empty?
options[:openstack_domain_id] = body['token']['user']['domain']['id']
else
options[:openstack_project_id] = projects_body['projects'].first['id']
options[:openstack_project_name] = projects_body['projects'].first['name']
options[:openstack_domain_id] = projects_body['projects'].first['domain_id']
end
end
token, body = retrieve_tokens_v3(options, connection_options)
service = get_service_v3(body, service_type, service_name, openstack_region, options)
end
unless service
if service_type.include? "identity"
identity_uri = uri.to_s.sub('/auth/tokens', '')
response = Fog::Core::Connection.new(identity_uri, false, connection_options).request({:method => 'GET'})
if response.status == 200
service = {
"endpoints" => [{
"url" => identity_uri,
"region" => openstack_region,
"interface" => endpoint_type
}],
"type" => service_type,
"name" => service_name
}
end
end
end
unless service
available_services = body['token']['catalog'].map { |service|
service['type']
}.sort.join ', '
available_regions = body['token']['catalog'].map { |service|
service['endpoints'].map { |endpoint|
endpoint['region']
}.uniq
}.uniq.sort.join ', '
missing = service_type.join ', '
message = "Could not find service #{missing}#{(' in region '+openstack_region) if openstack_region}."+
" Have #{available_services}#{(' in regions '+available_regions) if openstack_region}"
raise Fog::Errors::NotFound, message
end
service['endpoints'] = service['endpoints'].select do |endpoint|
endpoint['region'] == openstack_region && endpoint['interface'] == endpoint_type
end if openstack_region
if service['endpoints'].empty?
raise Fog::Errors::NotFound.new("No endpoints available for region '#{openstack_region}'")
end if openstack_region
regions = service["endpoints"].map { |e| e['region'] }.uniq
if regions.count > 1
raise Fog::Errors::NotFound.new("Multiple regions available choose one of these '#{regions.join(',')}'")
end
identity_service = get_service_v3(body, identity_service_type, nil, nil, :openstack_endpoint_path_matches => /\/v3/) if identity_service_type
management_url = service['endpoints'].find { |e| e['interface']==endpoint_type }['url']
identity_url = identity_service['endpoints'].find { |e| e['interface']=='public' }['url'] if identity_service
if body['token']['project']
tenant = body['token']['project']
elsif body['token']['user']['project']
tenant = body['token']['user']['project']
end
return {
:user => body['token']['user']['name'],
:tenant => tenant,
:identity_public_endpoint => identity_url,
:server_management_url => management_url,
:token => token,
:expires => body['token']['expires_at'],
:current_user_id => body['token']['user']['id'],
:unscoped_token => options[:unscoped_token]
}
end