summaryrefslogtreecommitdiff
path: root/ironic/common/exception.py
diff options
context:
space:
mode:
Diffstat (limited to 'ironic/common/exception.py')
-rw-r--r--ironic/common/exception.py119
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