summaryrefslogtreecommitdiffstats
path: root/nova/utils.py
diff options
context:
space:
mode:
authorAndrew Laski <andrew.laski@rackspace.com>2013-01-15 17:24:49 -0500
committerAndrew Laski <andrew.laski@rackspace.com>2013-02-01 14:38:42 -0500
commit250230b32364b1e36ae6d62ec4bb8c3285c59401 (patch)
tree0a4c6a6c3b1dc15b48a0fd12d43be40df1d79cb6 /nova/utils.py
parentc421d775ee3052d1af4c08b8ff81f6877ca8b1a8 (diff)
downloadnova-250230b32364b1e36ae6d62ec4bb8c3285c59401.tar.gz
nova-250230b32364b1e36ae6d62ec4bb8c3285c59401.tar.xz
nova-250230b32364b1e36ae6d62ec4bb8c3285c59401.zip
Record instance actions and events
Record when an action is initiated on an instance, and the underlying events related to completing that action. Actions will typically occur at the API level and should match what a user intended to do with an instance. Events will typically track what happens behind the scenes and may include things that would be unclear for a user if exposed, but should be beneficial to an admin/deployer. Adds a new wrapper to the compute manager. The wrapper will record when an event begins and finishes from the point of view of the compute manager. It will also record errors if they occur. Blueprint instance-actions Change-Id: I801f3e796d091e146413f84c2ccfab95ad2e1af4
Diffstat (limited to 'nova/utils.py')
-rw-r--r--nova/utils.py54
1 files changed, 54 insertions, 0 deletions
diff --git a/nova/utils.py b/nova/utils.py
index 83bf55583..21b670e8b 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -1293,3 +1293,57 @@ def metadata_to_dict(metadata):
for item in metadata:
result[item['key']] = item['value']
return result
+
+
+def get_wrapped_function(function):
+ """Get the method at the bottom of a stack of decorators."""
+ if not hasattr(function, 'func_closure') or not function.func_closure:
+ return function
+
+ def _get_wrapped_function(function):
+ if not hasattr(function, 'func_closure') or not function.func_closure:
+ return None
+
+ for closure in function.func_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)
+
+
+def getcallargs(function, *args, **kwargs):
+ """This is a simplified inspect.getcallargs (2.7+).
+
+ It should be replaced when python >= 2.7 is standard.
+ """
+ keyed_args = {}
+ argnames, varargs, keywords, defaults = inspect.getargspec(function)
+
+ keyed_args.update(kwargs)
+
+ #NOTE(alaski) the implicit 'self' or 'cls' argument shows up in
+ # argnames but not in args or kwargs. Uses 'in' rather than '==' because
+ # some tests use 'self2'.
+ if 'self' in argnames[0] or 'cls' == argnames[0]:
+ # The function may not actually be a method or have im_self.
+ # Typically seen when it's stubbed with mox.
+ if inspect.ismethod(function) and hasattr(function, 'im_self'):
+ keyed_args[argnames[0]] = function.im_self
+ else:
+ keyed_args[argnames[0]] = None
+
+ remaining_argnames = filter(lambda x: x not in keyed_args, argnames)
+ keyed_args.update(dict(zip(remaining_argnames, args)))
+
+ if defaults:
+ num_defaults = len(defaults)
+ for argname, value in zip(argnames[-num_defaults:], defaults):
+ if argname not in keyed_args:
+ keyed_args[argname] = value
+
+ return keyed_args