[Kimchi-devel] [PATCH V2 1/2] move RollbackContext from tests/utils to src/kimchi/rollbackcontext

shaohef at linux.vnet.ibm.com shaohef at linux.vnet.ibm.com
Tue Dec 31 11:55:14 UTC 2013


From: ShaoHe Feng <shaohef at linux.vnet.ibm.com>

Then kimchi source code can make use of it
Also add src/kimchi/rollbackcontext.py in dist list

Signed-off-by: Zhou Zheng Sheng <zhshzhou at linux.vnet.ibm.com>
Signed-off-by: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
---
 src/kimchi/Makefile.am        | 59 +++++++++++++++++------------------
 src/kimchi/rollbackcontext.py | 71 +++++++++++++++++++++++++++++++++++++++++++
 tests/test_model.py           | 25 +++++++--------
 tests/test_rest.py            |  3 +-
 tests/utils.py                | 45 ---------------------------
 5 files changed, 116 insertions(+), 87 deletions(-)
 create mode 100644 src/kimchi/rollbackcontext.py

diff --git a/src/kimchi/Makefile.am b/src/kimchi/Makefile.am
index 47a3bd2..2f05ab7 100644
--- a/src/kimchi/Makefile.am
+++ b/src/kimchi/Makefile.am
@@ -21,35 +21,36 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 kimchi_PYTHON = \
-	asynctask.py      \
-	auth.py           \
-	controller.py     \
-	disks.py          \
-	distroloader.py   \
-	exception.py      \
-	__init__.py       \
-	isoinfo.py        \
-	netinfo.py        \
-	network.py        \
-	networkxml.py     \
-	mockmodel.py      \
-	model.py          \
-	objectstore.py    \
-	osinfo.py         \
-	root.py           \
-	scan.py           \
-	screenshot.py     \
-	server.py         \
-	sslcert.py        \
-	template.py       \
-	vmtemplate.py     \
-	vnc.py            \
-	websocket.py      \
-	websockify.py     \
-	xmlutils.py       \
-	utils.py          \
-	cachebust.py      \
-	featuretests.py
+	__init__.py        \
+	asynctask.py       \
+	auth.py            \
+	cachebust.py       \
+	controller.py      \
+	disks.py           \
+	distroloader.py    \
+	exception.py       \
+	featuretests.py    \
+	isoinfo.py         \
+	mockmodel.py       \
+	model.py           \
+	netinfo.py         \
+	network.py         \
+	networkxml.py      \
+	objectstore.py     \
+	osinfo.py          \
+	rollbackcontext.py \
+	root.py            \
+	scan.py            \
+	screenshot.py      \
+	server.py          \
+	sslcert.py         \
+	template.py        \
+	utils.py           \
+	vmtemplate.py      \
+	vnc.py             \
+	websocket.py       \
+	websockify.py      \
+	xmlutils.py
 
 nodist_kimchi_PYTHON = config.py
 
diff --git a/src/kimchi/rollbackcontext.py b/src/kimchi/rollbackcontext.py
new file mode 100644
index 0000000..2afd114
--- /dev/null
+++ b/src/kimchi/rollbackcontext.py
@@ -0,0 +1,71 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Authors:
+#  Adam Litke <agl at linux.vnet.ibm.com>
+#  ShaoHe Feng <shaohef at linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+#
+
+import sys
+
+
+class RollbackContext(object):
+    '''
+    A context manager for recording and playing rollback.
+    The first exception will be remembered and re-raised after rollback
+
+    Sample usage:
+    with RollbackContext() as rollback:
+        step1()
+        rollback.prependDefer(lambda: undo step1)
+        def undoStep2(arg): pass
+        step2()
+        rollback.prependDefer(undoStep2, arg)
+    '''
+    def __init__(self, *args):
+        self._finally = []
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        firstException = exc_value
+
+        for undo, args, kwargs in self._finally:
+            try:
+                undo(*args, **kwargs)
+            except Exception as e:
+                # keep the earliest exception info
+                if not firstException:
+                    firstException = e
+                    # keep the original traceback info
+                    traceback = sys.exc_info()[2]
+
+        # re-raise the earliest exception
+        if firstException is not None:
+            if type(firstException) is str:
+                sys.stderr.write(firstException)
+            else:
+                raise firstException, None, traceback
+
+    def defer(self, func, *args, **kwargs):
+        self._finally.append((func, args, kwargs))
+
+    def prependDefer(self, func, *args, **kwargs):
+        self._finally.insert(0, (func, args, kwargs))
diff --git a/tests/test_model.py b/tests/test_model.py
index e19364f..7ecd8c6 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -38,6 +38,7 @@ import utils
 from kimchi import netinfo
 from kimchi.exception import InvalidOperation, InvalidParameter
 from kimchi.exception import NotFoundError, OperationFailed
+from kimchi.rollbackcontext import RollbackContext
 
 
 class ModelTests(unittest.TestCase):
@@ -72,7 +73,7 @@ class ModelTests(unittest.TestCase):
     def test_vm_lifecycle(self):
         inst = kimchi.model.Model(objstore_loc=self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             params = {'name': 'test', 'disks': []}
             inst.templates_create(params)
             rollback.prependDefer(inst.template_delete, 'test')
@@ -97,7 +98,7 @@ class ModelTests(unittest.TestCase):
     def test_vm_storage_provisioning(self):
         inst = kimchi.model.Model(objstore_loc=self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             params = {'name': 'test', 'disks': [{'size': 1}]}
             inst.templates_create(params)
             rollback.prependDefer(inst.template_delete, 'test')
@@ -115,7 +116,7 @@ class ModelTests(unittest.TestCase):
     def test_storagepool(self):
         inst = kimchi.model.Model('qemu:///system', self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             path = '/tmp/kimchi-images'
             name = 'test-pool'
             if not os.path.exists(path):
@@ -168,7 +169,7 @@ class ModelTests(unittest.TestCase):
     def test_storagevolume(self):
         inst = kimchi.model.Model('qemu:///system', self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             path = '/tmp/kimchi-images'
             pool = 'test-pool'
             vol = 'test-volume.img'
@@ -223,7 +224,7 @@ class ModelTests(unittest.TestCase):
     def test_template_storage_customise(self):
         inst = kimchi.model.Model(objstore_loc=self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             path = '/tmp/kimchi-images'
             pool = 'test-pool'
             if not os.path.exists(path):
@@ -295,7 +296,7 @@ class ModelTests(unittest.TestCase):
         orig_params = {'name': 'test', 'memory': '1024', 'cpus': '1'}
         inst.templates_create(orig_params)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             params_1 = {'name': 'kimchi-vm1', 'template': '/templates/test'}
             params_2 = {'name': 'kimchi-vm2', 'template': '/templates/test'}
             inst.vms_create(params_1)
@@ -326,7 +327,7 @@ class ModelTests(unittest.TestCase):
     def test_network(self):
         inst = kimchi.model.Model('qemu:///system', self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             name = 'test-network'
 
             networks = inst.networks_get_list()
@@ -480,7 +481,7 @@ class ModelTests(unittest.TestCase):
     def test_delete_running_vm(self):
         inst = kimchi.model.Model(objstore_loc=self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             params = {'name': u'test', 'disks': []}
             inst.templates_create(params)
             rollback.prependDefer(inst.template_delete, 'test')
@@ -501,7 +502,7 @@ class ModelTests(unittest.TestCase):
     def test_vm_list_sorted(self):
         inst = kimchi.model.Model(objstore_loc=self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             params = {'name': 'test', 'disks': []}
             inst.templates_create(params)
             rollback.prependDefer(inst.template_delete, 'test')
@@ -517,7 +518,7 @@ class ModelTests(unittest.TestCase):
     def test_use_test_host(self):
         inst = kimchi.model.Model('test:///default', objstore_loc=self.tmp_store)
 
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             params = {'name': 'test', 'disks': [],
                        'storagepool': '/storagepools/default-pool',
                        'domain': 'test',
@@ -546,7 +547,7 @@ class ModelTests(unittest.TestCase):
             inst.debugreport_delete(namePrefix + '*')
         except NotFoundError:
             pass
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             report_list = inst.debugreports_get_list()
             self.assertFalse(reportName in report_list)
             try:
@@ -617,7 +618,7 @@ class ModelTests(unittest.TestCase):
     @unittest.skipUnless(utils.running_as_root(), 'Must be run as root')
     def test_deep_scan(self):
         inst = kimchi.model.Model('qemu:///system', objstore_loc=self.tmp_store)
-        with utils.RollbackContext() as rollback:
+        with RollbackContext() as rollback:
             path = '/tmp/kimchi-images/tmpdir'
             if not os.path.exists(path):
                 os.makedirs(path)
diff --git a/tests/test_rest.py b/tests/test_rest.py
index 73946c0..1b7312f 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -33,8 +33,9 @@ from functools import partial
 import kimchi.mockmodel
 import kimchi.server
 from kimchi.asynctask import AsyncTask
+from kimchi.rollbackcontext import RollbackContext
 from utils import fake_user, get_free_port, https_request, patch_auth, request
-from utils import RollbackContext, run_server
+from utils import run_server
 
 
 test_server = None
diff --git a/tests/utils.py b/tests/utils.py
index a7596e8..960e0be 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -140,51 +140,6 @@ def https_request(host, port, path, data=None, method='GET', headers=None):
     return _request(conn, path, data, method, headers)
 
 
-class RollbackContext(object):
-    '''
-    A context manager for recording and playing rollback.
-    The first exception will be remembered and re-raised after rollback
-
-    Sample usage:
-    with RollbackContext() as rollback:
-        step1()
-        rollback.prependDefer(lambda: undo step1)
-        def undoStep2(arg): pass
-        step2()
-        rollback.prependDefer(undoStep2, arg)
-    '''
-    def __init__(self, *args):
-        self._finally = []
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_value, traceback):
-        firstException = exc_value
-
-        for undo, args, kwargs in self._finally:
-            try:
-                undo(*args, **kwargs)
-            except Exception as e:
-                # keep the earliest exception info
-                if not firstException:
-                    firstException = e
-                    # keep the original traceback info
-                    traceback = sys.exc_info()[2]
-
-        # re-raise the earliest exception
-        if firstException is not None:
-            if type(firstException) is str:
-                sys.stderr.write(firstException)
-            else:
-                raise firstException, None, traceback
-
-    def defer(self, func, *args, **kwargs):
-        self._finally.append((func, args, kwargs))
-
-    def prependDefer(self, func, *args, **kwargs):
-        self._finally.insert(0, (func, args, kwargs))
-
 def patch_auth():
     """
     Override the authenticate function with a simple test against an
-- 
1.8.4.2




More information about the Kimchi-devel mailing list