From cf6d43d774c265abd93022f273d55e24f4c3930a Mon Sep 17 00:00:00 2001 From: Andrew Melton Date: Tue, 17 Jun 2014 11:31:14 -0400 Subject: Enhance and test exception safety in hooks This patch adds exception handling when calling pre and post functions of hooks. Exceptions will be caught and logged, but the hook chain and function call will be allowed to proceed. Partially implements: bp instance-network-info-hook Change-Id: I45e76cd156c244ff57f77db103a9a579f14ad4f1 --- nova/hooks.py | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'nova/hooks.py') diff --git a/nova/hooks.py b/nova/hooks.py index adca138c21..d56455e2a1 100644 --- a/nova/hooks.py +++ b/nova/hooks.py @@ -46,6 +46,7 @@ import functools import stevedore +from nova.openstack.common.gettextutils import _LE from nova.openstack.common import log as logging LOG = logging.getLogger(__name__) @@ -54,6 +55,14 @@ NS = 'nova.hooks' _HOOKS = {} # hook name => hook manager +class FatalHookException(Exception): + """Exception which should be raised by hooks to indicate that normal + execution of the hooked function should be terminated. Raised exception + will be logged and reraised. + """ + pass + + class HookManager(stevedore.hook.HookManager): def __init__(self, name): # invoke_on_load creates an instance of the Hook class @@ -66,10 +75,19 @@ class HookManager(stevedore.hook.HookManager): if pre: LOG.debug("Running %(name)s pre-hook: %(obj)s", {'name': name, 'obj': obj}) - if f: - pre(f, *args, **kwargs) - else: - pre(*args, **kwargs) + try: + if f: + pre(f, *args, **kwargs) + else: + pre(*args, **kwargs) + except FatalHookException: + msg = _LE("Fatal Exception running %(name)s " + "pre-hook: %(obj)s") + LOG.exception(msg, {'name': name, 'obj': obj}) + raise + except Exception: + msg = _LE("Exception running %(name)s pre-hook: %(obj)s") + LOG.exception(msg, {'name': name, 'obj': obj}) def run_post(self, name, rv, args, kwargs, f=None): for e in reversed(self.extensions): @@ -78,10 +96,19 @@ class HookManager(stevedore.hook.HookManager): if post: LOG.debug("Running %(name)s post-hook: %(obj)s", {'name': name, 'obj': obj}) - if f: - post(f, rv, *args, **kwargs) - else: - post(rv, *args, **kwargs) + try: + if f: + post(f, rv, *args, **kwargs) + else: + post(rv, *args, **kwargs) + except FatalHookException: + msg = _LE("Fatal Exception running %(name)s " + "post-hook: %(obj)s") + LOG.exception(msg, {'name': name, 'obj': obj}) + raise + except Exception: + msg = _LE("Exception running %(name)s post-hook: %(obj)s") + LOG.exception(msg, {'name': name, 'obj': obj}) def add_hook(name, pass_function=False): -- cgit v1.2.1