summaryrefslogtreecommitdiff
path: root/nova/hooks.py
diff options
context:
space:
mode:
authorAndrew Melton <andrew.melton@rackspace.com>2014-06-17 11:31:14 -0400
committerAndrew Melton <andrew.melton@rackspace.com>2014-06-17 15:37:36 -0400
commitcf6d43d774c265abd93022f273d55e24f4c3930a (patch)
tree1467b60b193b9c41ee49f8960e5de9ce38480709 /nova/hooks.py
parent25ea5f480d22e38d0d7f82f80fd651713d4b9211 (diff)
downloadnova-cf6d43d774c265abd93022f273d55e24f4c3930a.tar.gz
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
Diffstat (limited to 'nova/hooks.py')
-rw-r--r--nova/hooks.py43
1 files changed, 35 insertions, 8 deletions
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):