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:
@@ -161,7 +161,7 @@ class HTTPClient(object):
|
|||||||
body = None
|
body = None
|
||||||
|
|
||||||
if resp.status_code >= 400:
|
if resp.status_code >= 400:
|
||||||
raise exceptions.from_response(resp, body)
|
raise exceptions.from_response(resp, method, url)
|
||||||
|
|
||||||
return resp, body
|
return resp, body
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ class HTTPClient(object):
|
|||||||
except exceptions.ClientException as e:
|
except exceptions.ClientException as e:
|
||||||
if attempts > self.retries:
|
if attempts > self.retries:
|
||||||
raise
|
raise
|
||||||
if 500 <= e.code <= 599:
|
if 500 <= e.http_status <= 599:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
@@ -228,7 +228,9 @@ class HTTPClient(object):
|
|||||||
We may get redirected to another site, fail or actually get
|
We may get redirected to another site, fail or actually get
|
||||||
back a service catalog with a token and our endpoints.
|
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
|
if resp.status_code == 200: # content must always present
|
||||||
try:
|
try:
|
||||||
self.auth_url = url
|
self.auth_url = url
|
||||||
@@ -260,7 +262,7 @@ class HTTPClient(object):
|
|||||||
elif resp.status_code == 305:
|
elif resp.status_code == 305:
|
||||||
return resp['location']
|
return resp['location']
|
||||||
else:
|
else:
|
||||||
raise exceptions.from_response(resp, body)
|
raise exceptions.from_response(resp, method, url)
|
||||||
|
|
||||||
def _fetch_endpoints_from_auth(self, url):
|
def _fetch_endpoints_from_auth(self, url):
|
||||||
"""Fetch endpoints from auth.
|
"""Fetch endpoints from auth.
|
||||||
@@ -351,7 +353,8 @@ class HTTPClient(object):
|
|||||||
if self.projectid:
|
if self.projectid:
|
||||||
headers['X-Auth-Project-Id'] = 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
|
if resp.status_code in (200, 204): # in some cases we get No Content
|
||||||
try:
|
try:
|
||||||
mgmt_header = 'x-server-management-url'
|
mgmt_header = 'x-server-management-url'
|
||||||
@@ -363,7 +366,7 @@ class HTTPClient(object):
|
|||||||
elif resp.status_code == 305:
|
elif resp.status_code == 305:
|
||||||
return resp.headers['location']
|
return resp.headers['location']
|
||||||
else:
|
else:
|
||||||
raise exceptions.from_response(resp, body)
|
raise exceptions.from_response(resp, method, url)
|
||||||
|
|
||||||
def _v2_auth(self, url):
|
def _v2_auth(self, url):
|
||||||
"""Authenticate against a v2.0 auth service."""
|
"""Authenticate against a v2.0 auth service."""
|
||||||
|
@@ -17,149 +17,13 @@
|
|||||||
Exception definitions.
|
Exception definitions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from manilaclient.openstack.common.apiclient.exceptions import * # noqa
|
||||||
class UnsupportedVersion(Exception):
|
|
||||||
"""Usage of unsupported API version.
|
|
||||||
|
|
||||||
Indicates that the user is trying to use an unsupported version
|
|
||||||
of the API.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class CommandError(Exception):
|
class NoTokenLookupException(ClientException):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class AuthorizationFailure(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class NoUniqueMatch(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class NoTokenLookupException(Exception):
|
|
||||||
"""No support for looking up endpoints.
|
"""No support for looking up endpoints.
|
||||||
|
|
||||||
This form of authentication does not support looking up
|
This form of authentication does not support looking up
|
||||||
endpoints from an existing token.
|
endpoints from an existing token.
|
||||||
"""
|
"""
|
||||||
pass
|
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)
|
super(TestResponse, self)
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
self.status_code = data.get('status_code', None)
|
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
|
# Fake the text attribute to streamline Response creation
|
||||||
self._text = data.get('text', None)
|
self._text = data.get('text', None)
|
||||||
else:
|
else:
|
||||||
self.status_code = data
|
self.status_code = data
|
||||||
|
self.headers = {'x-openstack-request-id': 'fake-request-id'}
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.__dict__ == other.__dict__
|
return self.__dict__ == other.__dict__
|
||||||
|
Reference in New Issue
Block a user