summaryrefslogtreecommitdiffstats
path: root/nova/utils.py
diff options
context:
space:
mode:
authorRick Harris <rconradharris@gmail.com>2012-02-29 23:38:56 +0000
committerRick Harris <rconradharris@gmail.com>2012-03-01 22:13:03 -0600
commitc9aa0f57b6200313ea1f6c3839d65828024e2d37 (patch)
tree279ca8081e6fa7dbb0cf9603b565e7bcdf611a77 /nova/utils.py
parentd65a4e4023e9994c8a14a1da4aa4eeb4f6452640 (diff)
downloadnova-c9aa0f57b6200313ea1f6c3839d65828024e2d37.tar.gz
nova-c9aa0f57b6200313ea1f6c3839d65828024e2d37.tar.xz
nova-c9aa0f57b6200313ea1f6c3839d65828024e2d37.zip
Refactor spawn to use UndoManager.
UndoManager provides a mechanism for automatically rolling back on exceptions. An additional benefit of this approach is that undo code is spatially close to the roll-forward code. This patch should be considered an intermediate step towards a more complete Command pattern based approach down the road. Change-Id: Ib429420d67324422a5d13cdea6872fd9c57c857e
Diffstat (limited to 'nova/utils.py')
-rw-r--r--nova/utils.py26
1 files changed, 26 insertions, 0 deletions
diff --git a/nova/utils.py b/nova/utils.py
index a224b3878..0ea6ee93b 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -1582,3 +1582,29 @@ def strcmp_const_time(s1, s2):
for (a, b) in zip(s1, s2):
result |= ord(a) ^ ord(b)
return result == 0
+
+
+class UndoManager(object):
+ """Provides a mechanism to facilitate rolling back a series of actions
+ when an exception is raised.
+ """
+ def __init__(self):
+ self.undo_stack = []
+
+ def undo_with(self, undo_func):
+ self.undo_stack.append(undo_func)
+
+ def _rollback(self):
+ for undo_func in reversed(self.undo_stack):
+ undo_func()
+
+ def rollback_and_reraise(self, msg=None):
+ """Rollback a series of actions then re-raise the exception.
+
+ NOTE(sirp): This should only be called within an exception handler.
+ """
+ with save_and_reraise_exception():
+ if msg:
+ LOG.exception(msg)
+
+ self._rollback()