diff options
| author | Andrey Kurilin <akurilin@mirantis.com> | 2014-04-16 14:09:00 +0300 |
|---|---|---|
| committer | Andrey Kurilin <akurilin@mirantis.com> | 2014-04-24 12:01:31 +0300 |
| commit | 0f6419015c5f03448689ffe7c75ff3bdb5f19c08 (patch) | |
| tree | 038263a6a097ed273f35f5afd98ac0d069c7aa1a | |
| parent | 587c4705b88339e3dd2acd7a30a9fdeae737740f (diff) | |
| download | python-ironicclient-0f6419015c5f03448689ffe7c75ff3bdb5f19c08.tar.gz | |
Sync latest code and reuse exceptions from oslo
Module `ironicclient.exc` contains exceptions which equal to exceptions
from oslo common code.
This patch:
- sync latest code of `apiclient.exceptions`(hash of last commit in oslo
related to apiclient.exceptions: 3570f44d5ccf52c59cc586bed1446b874fc3c07c)
- reuses exceptions from common code
- removes needless exceptions from `ironicclient.exc`
Related to bp common-client-library-2
Change-Id: I784007f36dd6a63fc4c77e0d0f0f000e05eb792f
| -rw-r--r-- | ironicclient/common/http.py | 16 | ||||
| -rw-r--r-- | ironicclient/common/utils.py | 2 | ||||
| -rw-r--r-- | ironicclient/exc.py | 184 | ||||
| -rw-r--r-- | ironicclient/openstack/common/apiclient/exceptions.py | 23 | ||||
| -rw-r--r-- | ironicclient/tests/test_http.py | 17 | ||||
| -rw-r--r-- | ironicclient/v1/node.py | 2 |
6 files changed, 72 insertions, 172 deletions
diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index ecfac51..2ac0ea5 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -56,7 +56,7 @@ class HTTPClient(object): _class = six.moves.http_client.HTTPConnection else: msg = 'Unsupported scheme: %s' % parts.scheme - raise exc.InvalidEndpoint(msg) + raise exc.EndpointException(msg) return (_class, _args, _kwargs) @@ -66,7 +66,7 @@ class HTTPClient(object): return _class(*self.connection_params[1][0:2], **self.connection_params[2]) except six.moves.http_client.InvalidURL: - raise exc.InvalidEndpoint() + raise exc.EndpointException() def log_curl_request(self, method, url, kwargs): curl = ['curl -i -X %s' % method] @@ -143,12 +143,12 @@ class HTTPClient(object): except socket.gaierror as e: message = ("Error finding address for %(url)s: %(e)s" % dict(url=url, e=e)) - raise exc.InvalidEndpoint(message=message) + raise exc.EndpointNotFound(message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint message = ("Error communicating with %(endpoint)s %(e)s" % dict(endpoint=endpoint, e=e)) - raise exc.CommunicationError(message=message) + raise exc.ConnectionRefused(message) body_iter = ResponseBodyIterator(resp) @@ -164,14 +164,14 @@ class HTTPClient(object): if 400 <= resp.status < 600: LOG.warn("Request returned failure status.") error_json = self._extract_error_json(body_str) - raise exc.from_response(resp, - error_json.get('faultstring'), - error_json.get('debuginfo')) + raise exc.from_response( + resp, error_json.get('faultstring'), + error_json.get('debuginfo'), method, url) elif resp.status in (301, 302, 305): # Redirected. Reissue the request to the new location. return self._http_request(resp['location'], method, **kwargs) elif resp.status == 300: - raise exc.from_response(resp) + raise exc.from_response(resp, method=method, url=url) return resp, body_iter diff --git a/ironicclient/common/utils.py b/ironicclient/common/utils.py index 1bca1de..fc2daff 100644 --- a/ironicclient/common/utils.py +++ b/ironicclient/common/utils.py @@ -179,7 +179,7 @@ def args_array_to_dict(kwargs, key_to_convert): except ValueError: raise exc.CommandError( _('%(key)s must be a list of KEY=VALUE not "%(values)s"') % - {'key': key_to_convert, 'values': values_to_convert}) + {'key': key_to_convert, 'values': values_to_convert}) return kwargs diff --git a/ironicclient/exc.py b/ironicclient/exc.py index aa2d840..4c5cfd1 100644 --- a/ironicclient/exc.py +++ b/ironicclient/exc.py @@ -10,169 +10,49 @@ # License for the specific language governing permissions and limitations # under the License. -import sys +from ironicclient.openstack.common.apiclient import exceptions +from ironicclient.openstack.common.apiclient.exceptions import * # noqa -class BaseException(Exception): - """An error occurred.""" - def __init__(self, message=None): - self.message = message +# NOTE(akurilin): This alias is left here since v.0.1.3 to support backwards +# compatibility. +InvalidEndpoint = EndpointException +CommunicationError = ConnectionRefused +HTTPBadRequest = BadRequest +HTTPInternalServerError = InternalServerError +HTTPNotFound = NotFound +HTTPServiceUnavailable = ServiceUnavailable - def __str__(self): - return self.message or self.__class__.__doc__ - -class AmbigiousAuthSystem(BaseException): +class AmbigiousAuthSystem(ClientException): """Could not obtain token and endpoint using provided credentials.""" - - -class CommandError(BaseException): - """Invalid usage of CLI.""" - - -class InvalidEndpoint(BaseException): - """The provided endpoint is invalid.""" - - -class CommunicationError(BaseException): - """Unable to communicate with server.""" - - -class ClientException(Exception): - """DEPRECATED.""" - - -class HTTPException(ClientException): - """Base exception for all HTTP-derived exceptions.""" - code = 'N/A' - - def __init__(self, details=None, server_traceback=None): - self.details = details - self.server_traceback = server_traceback - - def __str__(self): - msg = "%s (HTTP %s)" % (self.__class__.__name__, - self.code) - if self.details: - msg = self.details - if self.server_traceback: - msg += "\n%s" % self.server_traceback - return msg - - -class HTTPMultipleChoices(HTTPException): - code = 300 - - def __str__(self): - self.details = ("Requested version of OpenStack Images API is not" - "available.") - return "%s (HTTP %s) %s" % (self.__class__.__name__, self.code, - self.details) - - -class BadRequest(HTTPException): - """DEPRECATED.""" - code = 400 - - -class HTTPBadRequest(BadRequest): - pass - - -class Unauthorized(HTTPException): - """DEPRECATED.""" - code = 401 - - -class HTTPUnauthorized(Unauthorized): pass -class Forbidden(HTTPException): - """DEPRECATED.""" - code = 403 - - -class HTTPForbidden(Forbidden): - pass - - -class NotFound(HTTPException): - """DEPRECATED.""" - code = 404 - - -class HTTPNotFound(NotFound): - pass - - -class HTTPMethodNotAllowed(HTTPException): - code = 405 - - -class Conflict(HTTPException): - """DEPRECATED.""" - code = 409 - - -class HTTPConflict(Conflict): - pass - - -class OverLimit(HTTPException): - """DEPRECATED.""" - code = 413 - - -class HTTPOverLimit(OverLimit): - pass - - -class HTTPInternalServerError(HTTPException): - code = 500 - - -class HTTPNotImplemented(HTTPException): - code = 501 - - -class HTTPBadGateway(HTTPException): - code = 502 - - -class ServiceUnavailable(HTTPException): - """DEPRECATED.""" - code = 503 - - -class HTTPServiceUnavailable(ServiceUnavailable): +class InvalidAttribute(ClientException): pass -#NOTE(bcwaldon): Build a mapping of HTTP codes to corresponding exception -# classes -_code_map = {} -for obj_name in dir(sys.modules[__name__]): - if obj_name.startswith('HTTP'): - obj = getattr(sys.modules[__name__], obj_name) - _code_map[obj.code] = obj - +def from_response(response, message=None, traceback=None, method=None, + url=None): + """Return an instance of an HttpError based on response from + httplib/requests. + """ -def from_response(response, message=None, traceback=None): - """Return an instance of an HTTPException based on httplib response.""" - cls = _code_map.get(response.status, HTTPException) - return cls(message, traceback) + error_body = {} + if message: + error_body['message'] = message + if traceback: + error_body['details'] = traceback + if hasattr(response, 'status') and not hasattr(response, 'status_code'): + # NOTE(akurilin): These modifications around response object give + # ability to get all necessary information in method `from_response` + # from common code, which expecting response object from `requests` + # library instead of object from `httplib/httplib2` library. + response.status_code = response.status + response.headers = { + 'Content-Type': response.getheader('content-type', "")} + response.json = lambda: {'error': error_body} -class NoTokenLookupException(Exception): - """DEPRECATED.""" - pass - - -class EndpointNotFound(Exception): - """DEPRECATED.""" - pass - - -class InvalidAttribute(ClientException): - pass + return exceptions.from_response(response, message, url) diff --git a/ironicclient/openstack/common/apiclient/exceptions.py b/ironicclient/openstack/common/apiclient/exceptions.py index 4776d58..ada1344 100644 --- a/ironicclient/openstack/common/apiclient/exceptions.py +++ b/ironicclient/openstack/common/apiclient/exceptions.py @@ -127,6 +127,11 @@ class HttpError(ClientException): super(HttpError, self).__init__(formatted_string) +class HTTPRedirection(HttpError): + """HTTP Redirection.""" + message = "HTTP Redirection" + + class HTTPClientError(HttpError): """Client-side HTTP error. @@ -144,6 +149,16 @@ class HttpServerError(HttpError): message = "HTTP Server Error" +class MultipleChoices(HTTPRedirection): + """HTTP 300 - Multiple Choices. + + Indicates multiple options for the resource that the client may follow. + """ + + http_status = 300 + message = "Multiple Choices" + + class BadRequest(HTTPClientError): """HTTP 400 - Bad Request. @@ -425,10 +440,10 @@ def from_response(response, method, url): except ValueError: pass else: - if hasattr(body, "keys"): - error = body[body.keys()[0]] - kwargs["message"] = error.get("message", None) - kwargs["details"] = error.get("details", None) + if isinstance(body, dict): + error = list(body.values())[0] + kwargs["message"] = error.get("message") + kwargs["details"] = error.get("details") elif content_type.startswith("text/"): kwargs["details"] = response.text diff --git a/ironicclient/tests/test_http.py b/ironicclient/tests/test_http.py index 94847a6..d7e82d5 100644 --- a/ironicclient/tests/test_http.py +++ b/ironicclient/tests/test_http.py @@ -64,10 +64,10 @@ class HttpClientTest(utils.BaseTestCase): client.get_connection = \ lambda *a, **kw: utils.FakeConnection(fake_resp) - error = self.assertRaises(exc.HTTPInternalServerError, + error = self.assertRaises(exc.InternalServerError, client.json_request, 'GET', '/v1/resources') - self.assertEqual('HTTPInternalServerError (HTTP 500)', str(error)) + self.assertEqual('Internal Server Error (HTTP 500)', str(error)) def test_server_exception_msg_only(self): error_msg = 'test error msg' @@ -80,10 +80,10 @@ class HttpClientTest(utils.BaseTestCase): client.get_connection = \ lambda *a, **kw: utils.FakeConnection(fake_resp) - error = self.assertRaises(exc.HTTPInternalServerError, + error = self.assertRaises(exc.InternalServerError, client.json_request, 'GET', '/v1/resources') - self.assertEqual(error_msg, str(error)) + self.assertEqual(error_msg + ' (HTTP 500)', str(error)) def test_server_exception_msg_and_traceback(self): error_msg = 'another test error' @@ -98,7 +98,12 @@ class HttpClientTest(utils.BaseTestCase): client.get_connection = \ lambda *a, **kw: utils.FakeConnection(fake_resp) - error = self.assertRaises(exc.HTTPInternalServerError, + error = self.assertRaises(exc.InternalServerError, client.json_request, 'GET', '/v1/resources') - self.assertEqual(error_msg + "\n" + error_trace, str(error)) + + self.assertEqual( + '%(error)s (HTTP 500)\n%(trace)s' % {'error': error_msg, + 'trace': error_trace}, + "%(error)s\n%(details)s" % {'error': str(error), + 'details': str(error.details)}) diff --git a/ironicclient/v1/node.py b/ironicclient/v1/node.py index 2570aa6..ede506f 100644 --- a/ironicclient/v1/node.py +++ b/ironicclient/v1/node.py @@ -66,7 +66,7 @@ class NodeManager(base.Manager): uuid = getattr(nodes[0], 'uuid') return self.get(uuid) else: - raise exc.HTTPNotFound() + raise exc.NotFound() def create(self, **kwargs): new = {} |
