summaryrefslogtreecommitdiff
path: root/nova/safe_utils.py
diff options
context:
space:
mode:
authorAndrew Laski <andrew.laski@rackspace.com>2015-12-10 17:34:09 -0500
committerAndrew Laski <andrew.laski@rackspace.com>2015-12-11 10:11:08 -0500
commit1b757c328d43d8154282794fddb8822ea265b1cf (patch)
treef35451d3f4f3650b01edcefdf2bec3e0dd21035d /nova/safe_utils.py
parent2910d75b28afd909af3b4ac392729ac3d5e64b65 (diff)
downloadnova-1b757c328d43d8154282794fddb8822ea265b1cf.tar.gz
Fix wrap_exception to get all arguments for payload
The wrap_exception decorator that attempts to send a notification when exceptions occur was not sending all the arguments it was intending to. It relies on getcallargs to get the arguments and argument names for the called method but if the method has another decorator on it getcallargs pulls information for the decorator rather than the decorated method. This pulls the decorated method with get_wrapped_function and then calls getcallargs. get_wrapped_function was moved to safeutils because utils.py can't be imported by exception.py without a circular import. A few tests were updated to include the id on the instance object used. This was done because serialization of the object includes the instance.name field which assumes that id is set to populate the CONF.instance_name_template. When id is not set it triggers a lazy load which fails in the test environment. Change-Id: I87d8691a2aae6f3555177364f3c40a490a6f7591 Closes-bug: 1525282
Diffstat (limited to 'nova/safe_utils.py')
-rw-r--r--nova/safe_utils.py21
1 files changed, 21 insertions, 0 deletions
diff --git a/nova/safe_utils.py b/nova/safe_utils.py
index 2fad77b2a6..8fafdc0f70 100644
--- a/nova/safe_utils.py
+++ b/nova/safe_utils.py
@@ -49,3 +49,24 @@ def getcallargs(function, *args, **kwargs):
keyed_args[argname] = value
return keyed_args
+
+
+def get_wrapped_function(function):
+ """Get the method at the bottom of a stack of decorators."""
+ if not hasattr(function, '__closure__') or not function.__closure__:
+ return function
+
+ def _get_wrapped_function(function):
+ if not hasattr(function, '__closure__') or not function.__closure__:
+ return None
+
+ for closure in function.__closure__:
+ func = closure.cell_contents
+
+ deeper_func = _get_wrapped_function(func)
+ if deeper_func:
+ return deeper_func
+ elif hasattr(closure.cell_contents, '__call__'):
+ return closure.cell_contents
+
+ return _get_wrapped_function(function)