diff options
Diffstat (limited to 'ironic/common/exception.py')
-rw-r--r-- | ironic/common/exception.py | 119 |
1 files changed, 2 insertions, 117 deletions
diff --git a/ironic/common/exception.py b/ironic/common/exception.py index 96be2b0fa..b64640f1f 100644 --- a/ironic/common/exception.py +++ b/ironic/common/exception.py @@ -14,132 +14,17 @@ # License for the specific language governing permissions and limitations # under the License. -"""Ironic base exception handling. - -SHOULD include dedicated exception logging. - -""" - -import collections +"""Ironic specific exceptions list.""" +from ironic_lib.exception import IronicException from oslo_log import log as logging -from oslo_serialization import jsonutils -import six from six.moves import http_client from ironic.common.i18n import _ -from ironic.conf import CONF LOG = logging.getLogger(__name__) -def _ensure_exception_kwargs_serializable(exc_class_name, kwargs): - """Ensure that kwargs are serializable - - Ensure that all kwargs passed to exception constructor can be passed over - RPC, by trying to convert them to JSON, or, as a last resort, to string. - If it is not possible, unserializable kwargs will be removed, letting the - receiver to handle the exception string as it is configured to. - - :param exc_class_name: an IronicException class name. - :param kwargs: a dictionary of keyword arguments passed to the exception - constructor. - :returns: a dictionary of serializable keyword arguments. - """ - serializers = [(jsonutils.dumps, _('when converting to JSON')), - (six.text_type, _('when converting to string'))] - exceptions = collections.defaultdict(list) - serializable_kwargs = {} - for k, v in kwargs.items(): - for serializer, msg in serializers: - try: - serializable_kwargs[k] = serializer(v) - exceptions.pop(k, None) - break - except Exception as e: - exceptions[k].append( - '(%(serializer_type)s) %(e_type)s: %(e_contents)s' % - {'serializer_type': msg, 'e_contents': e, - 'e_type': e.__class__.__name__}) - if exceptions: - LOG.error("One or more arguments passed to the %(exc_class)s " - "constructor as kwargs can not be serialized. The " - "serialized arguments: %(serialized)s. These " - "unserialized kwargs were dropped because of the " - "exceptions encountered during their " - "serialization:\n%(errors)s", - dict(errors=';\n'.join("%s: %s" % (k, '; '.join(v)) - for k, v in exceptions.items()), - exc_class=exc_class_name, - serialized=serializable_kwargs)) - # We might be able to actually put the following keys' values into - # format string, but there is no guarantee, drop it just in case. - for k in exceptions: - del kwargs[k] - return serializable_kwargs - - -class IronicException(Exception): - """Base Ironic Exception - - To correctly use this class, inherit from it and define - a '_msg_fmt' property. That message will get printf'd - with the keyword arguments provided to the constructor. - - If you need to access the message from an exception you should use - six.text_type(exc) - - """ - _msg_fmt = _("An unknown exception occurred.") - code = http_client.INTERNAL_SERVER_ERROR - safe = False - - def __init__(self, message=None, **kwargs): - - self.kwargs = _ensure_exception_kwargs_serializable( - self.__class__.__name__, kwargs) - - if 'code' not in self.kwargs: - try: - self.kwargs['code'] = self.code - except AttributeError: - pass - else: - self.code = int(kwargs['code']) - - if not message: - try: - message = self._msg_fmt % kwargs - - except Exception as e: - # kwargs doesn't match a variable in self._msg_fmt - # log the issue and the kwargs - prs = ', '.join('%s: %s' % pair for pair in kwargs.items()) - LOG.exception('Exception in string format operation ' - '(arguments %s)', prs) - if CONF.fatal_exception_format_errors: - raise e - else: - # at least get the core self._msg_fmt out if something - # happened - message = self._msg_fmt - - super(IronicException, self).__init__(message) - - def __str__(self): - """Encode to utf-8 then wsme api can consume it as well.""" - value = self.__unicode__() - if six.PY3: - # On Python 3 unicode is the same as str - return value - else: - return value.encode('utf-8') - - def __unicode__(self): - """Return a unicode representation of the exception message.""" - return six.text_type(self.args[0]) - - class NotAuthorized(IronicException): _msg_fmt = _("Not authorized.") code = http_client.FORBIDDEN |