Added basic exception parsing for interaction w/ drivers

This commit is contained in:
tengqm 2015-02-11 17:53:20 +08:00
parent 3f61639a44
commit 6a64ca2353

View File

@ -13,13 +13,157 @@
'''
SDK Client
'''
from oslo_serialization import jsonutils
from openstack import connection
from openstack import exceptions
from openstack import user_preference
from requests import exceptions as reqexc
USER_AGENT = 'senlin'
exc = exceptions
verbose = False
class BaseException(Exception):
'''An error occurred.'''
def __init__(self, message=None):
self.message = message
def __str__(self):
return self.message or self.__class__.__doc__
class HTTPException(BaseException):
"""Base exception for all HTTP-derived exceptions."""
code = 'N/A'
def __init__(self, error=None):
super(HTTPException, self).__init__(error)
try:
self.error = error
if 'error' not in self.error:
raise KeyError(_('Key "error" not exists'))
except KeyError:
# If key 'error' does not exist, self.message becomes
# no sense. In this case, we return doc of current
# exception class instead.
self.error = {'error': {'message': self.__class__.__doc__}}
except Exception:
self.error = {'error':
{'message': self.message or self.__class__.__doc__}}
def __str__(self):
message = self.error['error'].get('message', 'Internal Error')
if verbose:
traceback = self.error['error'].get('traceback', '')
return (_('ERROR: %(message)s\n%(traceback)s') %
{'message': message, 'traceback': traceback})
else:
code = self.error['error'].get('code', 'Unknown')
return _('ERROR(%(code)s): %(message)s') % {'code': code,
'message': message}
class ClientError(HTTPException):
pass
class ServerError(HTTPException):
pass
class ConnectionRefused(HTTPException):
# 111
pass
class HTTPBadRequest(ClientError):
# 400
pass
class HTTPUnauthorized(ClientError):
# 401
pass
class HTTPForbidden(ClientError):
# 403
pass
class HTTPNotFound(ClientError):
# 404
pass
class HTTPInternalServerError(ServerError):
# 500
pass
class HTTPNotImplemented(ServerError):
# 501
pass
class HTTPServiceUnavailable(ServerError):
# 503
pass
_EXCEPTION_MAP = {
111: ConnectionRefused,
400: HTTPBadRequest,
401: HTTPUnauthorized,
403: HTTPForbidden,
404: HTTPNotFound,
500: HTTPInternalServerError,
501: HTTPNotImplemented,
503: HTTPServiceUnavailable,
}
def parse_exception(ex):
'''Parse exception code and yield useful information.
:param details: details of the exception.
'''
if isinstance(ex, exc.HttpException):
record = jsonutils.loads(ex.details)
elif isinstance(ex, reqexc.RequestException):
# Exceptions that are not captured by SDK
code = ex.message[1].errno
record = {
'error': {
'code': code,
'message': ex.message[0],
}
}
else:
print(_('Unknown exception: %s') % ex)
return
try:
code = record['error']['code']
except KeyError as err:
print(_('Malformed exception record, missing field "%s"') % err)
print(_('Original error record: %s') % record)
return
if code in _EXCEPTION_MAP:
inst = _EXCEPTION_MAP.get(code)
return inst(record)
else:
return HTTPException(record)
def ignore_not_found(ex):
parsed = parse_exception(ex)
if not isinstance(parsed, HTTPNotFound):
raise parsed
def create_connection(context):