diff options
author | Laszlo Hegedus <laszlo.hegedus@ericsson.com> | 2016-05-23 09:20:04 +0200 |
---|---|---|
committer | Balazs Gibizer <balazs.gibizer@ericsson.com> | 2016-06-21 09:39:47 +0200 |
commit | 6329d721ef326488d5d660e4f68febf563ed93ab (patch) | |
tree | f58c81d0177f00b85c306a2c01b927b6a712797b /nova/exception_wrapper.py | |
parent | 5cb46edbf089b477a57bf48a13956e4be493d1db (diff) | |
download | nova-6329d721ef326488d5d660e4f68febf563ed93ab.tar.gz |
Transform wrap_exception notification to versioned format
A new versioned notification is emitted from the wrap_exception
decorator.
Change-Id: I8fcbce111537dae6ad3ba0961fb761540ae800ed
Partially-Implements: bp versioned-notification-transformation-newton
Diffstat (limited to 'nova/exception_wrapper.py')
-rw-r--r-- | nova/exception_wrapper.py | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/nova/exception_wrapper.py b/nova/exception_wrapper.py new file mode 100644 index 0000000000..5b74c3b72f --- /dev/null +++ b/nova/exception_wrapper.py @@ -0,0 +1,94 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import functools +import inspect + +from oslo_utils import excutils +import six + +import nova.conf +from nova.notifications.objects import base +from nova.notifications.objects import exception +from nova.objects import fields +from nova import safe_utils + +CONF = nova.conf.CONF + + +def _emit_exception_notification(notifier, context, ex, function_name, args, + binary): + _emit_legacy_exception_notification(notifier, context, ex, function_name, + args) + _emit_versioned_exception_notification(context, ex, binary) + + +def _emit_versioned_exception_notification(context, ex, binary): + versioned_exception_payload = exception.ExceptionPayload.from_exception(ex) + publisher = base.NotificationPublisher(context=context, host=CONF.host, + binary=binary) + event_type = base.EventType( + object='compute', + action=fields.NotificationAction.EXCEPTION) + notification = exception.ExceptionNotification( + publisher=publisher, + event_type=event_type, + priority=fields.NotificationPriority.ERROR, + payload=versioned_exception_payload) + notification.emit(context) + + +def _emit_legacy_exception_notification(notifier, context, ex, function_name, + args): + payload = dict(exception=ex, args=args) + notifier.error(context, function_name, payload) + + +def wrap_exception(notifier=None, get_notifier=None, binary=None): + """This decorator wraps a method to catch any exceptions that may + get thrown. It also optionally sends the exception to the notification + system. + """ + def inner(f): + def wrapped(self, context, *args, **kw): + # Don't store self or context in the payload, it now seems to + # contain confidential information. + try: + return f(self, context, *args, **kw) + except Exception as e: + with excutils.save_and_reraise_exception(): + if notifier or get_notifier: + call_dict = _get_call_dict( + f, self, context, *args, **kw) + function_name = f.__name__ + _emit_exception_notification( + notifier or get_notifier(), context, e, + function_name, call_dict, binary) + + return functools.wraps(f)(wrapped) + return inner + + +def _get_call_dict(function, self, context, *args, **kw): + wrapped_func = safe_utils.get_wrapped_function(function) + + call_dict = inspect.getcallargs(wrapped_func, self, + context, *args, **kw) + # self can't be serialized and shouldn't be in the + # payload + call_dict.pop('self', None) + return _cleanse_dict(call_dict) + + +def _cleanse_dict(original): + """Strip all admin_password, new_pass, rescue_pass keys from a dict.""" + return {k: v for k, v in six.iteritems(original) if "_pass" not in k} |