diff --git a/manilaclient/client.py b/manilaclient/client.py index 12cf50093..1221ee93e 100644 --- a/manilaclient/client.py +++ b/manilaclient/client.py @@ -161,7 +161,7 @@ class HTTPClient(object): body = None if resp.status_code >= 400: - raise exceptions.from_response(resp, body) + raise exceptions.from_response(resp, method, url) return resp, body @@ -196,7 +196,7 @@ class HTTPClient(object): except exceptions.ClientException as e: if attempts > self.retries: raise - if 500 <= e.code <= 599: + if 500 <= e.http_status <= 599: pass else: raise @@ -228,7 +228,9 @@ class HTTPClient(object): We may get redirected to another site, fail or actually get back a service catalog with a token and our endpoints. """ - + method = None + if hasattr(resp, 'request') and hasattr(resp.request, 'method'): + method = resp.request.method if resp.status_code == 200: # content must always present try: self.auth_url = url @@ -260,7 +262,7 @@ class HTTPClient(object): elif resp.status_code == 305: return resp['location'] else: - raise exceptions.from_response(resp, body) + raise exceptions.from_response(resp, method, url) def _fetch_endpoints_from_auth(self, url): """Fetch endpoints from auth. @@ -351,7 +353,8 @@ class HTTPClient(object): if self.projectid: headers['X-Auth-Project-Id'] = self.projectid - resp, body = self.request(url, 'GET', headers=headers) + method = 'GET' + resp, body = self.request(url, method, headers=headers) if resp.status_code in (200, 204): # in some cases we get No Content try: mgmt_header = 'x-server-management-url' @@ -363,7 +366,7 @@ class HTTPClient(object): elif resp.status_code == 305: return resp.headers['location'] else: - raise exceptions.from_response(resp, body) + raise exceptions.from_response(resp, method, url) def _v2_auth(self, url): """Authenticate against a v2.0 auth service.""" diff --git a/manilaclient/exceptions.py b/manilaclient/exceptions.py index 2bfb65ab9..0fe764639 100644 --- a/manilaclient/exceptions.py +++ b/manilaclient/exceptions.py @@ -17,149 +17,13 @@ Exception definitions. """ - -class UnsupportedVersion(Exception): - """Usage of unsupported API version. - - Indicates that the user is trying to use an unsupported version - of the API. - """ - pass +from manilaclient.openstack.common.apiclient.exceptions import * # noqa -class CommandError(Exception): - pass - - -class AuthorizationFailure(Exception): - pass - - -class NoUniqueMatch(Exception): - pass - - -class NoTokenLookupException(Exception): +class NoTokenLookupException(ClientException): """No support for looking up endpoints. This form of authentication does not support looking up endpoints from an existing token. """ pass - - -class EndpointNotFound(Exception): - """Could not find Service or Region in Service Catalog.""" - pass - - -class AmbiguousEndpoints(Exception): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - self.endpoints = endpoints - - def __str__(self): - return "AmbiguousEndpoints: %s" % repr(self.endpoints) - - -class ClientException(Exception): - """The base exception class for all exceptions this library raises.""" - def __init__(self, code, message=None, details=None, request_id=None): - self.code = code - self.message = message or self.__class__.message - self.details = details - self.request_id = request_id - - def __str__(self): - formatted_string = "%s (HTTP %s)" % (self.message, self.code) - if self.request_id: - formatted_string += " (Request-ID: %s)" % self.request_id - - return formatted_string - - -class BadRequest(ClientException): - """HTTP 400 - Bad request: you sent some malformed data.""" - http_status = 400 - message = "Bad request" - - -class Unauthorized(ClientException): - """HTTP 401 - Unauthorized: bad credentials.""" - http_status = 401 - message = "Unauthorized" - - -class Forbidden(ClientException): - """HTTP 403. - - Forbidden: your credentials don't give you access to this resource. - """ - http_status = 403 - message = "Forbidden" - - -class NotFound(ClientException): - """HTTP 404 - Not found.""" - http_status = 404 - message = "Not found" - - -class OverLimit(ClientException): - """HTTP 413. - - Over limit: you're over the API limits for this time period. - """ - http_status = 413 - message = "Over limit" - - -# NotImplemented is a python keyword. -class HTTPNotImplemented(ClientException): - """HTTP 501. - - Not Implemented: the server does not support this operation. - """ - http_status = 501 - message = "Not Implemented" - - -# In Python 2.4 Exception is old-style and thus doesn't have a __subclasses__() -# so we can do this: -# _code_map = dict((c.http_status, c) -# for c in ClientException.__subclasses__()) -# -# Instead, we have to hardcode it: -_code_map = dict((c.http_status, c) for c in [BadRequest, Unauthorized, - Forbidden, NotFound, - OverLimit, HTTPNotImplemented]) - - -def from_response(response, body): - """Parse response and return Exception based on it. - - Return an instance of an ClientException or subclass based - on an requests response. - - Usage:: - - resp, body = requests.request(...) - if resp.status_code != 200: - raise exception_from_response(resp, rest.text) - """ - cls = _code_map.get(response.status_code, ClientException) - if response.headers: - request_id = response.headers.get('x-compute-request-id') - else: - request_id = None - if body: - message = "n/a" - details = "n/a" - if hasattr(body, 'keys'): - error = body[list(body)[0]] - message = error.get('message', None) - details = error.get('details', None) - return cls(code=response.status_code, message=message, details=details, - request_id=request_id) - else: - return cls(code=response.status_code, request_id=request_id) diff --git a/tests/utils.py b/tests/utils.py index 3efe70b8a..3a50178e3 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -46,11 +46,14 @@ class TestResponse(requests.Response): super(TestResponse, self) if isinstance(data, dict): self.status_code = data.get('status_code', None) - self.headers = data.get('headers', None) + self.headers = data.get('headers', {}) + self.headers['x-openstack-request-id'] = data.get( + 'x-openstack-request-id', 'fake-request-id') # Fake the text attribute to streamline Response creation self._text = data.get('text', None) else: self.status_code = data + self.headers = {'x-openstack-request-id': 'fake-request-id'} def __eq__(self, other): return self.__dict__ == other.__dict__