Reuse exceptions from common apiclient code

apiclient package from common code has 'exceptions' module,
so, lets reuse its exceptions and leave defined only one
exception that is absent there - NoTokenLookupException.

Partially implements: blueprint use-common-code

Change-Id: I024a90c407e2bd8f25f58935ab8a4241e038f3a8
This commit is contained in:
Valeriy Ponomaryov 2014-07-14 09:01:45 -04:00
parent 627deb7c87
commit 73e29db968
3 changed files with 15 additions and 145 deletions

View File

@ -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."""

View File

@ -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)

View File

@ -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__