diff --git a/lib/fog/bin/rackspace.rb b/lib/fog/bin/rackspace.rb index 11c83f1dd..4e6ae9ee5 100644 --- a/lib/fog/bin/rackspace.rb +++ b/lib/fog/bin/rackspace.rb @@ -7,6 +7,8 @@ class Rackspace < Fog::Bin Fog::CDN::Rackspace when :compute Fog::Compute::Rackspace + when :compute_v2 + Fog::Compute::RackspaceV2 when :storage Fog::Storage::Rackspace when :load_balancers @@ -31,6 +33,9 @@ class Rackspace < Fog::Bin when :compute Fog::Logger.warning("Rackspace[:compute] is not recommended, use Compute[:rackspace] for portability") Fog::Compute.new(:provider => 'Rackspace') + when :compute_v2 + Fog::Logger.warning("Rackspace[:compute] is not recommended, use Compute[:rackspace] for portability") + Fog::Compute.new(:provider => 'Rackspace', :version => 'v2') when :dns Fog::DNS.new(:provider => 'Rackspace') when :load_balancers diff --git a/lib/fog/compute.rb b/lib/fog/compute.rb index a48b9b7b3..9a1df512f 100644 --- a/lib/fog/compute.rb +++ b/lib/fog/compute.rb @@ -7,7 +7,10 @@ module Fog def self.new(attributes) attributes = attributes.dup # prevent delete from having side effects - case provider = attributes.delete(:provider).to_s.downcase.to_sym + provider = attributes.delete(:provider).to_s.downcase.to_sym + version = attributes.delete(:version).to_s.downcase.to_sym + + case provider when :aws require 'fog/aws/compute' Fog::Compute::AWS.new(attributes) @@ -64,8 +67,13 @@ module Fog require 'fog/ovirt/compute' Fog::Compute::Ovirt.new(attributes) when :rackspace - require 'fog/rackspace/compute' - Fog::Compute::Rackspace.new(attributes) + if version == :v2 + require 'fog/rackspace/compute_v2' + Fog::Compute::RackspaceV2.new(attributes) + else + require 'fog/rackspace/compute' + Fog::Compute::Rackspace.new(attributes) + end when :stormondemand require 'fog/storm_on_demand/compute' Fog::Compute::StormOnDemand.new(attributes) diff --git a/lib/fog/rackspace.rb b/lib/fog/rackspace.rb index 7d437d909..7a2ebce98 100644 --- a/lib/fog/rackspace.rb +++ b/lib/fog/rackspace.rb @@ -44,6 +44,7 @@ module Fog service(:cdn, 'rackspace/cdn', 'CDN') service(:compute, 'rackspace/compute', 'Compute') + service(:compute_v2, 'rackspace/compute_v2', 'Compute v2') service(:dns, 'rackspace/dns', 'DNS') service(:storage, 'rackspace/storage', 'Storage') service(:load_balancers, 'rackspace/load_balancers', 'LoadBalancers') diff --git a/lib/fog/rackspace/compute_v2.rb b/lib/fog/rackspace/compute_v2.rb new file mode 100644 index 000000000..62f6fe1fa --- /dev/null +++ b/lib/fog/rackspace/compute_v2.rb @@ -0,0 +1,93 @@ +require 'fog/compute' + +module Fog + module Compute + class RackspaceV2 < Fog::Service + + class ServiceError < Fog::Rackspace::Errors::ServiceError; end + class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end + class BadRequest < Fog::Rackspace::Errors::BadRequest; end + + DFW_ENDPOINT = 'https://dfw.servers.api.rackspacecloud.com/v2/' + ORD_ENDPOINT = 'https://ord.servers.api.rackspacecloud.com/v2/' + LON_ENDPOINT = 'https://lon.servers.api.rackspacecloud.com/v2/' + + requires :rackspace_username, :rackspace_api_key + recognizes :rackspace_endpoint + recognizes :rackspace_auth_url + recognizes :rackspace_auth_token + + model_path 'fog/rackspace/models/compute_v2' + + request_path 'fog/rackspace/requests/compute_v2' + + class Mock + def request(params) + Fog::Mock.not_implemented + end + end + + class Real + def initialize(options = {}) + @rackspace_api_key = options[:rackspace_api_key] + @rackspace_username = options[:rackspace_username] + @rackspace_auth_url = options[:rackspace_auth_url] + @rackspace_must_reauthenticate = false + @connection_options = options[:connection_options] || {} + + endpoint = options[:rackspace_endpoint] || DFW_ENDPOINT + uri = URI.parse(endpoint) + + @host = uri.host + @persistent = options[:persistent] || false + @path = uri.path + @port = uri.port + @scheme = uri.scheme + + authenticate + + @connection = Fog::Connection.new(uri.to_s, @persistent, @connection_options) + 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]}" + })) + rescue Excon::Errors::NotFound => error + raise NotFound.slurp error + rescue Excon::Errors::BadRequest => error + raise BadRequest.slurp error + rescue Excon::Errors::InternalServerError => error + raise InternalServerError.slurp error + rescue Excon::Errors::HTTPStatusError => error + raise ServiceError.slurp error + end + unless response.body.empty? + response.body = Fog::JSON.decode(response.body) + end + response + end + + private + + def authenticate + options = { + :rackspace_api_key => @rackspace_api_key, + :rackspace_username => @rackspace_username, + :rackspace_auth_url => @rackspace_auth_url + } + credentials = Fog::Rackspace.authenticate(options, @connection_options) + @auth_token = credentials['X-Auth-Token'] + account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1] + @path = "#{@path}/#{account_id}" + end + end + end + end +end