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:
parent
627deb7c87
commit
73e29db968
@ -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."""
|
||||
|
@ -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)
|
||||
|
@ -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__
|
||||
|
Loading…
Reference in New Issue
Block a user