1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/openstack/image.rb
Dan Prince ba26129001 OpenStack auth updates to select by service name.
This patch updates the OpenStack auth implementation so that
it supports selecting API service by both 'name' and 'type'.

Previously the implementation was confusing because it
used a config param called :openstack_service_name to
select the service 'type' from the catalog. This patch
swaps it so that :openstack_service_name actually selects
by 'name'.

The previous logic to select service by type ('compute' for example)
has been preserved in a new :openstack_service_type parameter.
This option is used just as it was before for backwards compatability.

This change is potentially breaking for anyone previously using
:openstack_service_name (which I don't think is that common but is
possible). As such we should probably make a release note saying
that previous users of :openstack_service_name should migrate to
use :openstack_service_type instead.
2012-12-10 07:55:54 -05:00

213 lines
7.2 KiB
Ruby

require 'fog/openstack'
module Fog
module Image
class OpenStack < Fog::Service
requires :openstack_auth_url
recognizes :openstack_auth_token, :openstack_management_url, :persistent,
:openstack_service_type, :openstack_service_name, :openstack_tenant,
:openstack_api_key, :openstack_username,
:current_user, :current_tenant
model_path 'fog/openstack/models/image'
model :image
collection :images
request_path 'fog/openstack/requests/image'
request :list_public_images
request :list_public_images_detailed
request :get_image
request :create_image
request :update_image
request :get_image_members
request :update_image_members
request :get_shared_images
request :add_member_to_image
request :remove_member_from_image
request :delete_image
request :get_image_by_id
request :set_tenant
class Mock
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = {
:images => {}
}
end
end
def self.reset
@data = nil
end
def initialize(options={})
require 'multi_json'
@openstack_username = options[:openstack_username]
@openstack_tenant = options[:openstack_tenant]
@openstack_auth_uri = URI.parse(options[:openstack_auth_url])
@auth_token = Fog::Mock.random_base64(64)
@auth_token_expiration = (Time.now.utc + 86400).iso8601
management_url = URI.parse(options[:openstack_auth_url])
management_url.port = 9292
management_url.path = '/v1'
@openstack_management_url = management_url.to_s
@data ||= { :users => {} }
unless @data[:users].find {|u| u['name'] == options[:openstack_username]}
id = Fog::Mock.random_numbers(6).to_s
@data[:users][id] = {
'id' => id,
'name' => options[:openstack_username],
'email' => "#{options[:openstack_username]}@mock.com",
'tenantId' => Fog::Mock.random_numbers(6).to_s,
'enabled' => true
}
end
end
def data
self.class.data[@openstack_username]
end
def reset_data
self.class.data.delete(@openstack_username)
end
def credentials
{ :provider => 'openstack',
:openstack_auth_url => @openstack_auth_uri.to_s,
:openstack_auth_token => @auth_token,
:openstack_management_url => @openstack_management_url }
end
end
class Real
attr_reader :current_user
attr_reader :current_tenant
def initialize(options={})
require 'multi_json'
@openstack_auth_token = options[:openstack_auth_token]
unless @openstack_auth_token
missing_credentials = Array.new
@openstack_api_key = options[:openstack_api_key]
@openstack_username = options[:openstack_username]
missing_credentials << :openstack_api_key unless @openstack_api_key
missing_credentials << :openstack_username unless @openstack_username
raise ArgumentError, "Missing required arguments: #{missing_credentials.join(', ')}" unless missing_credentials.empty?
end
@openstack_tenant = options[:openstack_tenant]
@openstack_auth_uri = URI.parse(options[:openstack_auth_url])
@openstack_management_url = options[:openstack_management_url]
@openstack_must_reauthenticate = false
@openstack_service_type = options[:openstack_service_type] || ['image']
@openstack_service_name = options[:openstack_service_name]
@connection_options = options[:connection_options] || {}
@current_user = options[:current_user]
@current_tenant = options[:current_tenant]
authenticate
@persistent = options[:persistent] || false
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", @persistent, @connection_options)
end
def credentials
{ :provider => 'openstack',
:openstack_auth_url => @openstack_auth_uri.to_s,
:openstack_auth_token => @auth_token,
:openstack_management_url => @openstack_management_url,
:current_user => @current_user,
:current_tenant => @current_tenant }
end
def reload
@connection.reset
end
def request(params)
begin
response = @connection.request(params.merge({
:headers => {
'Content-Type' => 'application/json',
'X-Auth-Token' => @auth_token
}.merge!(params[:headers] || {}),
:host => @host,
:path => "#{@path}/#{params[:path]}"#,
# Causes errors for some requests like tenants?limit=1
# :query => ('ignore_awful_caching' << Time.now.to_i.to_s)
}))
rescue Excon::Errors::Unauthorized => error
if error.response.body != 'Bad username or password' # token expiration
@openstack_must_reauthenticate = true
authenticate
retry
else # bad credentials
raise error
end
rescue Excon::Errors::HTTPStatusError => error
raise case error
when Excon::Errors::NotFound
Fog::Compute::OpenStack::NotFound.slurp(error)
else
error
end
end
unless response.body.empty?
response.body = MultiJson.decode(response.body)
end
response
end
private
def authenticate
if !@openstack_management_url || @openstack_must_reauthenticate
options = {
:openstack_tenant => @openstack_tenant,
:openstack_api_key => @openstack_api_key,
:openstack_username => @openstack_username,
:openstack_auth_uri => @openstack_auth_uri,
:openstack_auth_token => @openstack_auth_token,
:openstack_service_type => @openstack_service_type,
:openstack_service_name => @openstack_service_name,
:openstack_endpoint_type => 'adminURL'
}
credentials = Fog::OpenStack.authenticate_v2(options, @connection_options)
@current_user = credentials[:user]
@current_tenant = credentials[:tenant]
@openstack_must_reauthenticate = false
@auth_token = credentials[:token]
@openstack_management_url = credentials[:server_management_url]
uri = URI.parse(@openstack_management_url)
else
@auth_token = @openstack_auth_token
uri = URI.parse(@openstack_management_url)
end
@host = uri.host
@path = uri.path
@path.sub!(/\/$/, '')
@port = uri.port
@scheme = uri.scheme
true
end
end
end
end
end