Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Rackspace: API 07/08/09 support

  • Loading branch information...
commit ef396bf8d2ecca779aae4629dc50d2caed048c8c 1 parent 21604ba
@konstantin-dzreev konstantin-dzreev authored
View
90 lib/rackspace.rb
@@ -83,7 +83,7 @@ module Rackspace
# begin
# new_list = rackspace.list_servers(:detail => true)
# rescue Rightscale::Rackspace::NoChange
- # puts "Ohoho! We hit internal cache!"
+ # puts e.message #=> "Cached: '/servers/detail' has not changed since Thu, 09 Jul 2009 10:53:35 GMT."
# # extract the list of servers from internal cache
# new_list = rackspace.cache['/servers/detail'][:data]
# # the lists must be equal
@@ -110,14 +110,25 @@ module Rackspace
# last_request_time = Time.now - 3600
# begin
# rackspace.list_servers(:detail => true, :headers => { 'if-modified-since' => last_request_time })
- # rescue Rightscale::Rackspace::NoChange
- # puts "Nothing has changed since #{last_request_was_at}"
+ # rescue Rightscale::Rackspace::NoChange => e
+ # # e.message can return one of the messages below:
+ # # - "Cached: '/servers/detail' has not changed since Thu, 09 Jul 2009 10:55:41 GMT."
+ # # - "NotModified: '/servers/detail' has not changed since Thu, 09 Jul 2009 10:55:41 GMT."
+ # # The first comes when we have cached response from Rackspace and it can be retreived as
+ # # rackspace.cache['/servers/detail'][:data]. The second one appears when the local
+ # # cache has no stored records for the request.
+ # puts e.message
# end
#
# # 'changes-since' URL variable usage:
- # new_servers = rackspace.list_servers(:detail => true, :vars => { 'changes-since' => last_request_time })
- # # show the changes at servers since last_request_time
- # puts new_servers.inspect
+ # begin
+ # new_servers = rackspace.list_servers(:detail => true, :vars => { 'changes-since' => last_request_time })
+ # # show the changes at servers since last_request_time
+ # puts new_servers.inspect
+ # rescue Rightscale::Rackspace::NoChange => e
+ # puts e.message #=>
+ # "NotModified: '/flavors?changes-since=1247137435&limit=1000&offset=0' has not changed since the requested time."
+ # end
#
# === Callbacks:
#
@@ -190,7 +201,7 @@ def list_limits(opts={})
# Images
#--------------------------------
- # List images.
+ # List images. Options: :detail => false|true.
#
# # Get images list.
# rackspace.list_images #=>
@@ -303,15 +314,16 @@ def get_image(image_id, opts={})
#
#
def create_image(server_id, name, opts={})
- body = { 'image' => { 'name' => name } }
- api(:post, "/servers/#{server_id}/actions/create_image", opts.merge(:body => body.to_json))
+ body = { 'image' => { 'name' => name,
+ 'serverId' => server_id } }
+ api(:post, "/images", opts.merge(:body => body.to_json))
end
#--------------------------------
# Flavors
#--------------------------------
- # List flavors.
+ # List flavors. Options: :detail => false|true.
#
# # Get list of flavors.
# rackspace.list_flavors #=>
@@ -336,9 +348,7 @@ def create_image(server_id, name, opts={})
# RightRackspace caching: yes, keys: '/flavors', '/flavors/detail'
#
def list_flavors(opts={})
- # TODO: use incrementally one when Rackspace report they support pagination for list flavors
-# api_or_cache(:get, detailed_path("/flavors", opts), opts.merge(:incrementally => true))
- api_or_cache(:get, detailed_path("/flavors", opts), opts)
+ api_or_cache(:get, detailed_path("/flavors", opts), opts.merge(:incrementally => true))
end
# Incrementally list flavors.
@@ -365,7 +375,7 @@ def get_flavor(flavor_id, opts={})
# Servers
#--------------------------------
- # List servers.
+ # List servers. Options: :detail => false|true.
#
# rackspace.list_servers #=>
# {"servers"=>[{"name"=>"my-super-awesome-server-", "id"=>62844}]}
@@ -382,7 +392,7 @@ def get_flavor(flavor_id, opts={})
# "flavorId"=>3,
# "hostId"=>"fabfc1cebef6f1d7e4b075138dbd6b46",
# "status"=>"ACTIVE"}]
-
+ #
def list_servers(opts={})
api_or_cache(:get, detailed_path("/servers", opts), opts.merge(:incrementally => true))
end
@@ -483,7 +493,7 @@ def update_server(server_id, server_data, opts={})
#
def reboot_server(server_id, type = :soft, opts={})
body = { 'reboot' => { 'type' => type.to_s.upcase } }
- api(:post, "/servers/#{server_id}/actions/reboot", opts.merge(:body => body.to_json))
+ api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
end
# The rebuild function removes all data on the server and replaces it with the specified image.
@@ -507,7 +517,7 @@ def reboot_server(server_id, type = :soft, opts={})
#
def rebuild_server(server_id, image_id, opts={})
body = { 'rebuild' => { 'imageId' => image_id } }
- api(:post, "/servers/#{server_id}/actions/rebuild", opts.merge(:body => body.to_json))
+ api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
end
# The resize function converts an existing server to a different flavor, in essence, scaling the server up
@@ -530,7 +540,7 @@ def rebuild_server(server_id, image_id, opts={})
#
def resize_server(server_id, flavor_id, opts={})
body = { 'resize' => { 'flavorId' => flavor_id } }
- api(:post, "/servers/#{server_id}/actions/resize", opts.merge(:body => body.to_json))
+ api(:post, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
end
# Confirm a server resize action.
@@ -538,7 +548,8 @@ def resize_server(server_id, flavor_id, opts={})
# rackspace.confirm_resized_server(2290) #=> true
#
def confirm_resized_server(server_id, opts={})
- api(:put, "/servers/#{server_id}/actions/resize", opts)
+ body = { 'confirmResize' => nil }
+ api(:put, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
end
# Revert a server resize action.
@@ -546,7 +557,36 @@ def confirm_resized_server(server_id, opts={})
# rackspace.revert_resized_server(2290) #=> true
#
def revert_resized_server(server_id, opts={})
- api(:delete, "/servers/#{server_id}/actions/resize", opts)
+ body = { 'revertResize' => nil }
+ api(:delete, "/servers/#{server_id}/action", opts.merge(:body => body.to_json))
+ end
+
+ #--------------------------------
+ # Server addresses
+ #--------------------------------
+
+ # Get server addresses.
+ #
+ # # get all addresses
+ # rackspace.list_addresses(62844) #=>
+ # {"addresses"=>{"public"=>["174.143.246.228"], "private"=>["10.176.134.157"]}}
+ #
+ # # get public addresses
+ # rackspace.list_addresses(62844, :public) #=>
+ # {"public"=>["174.143.246.228"]}
+ #
+ # # get private addresses
+ # rackspace.list_addresses(62844, :private) #=>
+ # {"private"=>["10.176.134.157"]}
+ #
+ # RightRackspace caching: no
+ def list_addresses(server_id, address_type=:all, opts={})
+ path = "/servers/#{server_id}/ip"
+ case address_type.to_s
+ when 'public' then path += "/public"
+ when 'private' then path += "/private"
+ end
+ api(:get, path, opts.merge(:incrementally => true))
end
# Share an IP from an existing server in the specified shared IP group to another
@@ -567,14 +607,14 @@ def revert_resized_server(server_id, opts={})
# "hostId"=>"1d5fa1271f57354d9e2861e848568eb3",
# "status"=>"SHARE_IP_NO_CONFIG"}}
#
- def share_ip_address(server_id, shared_ip_group_id, address, opts={})
+ def share_ip_address(server_id, shared_ip_group_id, address, configure_server=true, opts={})
body = {
'shareIp' => {
'sharedIpGroupId' => shared_ip_group_id,
- 'addr' => address
+ 'configureServer' => configure_server
}
}
- api(:post, "/servers/#{server_id}/actions/share_ip", opts.merge(:body => body.to_json))
+ api(:put, "/servers/#{server_id}/ip/public/#{address}", opts.merge(:body => body.to_json))
end
# Remove a shared IP address from the specified server
@@ -583,7 +623,7 @@ def share_ip_address(server_id, shared_ip_group_id, address, opts={})
#
def unshare_ip_address(server_id, address, opts={})
body = { 'unshareIp' => { 'addr' => address } }
- api(:post, "/servers/#{server_id}/actions/unshare_ip", opts.merge(:body => body.to_json))
+ api(:delete, "/servers/#{server_id}/ip/public/#{address}", opts.merge(:body => body.to_json))
end
# Delete a server.
@@ -645,7 +685,7 @@ def delete_backup_schedule(server_id, opts={})
# Shared IP Groups
#--------------------------------
- # List shared IP groups.
+ # List shared IP groups. Options: :detail => false|true.
#
# RightRackspace caching: yes, keys: '/shared_ip_groups', '/shared_ip_groups/detail'
#
View
42 lib/rackspace_base.rb
@@ -223,19 +223,27 @@ def request_info(request_hash) #:nodoc:
result = nil
# check response for success...
case @last_response.code
- when '304' # Cache hit: NotModified
- @error_handler = nil
- on_event(:on_success)
- raise NoChange.new("NotModified: '#{simple_path(@last_request.path)}' has not changed since the requested time.")
- when /^2../ # SUCCESS
+ when /^2..|304/ # SUCCESS
@error_handler = nil
on_event(:on_success)
+
# Cache hit: Cached
- if @last_response.code == '203' && @last_response.body.blank?
- # 203 + an empty response body means we asked whether the value did not change and it hit
- path = cached_path(@last_request.path)
- raise NoChange.new("Cached: '#{path}' has not changed since #{@cache[path][:last_modified_at]}.")
+ case @last_response.code
+ when '304' # 'changes-since' param
+ raise NoChange.new("NotModified: '#{simple_path(@last_request.path)}' has not changed since the requested time.")
+ when '203' # 'if-modified-since' header
+ # TODO: Mhhh... It seems Rackspace updates 'last-modified' header every 60 seconds or something even if nothing has changed
+ if @last_response.body.blank?
+ cached_path = cached_path(@last_request.path)
+ last_modified = @last_response['last-modified'].first
+ message_header = merged_params[:caching] &&
+ @cache[cached_path] &&
+ @cache[cached_path][:last_modified_at] == last_modified ? 'Cached' : 'NotModified'
+ # 203 + an empty response body means we asked whether the value did not change and it hit
+ raise NoChange.new("#{message_header}: '#{cached_path}' has not changed since #{last_modified}.")
+ end
end
+
# Parse a response body. If the body is empty the return +true+
@@bench.parser.add! do
result = if @last_response.body.blank? then true
@@ -280,6 +288,8 @@ def detailed_path(path, options) # :nodoc:
# Params: +soft+ is used for auto-authentication when auth_token expires. Soft auth
# do not overrides @last_request and @last_response attributes (are needed for a proper
# error handling) on success.
+ #
+ # TODO: make sure 'x-compute-url' header works when Rackspace release the service publicly
def authenticate(opts={}) # :nodoc:
@logged_in = false
@auth_headers = {}
@@ -322,14 +332,15 @@ def incrementally_list_resources(verb, path, offset=nil, limit=nil, opts={}, &bl
end
result = { resource_name => []}
loop do
- begin
+# begin
response = api(verb, path, opts)
result[resource_name] += response[resource_name]
- rescue Rightscale::Rackspace::Error => e
- raise e unless e.message[/itemNotFound/]
- response = nil
- end
+# rescue Rightscale::Rackspace::Error => e
+# raise e unless e.message[/itemNotFound/]
+# response = nil
+# end
break if response.blank? ||
+ (response[resource_name].blank?) ||
(block && !block.call(response)) ||
(response[resource_name].size < opts[:vars]['limit'])
opts[:vars]['offset'] += opts[:vars]['limit']
@@ -408,7 +419,8 @@ class HttpErrorHandler # :nodoc:
REAUTHENTICATE_ON = ['401']
# Some error are too ennoing to be logged: '404' comes very often when one calls
# incrementally_list_something
- SKIP_LOGGING_ON = ['404']
+# SKIP_LOGGING_ON = ['404']
+ SKIP_LOGGING_ON = []
@@reiteration_start_delay = 0.2
def self.reiteration_start_delay
View
4 test/_test_credentials.rb
@@ -23,8 +23,8 @@ def self.auth_key=(newval)
#
# or you have a file: ~/.rightscale/test_rackspace_credentials.rb with text:
#
-# TestCredentials.key = 'your_rackspace_username'
-# TestCredentials.secret = 'your_rackspace_auth_key'
+# TestCredentials.username = 'your_rackspace_username'
+# TestCredentials.auth_key = 'your_rackspace_auth_key'
#
def self.get_credentials
Dir.chdir do
View
41 test/test_right_rackspace.rb
@@ -15,7 +15,9 @@ class TestRightRackspace < Test::Unit::TestCase
def setup
$stdout.sync = true
::TestCredentials.get_credentials
+ # TODO: remove :auth_endpoint and :service_endpoint when the service is released publicly
@rackspace = Rightscale::Rackspace::Interface.new(TestCredentials.username, TestCredentials.auth_key,
+ :logger => Logger.new('/dev/null'),
:auth_endpoint => 'https://api.mosso.com/auth',
:service_endpoint => 'https://servers.api.rackspacecloud.com/v1.0/413609')
end
@@ -34,15 +36,16 @@ def get_test_server_id
def wail_until(reason, &block)
print reason
loop do
- print '.'
- sleep 3
+ print '*'
+ sleep 5
break if block.call
end
- sleep 15
+ sleep 10
puts
end
def resources_test(name)
+# puts ">>> Resource test: #{name}"
resource_type = ''
name.split('_').each_with_index do |w, i|
resource_type += (i==0 ? w.downcase : w.capitalize)
@@ -85,6 +88,7 @@ def resources_test(name)
end
def right_rackspace_level_caching_test(cache_key, *api_call_data)
+# puts ">>> Rackspace gem level caching test: #{cache_key}"
# Assert there are no any exceptions while the caching is off
@rackspace.send(*api_call_data)
@rackspace.send(*api_call_data)
@@ -103,6 +107,7 @@ def right_rackspace_level_caching_test(cache_key, *api_call_data)
end
def rackspace_service_level_caching_test(*api_call_data)
+# puts ">>> Rackspace service caching test: #{cache_key}"
assert_raise(Rightscale::Rackspace::NoChange) do
opts = api_call_data.last.is_a?(Hash) ? api_call_data.pop : {}
opts[:vars] = { 'changes-since' => Time.now.utc }
@@ -219,7 +224,35 @@ def test_044_backup_schedule
assert @rackspace.update_backup_schedule(id)
end
- def test_045_delete_server
+ def test_045_list_addresses_test
+ id = get_test_server_id
+ # all addresses
+ addresses = nil
+ assert_nothing_raised do
+ addresses = @rackspace.list_addresses(id)
+ end
+ assert addresses['addresses'].is_a?(Hash)
+ assert addresses['addresses']['public'].is_a?(Array)
+ assert addresses['addresses']['private'].is_a?(Array)
+ # public addresses
+ public_addresses = nil
+ assert_nothing_raised do
+ public_addresses = @rackspace.list_addresses(id, :public)
+ end
+ assert public_addresses.is_a?(Hash)
+ assert public_addresses['public'].is_a?(Array)
+ assert !public_addresses['public'].blank?
+ # private addresses
+ private_addresses = nil
+ assert_nothing_raised do
+ private_addresses = @rackspace.list_addresses(id, :private)
+ end
+ assert private_addresses.is_a?(Hash)
+ assert private_addresses['private'].is_a?(Array)
+ assert !private_addresses['private'].blank?
+ end
+
+ def test_049_delete_server
assert @rackspace.delete_server(get_test_server_id)
end
Please sign in to comment.
Something went wrong with that request. Please try again.