diff --git libcloud/common/rackspace.py libcloud/common/rackspace.py index 953a961..908c73e 100644 --- libcloud/common/rackspace.py +++ libcloud/common/rackspace.py @@ -19,7 +19,7 @@ Common utilities for Rackspace Cloud Servers and Cloud Files import httplib from urllib2 import urlparse from libcloud.common.base import ConnectionUserAndKey -from libcloud.compute.types import InvalidCredsError +from libcloud.compute.types import InvalidCredsError, MalformedResponseError AUTH_HOST_US='auth.api.rackspacecloud.com' AUTH_HOST_UK='lon.auth.api.rackspacecloud.com' @@ -95,20 +95,32 @@ class RackspaceBaseConnection(ConnectionUserAndKey): resp = conn.getresponse() - if resp.status != httplib.NO_CONTENT: - raise InvalidCredsError() + # HTTP NO CONTENT (204): auth successful + if resp.status == httplib.NO_CONTENT: + headers = dict(resp.getheaders()) + + try: + self.server_url = headers['x-server-management-url'] + self.storage_url = headers['x-storage-url'] + self.cdn_management_url = headers['x-cdn-management-url'] + self.lb_url = self.server_url.replace("servers", "ord.loadbalancers") + self.auth_token = headers['x-auth-token'] - headers = dict(resp.getheaders()) + # Returned 204 but has missing information in the header, something is wrong + except KeyError, e: + raise MalformedResponseError('Malformed response', + body='Missing header: %s' % e, driver=self.driver) - try: - self.server_url = headers['x-server-management-url'] - self.storage_url = headers['x-storage-url'] - self.cdn_management_url = headers['x-cdn-management-url'] - self.lb_url = self.server_url.replace("servers", "ord.loadbalancers") - self.auth_token = headers['x-auth-token'] - except KeyError: + # HTTP UNAUTHORIZED (401): auth failed + elif resp.status == httplib.UNAUTHORIZED: raise InvalidCredsError() + # Any response code != 401 or 204, something is wrong + else: + raise MalformedResponseError('Malformed response', + body='code: %s body:%s' % (resp.status, ''.join(resp.body.readlines())), + driver=self.driver) + for key in ['server_url', 'storage_url', 'cdn_management_url', 'lb_url']: scheme, server, request_path, param, query, fragment = ( diff --git test/compute/test_rackspace.py test/compute/test_rackspace.py index b46f3dd..dbe92ee 100644 --- test/compute/test_rackspace.py +++ test/compute/test_rackspace.py @@ -16,7 +16,7 @@ import sys import unittest import httplib -from libcloud.common.types import InvalidCredsError +from libcloud.common.types import InvalidCredsError, MalformedResponseError from libcloud.compute.drivers.rackspace import RackspaceNodeDriver as Rackspace from libcloud.compute.base import Node, NodeImage, NodeSize @@ -46,8 +46,17 @@ class RackspaceTests(unittest.TestCase, TestCaseMixin): RackspaceMockHttp.type = 'UNAUTHORIZED_MISSING_KEY' try: self.driver = Rackspace(RACKSPACE_USER, RACKSPACE_KEY) - except InvalidCredsError, e: - self.assertEqual(True, isinstance(e, InvalidCredsError)) + except MalformedResponseError, e: + self.assertEqual(True, isinstance(e, MalformedResponseError)) + else: + self.fail('test should have thrown') + + def test_auth_server_error(self): + RackspaceMockHttp.type = 'INTERNAL_SERVER_ERROR' + try: + self.driver = Rackspace(RACKSPACE_USER, RACKSPACE_KEY) + except MalformedResponseError, e: + self.assertEqual(True, isinstance(e, MalformedResponseError)) else: self.fail('test should have thrown') @@ -197,6 +206,9 @@ class RackspaceMockHttp(MockHttp): def _v1_0_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) + def _v1_0_INTERNAL_SERVER_ERROR(self, method, url, body, headers): + return (httplib.INTERNAL_SERVER_ERROR, "