]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
RBD unit test improvements
authorEdward Hope-Morley <edward.hope-morley@canonical.com>
Wed, 5 Feb 2014 17:42:53 +0000 (17:42 +0000)
committerEdward Hope-Morley <edward.hope-morley@canonical.com>
Wed, 5 Feb 2014 23:13:57 +0000 (23:13 +0000)
This commit brings the implementation of the test_rbd and
test_backup_ceph unit tests more inline and tries to ensure
that no mock is set without being unset so as not to tread
on the toes of any other tests.

Change-Id: Ibb6bd3bf90952914512e3fa39fd216f43f0f8ecb
Closes-bug: 1276657

cinder/tests/test_backup_ceph.py
cinder/tests/test_rbd.py

index ae76ef949f91f621bae58e10de37916ed56f52e0..2545519c64cb8cd702b27d5a5c352c657d6a89ca 100644 (file)
 #    under the License.
 """ Tests for Ceph backup service."""
 
-import eventlet
-import fcntl
 import hashlib
 import mock
 import os
-import subprocess
 import tempfile
-import time
 import uuid
 
 from cinder.backup.drivers import ceph
@@ -36,58 +32,24 @@ from cinder.volume.drivers import rbd as rbddriver
 
 LOG = logging.getLogger(__name__)
 
+# This is used to collect raised exceptions so that tests may check what was
+# raised.
+# NOTE: this must be initialised in test setUp().
+RAISED_EXCEPTIONS = []
 
-class ImageNotFound(Exception):
-    _called = False
 
-    def __init__(self, *args, **kwargs):
-        self.__class__._called = True
-
-    @classmethod
-    def called(cls):
-        ret = cls._called
-        cls._called = False
-        return ret
-
-
-class ImageBusy(Exception):
-    _called = False
+class MockException(Exception):
 
     def __init__(self, *args, **kwargs):
-        self.__class__._called = True
-
-    @classmethod
-    def called(cls):
-        ret = cls._called
-        cls._called = False
-        return ret
-
-
-def common_backup_mocks(f):
-    """Decorator to set mocks common to all backup tests.
-    """
-    def _common_backup_mocks_inner(inst, *args, **kwargs):
-        inst.service.rbd.Image.size = mock.Mock()
-        inst.service.rbd.Image.size.return_value = \
-            inst.chunk_size * inst.num_chunks
+        RAISED_EXCEPTIONS.append(self.__class__)
 
-        with mock.patch.object(inst.service, '_get_rbd_support') as \
-                mock_rbd_support:
-            mock_rbd_support.return_value = (True, 3)
-            with mock.patch.object(inst.service, 'get_backup_snaps'):
-                return f(inst, *args, **kwargs)
 
-    return _common_backup_mocks_inner
+class MockImageNotFoundException(MockException):
+    """Used as mock for rbd.ImageNotFound."""
 
 
-def common_restore_mocks(f):
-    """Decorator to set mocks common to all restore tests.
-    """
-    @common_backup_mocks
-    def _common_restore_mocks_inner(inst, *args, **kwargs):
-        return f(inst, *args, **kwargs)
-
-    return _common_restore_mocks_inner
+class MockImageBusyException(MockException):
+    """Used as mock for rbd.ImageBusy."""
 
 
 def common_mocks(f):
@@ -97,9 +59,20 @@ def common_mocks(f):
     mocks that can't/dont't get unset.
     """
     def _common_inner_inner1(inst, *args, **kwargs):
+        # NOTE(dosaboy): mock Popen to, by default, raise Exception in order to
+        #                ensure that any test ending up in a subprocess fails
+        #                if not properly mocked.
+        @mock.patch('subprocess.Popen')
+        # NOTE(dosaboy): mock out eventlet.sleep() so that it does nothing.
+        @mock.patch('eventlet.sleep')
+        @mock.patch('time.time')
         @mock.patch('cinder.backup.drivers.ceph.rbd')
         @mock.patch('cinder.backup.drivers.ceph.rados')
-        def _common_inner_inner2(mock_rados, mock_rbd):
+        def _common_inner_inner2(mock_rados, mock_rbd, mock_time, mock_sleep,
+                                 mock_popen):
+            mock_time.side_effect = inst.time_inc
+            mock_popen.side_effect = Exception
+
             inst.mock_rados = mock_rados
             inst.mock_rbd = mock_rbd
             inst.mock_rados.Rados = mock.Mock
@@ -107,23 +80,15 @@ def common_mocks(f):
             inst.mock_rbd.RBD = mock.Mock
             inst.mock_rbd.Image = mock.Mock
             inst.mock_rbd.Image.close = mock.Mock()
-            inst.mock_rbd.ImageBusy = ImageBusy
-            inst.mock_rbd.ImageNotFound = ImageNotFound
+            inst.mock_rbd.ImageBusy = MockImageBusyException
+            inst.mock_rbd.ImageNotFound = MockImageNotFoundException
 
             inst.service.rbd = inst.mock_rbd
             inst.service.rados = inst.mock_rados
-
-            with mock.patch.object(time, 'time') as mock_time:
-                mock_time.side_effect = inst.time_inc
-                with mock.patch.object(eventlet, 'sleep'):
-                    # Mock Popen to raise Exception in order to ensure that any
-                    # test ending up in a subprocess fails if not properly
-                    # mocked.
-                    with mock.patch.object(subprocess, 'Popen') as mock_popen:
-                        mock_popen.side_effect = Exception
-                        return f(inst, *args, **kwargs)
+            return f(inst, *args, **kwargs)
 
         return _common_inner_inner2()
+
     return _common_inner_inner1
 
 
@@ -171,6 +136,8 @@ class BackupCephTestCase(test.TestCase):
         mock_popen.side_effect = MockPopen
 
     def setUp(self):
+        global RAISED_EXCEPTIONS
+        RAISED_EXCEPTIONS = []
         super(BackupCephTestCase, self).setUp()
         self.ctxt = context.get_admin_context()
 
@@ -303,7 +270,6 @@ class BackupCephTestCase(test.TestCase):
         self.assertEqual(len(snaps), 3)
 
     @common_mocks
-    @common_backup_mocks
     def test_transfer_data_from_rbd_to_file(self):
         self.mock_rbd.Image.read = mock.Mock()
         self.mock_rbd.Image.read.return_value = \
@@ -358,7 +324,6 @@ class BackupCephTestCase(test.TestCase):
             self.assertEqual(checksum.digest(), self.checksum.digest())
 
     @common_mocks
-    @common_backup_mocks
     def test_transfer_data_from_file_to_rbd(self):
 
         def mock_write_data(data, offset):
@@ -380,7 +345,6 @@ class BackupCephTestCase(test.TestCase):
             self.assertEqual(checksum.digest(), self.checksum.digest())
 
     @common_mocks
-    @common_backup_mocks
     def test_transfer_data_from_file_to_file(self):
         with tempfile.NamedTemporaryFile() as test_file:
             self.volume_file.seek(0)
@@ -398,8 +362,8 @@ class BackupCephTestCase(test.TestCase):
             self.assertEqual(checksum.digest(), self.checksum.digest())
 
     @common_mocks
-    @common_backup_mocks
     def test_backup_volume_from_file(self):
+        checksum = hashlib.sha256()
 
         def mock_write_data(data, offset):
             checksum.update(data)
@@ -410,13 +374,13 @@ class BackupCephTestCase(test.TestCase):
 
         with mock.patch.object(self.service, '_discard_bytes'):
             with tempfile.NamedTemporaryFile() as test_file:
-                checksum = hashlib.sha256()
-
                 self.service.backup(self.backup, self.volume_file)
 
                 # Ensure the files are equal
                 self.assertEqual(checksum.digest(), self.checksum.digest())
 
+        self.assertTrue(self.service.rbd.Image.write.called)
+
     @common_mocks
     def test_get_backup_base_name(self):
         name = self.service._get_backup_base_name(self.volume_id,
@@ -432,9 +396,9 @@ class BackupCephTestCase(test.TestCase):
                          "volume-%s.backup.%s" % (self.volume_id, '1234'))
 
     @common_mocks
-    @common_backup_mocks
+    @mock.patch('fcntl.fcntl')
     @mock.patch('subprocess.Popen')
-    def test_backup_volume_from_rbd(self, mock_popen):
+    def test_backup_volume_from_rbd(self, mock_popen, mock_fnctl):
         backup_name = self.service._get_backup_base_name(self.backup_id,
                                                          diff_format=True)
 
@@ -457,8 +421,10 @@ class BackupCephTestCase(test.TestCase):
         self.mock_rbd.RBD.list = mock.Mock()
         self.mock_rbd.RBD.list.return_value = [backup_name]
 
-        with mock.patch.object(fcntl, 'fcntl'):
-            with mock.patch.object(self.service, '_discard_bytes'):
+        with mock.patch.object(self.service, 'get_backup_snaps') as \
+                mock_get_backup_snaps:
+            with mock.patch.object(self.service, '_full_backup') as \
+                    mock_full_backup:
                 with mock.patch.object(self.service, '_try_delete_base_image'):
                     with tempfile.NamedTemporaryFile() as test_file:
                         checksum = hashlib.sha256()
@@ -467,9 +433,8 @@ class BackupCephTestCase(test.TestCase):
                                                           'pool_foo',
                                                           'user_foo',
                                                           'conf_foo')
-                        rbd_io = rbddriver.RBDImageIOWrapper(meta)
-
-                        self.service.backup(self.backup, rbd_io)
+                        self.service.backup(self.backup,
+                                            rbddriver.RBDImageIOWrapper(meta))
 
                         self.assertEqual(self.callstack, ['popen_init',
                                                           'read',
@@ -478,12 +443,14 @@ class BackupCephTestCase(test.TestCase):
                                                           'stdout_close',
                                                           'communicate'])
 
+                        self.assertFalse(mock_full_backup.called)
+                        self.assertTrue(mock_get_backup_snaps.called)
+
                         # Ensure the files are equal
                         self.assertEqual(checksum.digest(),
                                          self.checksum.digest())
 
     @common_mocks
-    @common_backup_mocks
     def test_backup_vol_length_0(self):
         volume_id = str(uuid.uuid4())
         self._create_volume_db_entry(volume_id, 0)
@@ -497,7 +464,6 @@ class BackupCephTestCase(test.TestCase):
                           backup, self.volume_file)
 
     @common_mocks
-    @common_restore_mocks
     def test_restore(self):
         backup_name = self.service._get_backup_base_name(self.backup_id,
                                                          diff_format=True)
@@ -511,7 +477,8 @@ class BackupCephTestCase(test.TestCase):
         self.mock_rbd.Image.read = mock.Mock()
         self.mock_rbd.Image.read.side_effect = mock_read_data
 
-        with mock.patch.object(self.service, '_discard_bytes'):
+        with mock.patch.object(self.service, '_discard_bytes') as \
+                mock_discard_bytes:
             with tempfile.NamedTemporaryFile() as test_file:
                 self.volume_file.seek(0)
 
@@ -525,6 +492,10 @@ class BackupCephTestCase(test.TestCase):
                 # Ensure the files are equal
                 self.assertEqual(checksum.digest(), self.checksum.digest())
 
+            self.assertTrue(mock_discard_bytes.called)
+
+        self.assertTrue(self.service.rbd.Image.read.called)
+
     @common_mocks
     def test_discard_bytes(self):
         self.mock_rbd.Image.discard = mock.Mock()
@@ -540,6 +511,7 @@ class BackupCephTestCase(test.TestCase):
         self.mock_rbd.Image.write = mock.Mock()
         self.mock_rbd.Image.flush = mock.Mock()
 
+        # Test discard with no remainder
         with mock.patch.object(self.service, '_file_is_rbd') as \
                 mock_file_is_rbd:
             mock_file_is_rbd.return_value = False
@@ -553,7 +525,9 @@ class BackupCephTestCase(test.TestCase):
 
         self.mock_rbd.Image.write.reset_mock()
         self.mock_rbd.Image.flush.reset_mock()
+        self.mock_rbd.Image.discard.reset_mock()
 
+        # Now test with a remainder.
         with mock.patch.object(self.service, '_file_is_rbd') as \
                 mock_file_is_rbd:
             mock_file_is_rbd.return_value = False
@@ -631,20 +605,22 @@ class BackupCephTestCase(test.TestCase):
         self.mock_rbd.RBD.remove = mock.Mock()
         self.mock_rbd.RBD.remove.side_effect = self.mock_rbd.ImageBusy
 
-        with mock.patch.object(self.service, 'get_backup_snaps'):
+        with mock.patch.object(self.service, 'get_backup_snaps') as \
+                mock_get_backup_snaps:
             self.assertRaises(self.mock_rbd.ImageBusy,
                               self.service._try_delete_base_image,
                               self.backup['id'], self.backup['volume_id'])
+            self.assertTrue(mock_get_backup_snaps.called)
 
-            self.assertTrue(self.mock_rbd.RBD.list.called)
-            self.assertTrue(self.mock_rbd.RBD.remove.called)
-            self.assertTrue(self.mock_rbd.ImageBusy.called())
+        self.assertTrue(self.mock_rbd.RBD.list.called)
+        self.assertTrue(self.mock_rbd.RBD.remove.called)
+        self.assertTrue(MockImageBusyException in RAISED_EXCEPTIONS)
 
     @common_mocks
     def test_delete(self):
         with mock.patch.object(self.service, '_try_delete_base_image'):
             self.service.delete(self.backup)
-            self.assertFalse(self.mock_rbd.ImageNotFound.called())
+            self.assertEqual(RAISED_EXCEPTIONS, [])
 
     @common_mocks
     def test_delete_image_not_found(self):
@@ -653,7 +629,7 @@ class BackupCephTestCase(test.TestCase):
             mock_del_base.side_effect = self.mock_rbd.ImageNotFound
             # ImageNotFound exception is caught so that db entry can be cleared
             self.service.delete(self.backup)
-            self.assertTrue(self.mock_rbd.ImageNotFound.called())
+            self.assertEqual(RAISED_EXCEPTIONS, [MockImageNotFoundException])
 
     @common_mocks
     def test_diff_restore_allowed_true(self):
@@ -665,15 +641,16 @@ class BackupCephTestCase(test.TestCase):
         self.mock_rbd.Image.size = mock.Mock()
         self.mock_rbd.Image.size.return_value = self.volume_size * units.GiB
 
-        mpo = mock.patch.object
-        with mpo(self.service, '_get_restore_point') as mock_restore_point:
+        with mock.patch.object(self.service, '_get_restore_point') as \
+                mock_restore_point:
             mock_restore_point.return_value = restore_point
-            with mpo(self.service, '_rbd_has_extents') as mock_rbd_has_extents:
+            with mock.patch.object(self.service, '_rbd_has_extents') as \
+                    mock_rbd_has_extents:
                 mock_rbd_has_extents.return_value = False
-                with mpo(self.service, '_rbd_image_exists') as \
+                with mock.patch.object(self.service, '_rbd_image_exists') as \
                         mock_rbd_image_exists:
                     mock_rbd_image_exists.return_value = (True, 'foo')
-                    with mpo(self.service, '_file_is_rbd') as \
+                    with mock.patch.object(self.service, '_file_is_rbd') as \
                             mock_file_is_rbd:
                         mock_file_is_rbd.return_value = True
 
@@ -761,11 +738,11 @@ class BackupCephTestCase(test.TestCase):
                         self.assertTrue(mock_rbd_has_extents.called)
 
     @common_mocks
+    @mock.patch('fcntl.fcntl')
     @mock.patch('subprocess.Popen')
-    def test_piped_execute(self, mock_popen):
-        with mock.patch.object(fcntl, 'fcntl') as mock_fcntl:
-            mock_fcntl.return_value = 0
-            self._setup_mock_popen(mock_popen, ['out', 'err'])
-            self.service._piped_execute(['foo'], ['bar'])
-            self.assertEqual(self.callstack, ['popen_init', 'popen_init',
-                                              'stdout_close', 'communicate'])
+    def test_piped_execute(self, mock_popen, mock_fcntl):
+        mock_fcntl.return_value = 0
+        self._setup_mock_popen(mock_popen, ['out', 'err'])
+        self.service._piped_execute(['foo'], ['bar'])
+        self.assertEqual(self.callstack, ['popen_init', 'popen_init',
+                                          'stdout_close', 'communicate'])
index 4c80863f4e6f11858a5e0599e58b579cd0db6d7a..c9baa64a6102d4a21ebf1eadf21121e63f254790 100644 (file)
@@ -37,6 +37,62 @@ from cinder.volume.flows.manager import create_volume
 LOG = logging.getLogger(__name__)
 
 
+# This is used to collect raised exceptions so that tests may check what was
+# raised.
+# NOTE: this must be initialised in test setUp().
+RAISED_EXCEPTIONS = []
+
+
+class MockException(Exception):
+
+    def __init__(self, *args, **kwargs):
+        RAISED_EXCEPTIONS.append(self.__class__)
+
+
+class MockImageNotFoundException(MockException):
+    """Used as mock for rbd.ImageNotFound."""
+
+
+class MockImageBusyException(MockException):
+    """Used as mock for rbd.ImageBusy."""
+
+
+def common_mocks(f):
+    """Decorator to set mocks common to all tests.
+
+    The point of doing these mocks here is so that we don't accidentally set
+    mocks that can't/dont't get unset.
+    """
+    def _common_inner_inner1(inst, *args, **kwargs):
+        @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy')
+        @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
+        @mock.patch('cinder.backup.drivers.ceph.rbd')
+        @mock.patch('cinder.backup.drivers.ceph.rados')
+        def _common_inner_inner2(mock_rados, mock_rbd, mock_client,
+                                 mock_proxy):
+            inst.mock_rbd = mock_rbd
+            inst.mock_rados = mock_rados
+            inst.mock_client = mock_client
+            inst.mock_proxy = mock_proxy
+            inst.mock_rados.Rados = mock.Mock
+            inst.mock_rados.Rados.ioctx = mock.Mock()
+            inst.mock_rbd.RBD = mock.Mock
+            inst.mock_rbd.Image = mock.Mock
+            inst.mock_rbd.Image.close = mock.Mock()
+            inst.mock_rbd.RBD.Error = Exception
+            inst.mock_rados.Error = Exception
+            inst.mock_rbd.ImageBusy = MockImageBusyException
+            inst.mock_rbd.ImageNotFound = MockImageNotFoundException
+
+            inst.driver.rbd = inst.mock_rbd
+            inst.driver.rados = inst.mock_rados
+            return f(inst, *args, **kwargs)
+
+        return _common_inner_inner2()
+
+    return _common_inner_inner1
+
+
 CEPH_MON_DUMP = """dumped monmap epoch 1
 { "epoch": 1,
   "fsid": "33630410-6d93-4d66-8e42-3b953cf194aa",
@@ -77,6 +133,8 @@ class TestUtil(test.TestCase):
 class RBDTestCase(test.TestCase):
 
     def setUp(self):
+        global RAISED_EXCEPTIONS
+        RAISED_EXCEPTIONS = []
         super(RBDTestCase, self).setUp()
 
         self.cfg = mock.Mock(spec=conf.Configuration)
@@ -87,21 +145,11 @@ class RBDTestCase(test.TestCase):
         self.cfg.rbd_user = None
         self.cfg.volume_dd_blocksize = '1M'
 
-        # set some top level mocks for these common modules and tests can then
-        # set method/attributes as required.
-        self.rados = mock.Mock()
-        self.rbd = mock.Mock()
-        self.rbd.RBD = mock.Mock
-        self.rbd.Image = mock.Mock
-        self.rbd.ImageSnapshot = mock.Mock
-
         mock_exec = mock.Mock()
         mock_exec.return_value = ('', '')
 
         self.driver = driver.RBDDriver(execute=mock_exec,
-                                       configuration=self.cfg,
-                                       rados=self.rados,
-                                       rbd=self.rbd)
+                                       configuration=self.cfg)
         self.driver.set_initialized()
 
         self.volume_name = u'volume-00000001'
@@ -114,53 +162,51 @@ class RBDTestCase(test.TestCase):
     def tearDown(self):
         super(RBDTestCase, self).tearDown()
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_create_volume(self, mock_client):
-        client = mock_client.return_value
+    @common_mocks
+    def test_create_volume(self):
+        client = self.mock_client.return_value
         client.__enter__.return_value = client
 
-        self.driver._supports_layering = mock.Mock()
-        self.driver._supports_layering.return_value = True
-        self.rbd.RBD.create = mock.Mock()
-
-        self.driver.create_volume(self.volume)
-
-        args = [client.ioctx, str(self.volume_name),
-                self.volume_size * units.GiB]
-        kwargs = {'old_format': False,
-                  'features': self.rbd.RBD_FEATURE_LAYERING}
-
-        self.rbd.RBD.create.assert_called_once()
-        client.__enter__.assert_called_once()
-        client.__exit__.assert_called_once()
-        self.driver._supports_layering.assert_called_once()
-        self.rbd.RBD.create.assert_called_once_with(*args, **kwargs)
-
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_create_volume_no_layering(self, mock_client):
-        client = mock_client.return_value
+        with mock.patch.object(self.driver, '_supports_layering') as \
+                mock_supports_layering:
+            mock_supports_layering.return_value = True
+            self.mock_rbd.RBD.create = mock.Mock()
+
+            self.driver.create_volume(self.volume)
+
+            args = [client.ioctx, str(self.volume_name),
+                    self.volume_size * units.GiB]
+            kwargs = {'old_format': False,
+                      'features': self.mock_rbd.RBD_FEATURE_LAYERING}
+            self.mock_rbd.RBD.create.assert_called_once_with(*args, **kwargs)
+            client.__enter__.assert_called_once()
+            client.__exit__.assert_called_once()
+            mock_supports_layering.assert_called_once()
+
+    @common_mocks
+    def test_create_volume_no_layering(self):
+        client = self.mock_client.return_value
         client.__enter__.return_value = client
 
-        self.driver._supports_layering = mock.Mock()
-        self.driver._supports_layering.return_value = False
-        self.rbd.RBD.create = mock.Mock()
-
-        self.driver.create_volume(self.volume)
+        with mock.patch.object(self.driver, '_supports_layering') as \
+                mock_supports_layering:
+            mock_supports_layering.return_value = False
+            self.mock_rbd.RBD.create = mock.Mock()
 
-        args = [client.ioctx, str(self.volume_name),
-                self.volume_size * units.GiB]
-        kwargs = {'old_format': True,
-                  'features': 0}
+            self.driver.create_volume(self.volume)
 
-        self.rbd.RBD.create.assert_called_once()
-        client.__enter__.assert_called_once()
-        client.__exit__.assert_called_once()
-        self.driver._supports_layering.assert_called_once()
-        self.rbd.RBD.create.assert_called_once_with(*args, **kwargs)
+            args = [client.ioctx, str(self.volume_name),
+                    self.volume_size * units.GiB]
+            kwargs = {'old_format': True,
+                      'features': 0}
+            self.mock_rbd.RBD.create.assert_called_once_with(*args, **kwargs)
+            client.__enter__.assert_called_once()
+            client.__exit__.assert_called_once()
+            mock_supports_layering.assert_called_once()
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_delete_volume(self, mock_client):
-        client = mock_client.return_value
+    @common_mocks
+    def test_delete_volume(self):
+        client = self.mock_client.return_value
 
         self.driver.rbd.Image.list_snaps = mock.Mock()
         self.driver.rbd.Image.list_snaps.return_value = []
@@ -168,60 +214,62 @@ class RBDTestCase(test.TestCase):
         self.driver.rbd.Image.remove = mock.Mock()
         self.driver.rbd.Image.unprotect_snap = mock.Mock()
 
-        self.driver._get_clone_info = mock.Mock()
-        self.driver._get_clone_info.return_value = (None, None, None)
-        self.driver._delete_backup_snaps = mock.Mock()
-
-        self.driver.delete_volume(self.volume)
-
-        self.driver._get_clone_info.assert_called_once()
-        self.driver.rbd.Image.list_snaps.assert_called_once()
-        client.__enter__.assert_called_once()
-        client.__exit__.assert_called_once()
-        self.driver._delete_backup_snaps.assert_called_once()
-        self.assertFalse(self.driver.rbd.Image.unprotect_snap.called)
-        self.driver.rbd.RBD.remove.assert_called_once()
-
-    @mock.patch('cinder.volume.drivers.rbd.rbd')
-    def test_delete_volume_not_found(self, mock_rbd):
-        mock_rbd.RBD = mock.Mock
-        mock_rbd.ImageNotFound = Exception
-        mock_rbd.Image.side_effect = mock_rbd.ImageNotFound
-
-        self.driver.rbd = mock_rbd
-
-        with mock.patch.object(driver, 'RADOSClient'):
-            self.assertIsNone(self.driver.delete_volume(self.volume))
-            mock_rbd.Image.assert_called_once()
-
+        with mock.patch.object(self.driver, '_get_clone_info') as \
+                mock_get_clone_info:
+            with mock.patch.object(self.driver, '_delete_backup_snaps') as \
+                    mock_delete_backup_snaps:
+                mock_get_clone_info.return_value = (None, None, None)
+
+                self.driver.delete_volume(self.volume)
+
+                mock_get_clone_info.assert_called_once()
+                self.driver.rbd.Image.list_snaps.assert_called_once()
+                client.__enter__.assert_called_once()
+                client.__exit__.assert_called_once()
+                mock_delete_backup_snaps.assert_called_once()
+                self.assertFalse(self.driver.rbd.Image.unprotect_snap.called)
+                self.driver.rbd.RBD.remove.assert_called_once()
+
+    @common_mocks
+    def delete_volume_not_found(self):
+        self.mock_rbd.Image.side_effect = self.mock_rbd.ImageNotFound
+        self.assertIsNone(self.driver.delete_volume(self.volume))
+        self.mock_rbd.Image.assert_called_once()
+        # Make sure the exception was raised
+        self.assertEqual(RAISED_EXCEPTIONS, [self.mock_rbd.ImageNotFound])
+
+    @common_mocks
     def test_delete_busy_volume(self):
-        self.rbd.Image.close = mock.Mock()
-        self.rbd.Image.list_snaps = mock.Mock()
-        self.rbd.Image.list_snaps.return_value = []
-        self.rbd.Image.unprotect_snap = mock.Mock()
-
-        self.rbd.ImageBusy = Exception
-        self.rbd.RBD.remove = mock.Mock()
-        self.rbd.RBD.remove.side_effect = self.rbd.ImageBusy
-
-        self.driver._get_clone_info = mock.Mock()
-        self.driver._get_clone_info.return_value = (None, None, None)
-        self.driver._delete_backup_snaps = mock.Mock()
-
-        with mock.patch.object(driver, 'RADOSClient') as mock_rados_client:
-            self.assertRaises(exception.VolumeIsBusy,
-                              self.driver.delete_volume, self.volume)
-
-            self.driver._get_clone_info.assert_called_once()
-            self.rbd.Image.list_snaps.assert_called_once()
-            mock_rados_client.assert_called_once()
-            self.driver._delete_backup_snaps.assert_called_once()
-            self.assertFalse(self.rbd.Image.unprotect_snap.called)
-            self.rbd.RBD.remove.assert_called_once()
-
-    @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy')
-    def test_create_snapshot(self, mock_proxy):
-        proxy = mock_proxy.return_value
+        self.mock_rbd.Image.list_snaps = mock.Mock()
+        self.mock_rbd.Image.list_snaps.return_value = []
+        self.mock_rbd.Image.unprotect_snap = mock.Mock()
+
+        self.mock_rbd.RBD.remove = mock.Mock()
+        self.mock_rbd.RBD.remove.side_effect = self.mock_rbd.ImageBusy
+
+        with mock.patch.object(self.driver, '_get_clone_info') as \
+                mock_get_clone_info:
+            mock_get_clone_info.return_value = (None, None, None)
+            with mock.patch.object(self.driver, '_delete_backup_snaps') as \
+                    mock_delete_backup_snaps:
+                with mock.patch.object(driver, 'RADOSClient') as \
+                        mock_rados_client:
+                    self.assertRaises(exception.VolumeIsBusy,
+                                      self.driver.delete_volume, self.volume)
+
+                    mock_get_clone_info.assert_called_once()
+                    self.mock_rbd.Image.list_snaps.assert_called_once()
+                    mock_rados_client.assert_called_once()
+                    mock_delete_backup_snaps.assert_called_once()
+                    self.assertFalse(self.mock_rbd.Image.unprotect_snap.called)
+                    self.mock_rbd.RBD.remove.assert_called_once()
+                    # Make sure the exception was raised
+                    self.assertEqual(RAISED_EXCEPTIONS,
+                                     [self.mock_rbd.ImageBusy])
+
+    @common_mocks
+    def test_create_snapshot(self):
+        proxy = self.mock_proxy.return_value
         proxy.__enter__.return_value = proxy
 
         self.driver.create_snapshot(self.snapshot)
@@ -230,9 +278,9 @@ class RBDTestCase(test.TestCase):
         proxy.create_snap.assert_called_with(*args)
         proxy.protect_snap.assert_called_with(*args)
 
-    @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy')
-    def test_delete_snapshot(self, mock_proxy):
-        proxy = mock_proxy.return_value
+    @common_mocks
+    def test_delete_snapshot(self):
+        proxy = self.mock_proxy.return_value
         proxy.__enter__.return_value = proxy
 
         self.driver.delete_snapshot(self.snapshot)
@@ -241,9 +289,9 @@ class RBDTestCase(test.TestCase):
         proxy.remove_snap.assert_called_with(*args)
         proxy.unprotect_snap.assert_called_with(*args)
 
+    @common_mocks
     def test_get_clone_info(self):
-
-        volume = self.rbd.Image()
+        volume = self.mock_rbd.Image()
         volume.set_snap = mock.Mock()
         volume.parent_info = mock.Mock()
         parent_info = ('a', 'b', '%s.clone_snap' % (self.volume_name))
@@ -256,15 +304,15 @@ class RBDTestCase(test.TestCase):
         self.assertFalse(volume.set_snap.called)
         volume.parent_info.assert_called_once()
 
+    @common_mocks
     def test_get_clone_info_w_snap(self):
-
-        volume = self.rbd.Image()
+        volume = self.mock_rbd.Image()
         volume.set_snap = mock.Mock()
         volume.parent_info = mock.Mock()
         parent_info = ('a', 'b', '%s.clone_snap' % (self.volume_name))
         volume.parent_info.return_value = parent_info
 
-        snapshot = self.rbd.ImageSnapshot()
+        snapshot = self.mock_rbd.ImageSnapshot()
 
         info = self.driver._get_clone_info(volume, self.volume_name,
                                            snap=snapshot)
@@ -275,16 +323,14 @@ class RBDTestCase(test.TestCase):
         self.assertEqual(volume.set_snap.call_count, 2)
         volume.parent_info.assert_called_once()
 
+    @common_mocks
     def test_get_clone_info_w_exception(self):
-
-        self.rbd.ImageNotFound = Exception
-
-        volume = self.rbd.Image()
+        volume = self.mock_rbd.Image()
         volume.set_snap = mock.Mock()
         volume.parent_info = mock.Mock()
-        volume.parent_info.side_effect = self.rbd.ImageNotFound
+        volume.parent_info.side_effect = self.mock_rbd.ImageNotFound
 
-        snapshot = self.rbd.ImageSnapshot()
+        snapshot = self.mock_rbd.ImageSnapshot()
 
         info = self.driver._get_clone_info(volume, self.volume_name,
                                            snap=snapshot)
@@ -294,10 +340,12 @@ class RBDTestCase(test.TestCase):
         volume.set_snap.assert_called_once()
         self.assertEqual(volume.set_snap.call_count, 2)
         volume.parent_info.assert_called_once()
+        # Make sure the exception was raised
+        self.assertEqual(RAISED_EXCEPTIONS, [self.mock_rbd.ImageNotFound])
 
+    @common_mocks
     def test_get_clone_info_deleted_volume(self):
-
-        volume = self.rbd.Image()
+        volume = self.mock_rbd.Image()
         volume.set_snap = mock.Mock()
         volume.parent_info = mock.Mock()
         parent_info = ('a', 'b', '%s.clone_snap' % (self.volume_name))
@@ -311,92 +359,101 @@ class RBDTestCase(test.TestCase):
         self.assertFalse(volume.set_snap.called)
         volume.parent_info.assert_called_once()
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_create_cloned_volume(self, mock_client):
+    @common_mocks
+    def test_create_cloned_volume(self):
         src_name = u'volume-00000001'
         dst_name = u'volume-00000002'
 
         self.cfg.rbd_max_clone_depth = 2
-        self.rbd.RBD.clone = mock.Mock()
-        self.driver._get_clone_depth = mock.Mock()
-        # Try with no flatten required
-        self.driver._get_clone_depth.return_value = 1
+        self.mock_rbd.RBD.clone = mock.Mock()
 
-        self.rbd.Image.create_snap = mock.Mock()
-        self.rbd.Image.protect_snap = mock.Mock()
-        self.rbd.Image.close = mock.Mock()
+        with mock.patch.object(self.driver, '_get_clone_depth') as \
+                mock_get_clone_depth:
+            # Try with no flatten required
+            mock_get_clone_depth.return_value = 1
 
-        self.driver.create_cloned_volume(dict(name=dst_name),
-                                         dict(name=src_name))
+            self.mock_rbd.Image.create_snap = mock.Mock()
+            self.mock_rbd.Image.protect_snap = mock.Mock()
+            self.mock_rbd.Image.close = mock.Mock()
 
-        self.rbd.Image.create_snap.assert_called_once()
-        self.rbd.Image.protect_snap.assert_called_once()
-        self.rbd.RBD.clone.assert_called_once()
-        self.rbd.Image.close.assert_called_once()
+            self.driver.create_cloned_volume(dict(name=dst_name),
+                                             dict(name=src_name))
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_create_cloned_volume_w_flatten(self, mock_client):
+            self.mock_rbd.Image.create_snap.assert_called_once()
+            self.mock_rbd.Image.protect_snap.assert_called_once()
+            self.mock_rbd.RBD.clone.assert_called_once()
+            self.mock_rbd.Image.close.assert_called_once()
+            self.assertTrue(mock_get_clone_depth.called)
+
+    @common_mocks
+    def test_create_cloned_volume_w_flatten(self):
         src_name = u'volume-00000001'
         dst_name = u'volume-00000002'
 
         self.cfg.rbd_max_clone_depth = 1
-        self.rbd.RBD.Error = Exception
-        self.rbd.RBD.clone = mock.Mock()
-        self.rbd.RBD.clone.side_effect = self.rbd.RBD.Error
-        self.driver._get_clone_depth = mock.Mock()
-        # Try with no flatten required
-        self.driver._get_clone_depth.return_value = 1
-
-        self.rbd.Image.create_snap = mock.Mock()
-        self.rbd.Image.protect_snap = mock.Mock()
-        self.rbd.Image.unprotect_snap = mock.Mock()
-        self.rbd.Image.remove_snap = mock.Mock()
-        self.rbd.Image.close = mock.Mock()
-
-        self.assertRaises(self.rbd.RBD.Error, self.driver.create_cloned_volume,
-                          dict(name=dst_name), dict(name=src_name))
-
-        self.rbd.Image.create_snap.assert_called_once()
-        self.rbd.Image.protect_snap.assert_called_once()
-        self.rbd.RBD.clone.assert_called_once()
-        self.rbd.Image.unprotect_snap.assert_called_once()
-        self.rbd.Image.remove_snap.assert_called_once()
-        self.rbd.Image.close.assert_called_once()
-
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_create_cloned_volume_w_clone_exception(self, mock_client):
+        self.mock_rbd.RBD.clone = mock.Mock()
+        self.mock_rbd.RBD.clone.side_effect = self.mock_rbd.RBD.Error
+
+        with mock.patch.object(self.driver, '_get_clone_depth') as \
+                mock_get_clone_depth:
+            # Try with no flatten required
+            mock_get_clone_depth.return_value = 1
+
+            self.mock_rbd.Image.create_snap = mock.Mock()
+            self.mock_rbd.Image.protect_snap = mock.Mock()
+            self.mock_rbd.Image.unprotect_snap = mock.Mock()
+            self.mock_rbd.Image.remove_snap = mock.Mock()
+            self.mock_rbd.Image.close = mock.Mock()
+
+            self.assertRaises(self.mock_rbd.RBD.Error,
+                              self.driver.create_cloned_volume,
+                              dict(name=dst_name), dict(name=src_name))
+
+            self.mock_rbd.Image.create_snap.assert_called_once()
+            self.mock_rbd.Image.protect_snap.assert_called_once()
+            self.mock_rbd.RBD.clone.assert_called_once()
+            self.mock_rbd.Image.unprotect_snap.assert_called_once()
+            self.mock_rbd.Image.remove_snap.assert_called_once()
+            self.mock_rbd.Image.close.assert_called_once()
+            self.assertTrue(mock_get_clone_depth.called)
+
+    @common_mocks
+    def test_create_cloned_volume_w_clone_exception(self):
         src_name = u'volume-00000001'
         dst_name = u'volume-00000002'
 
         self.cfg.rbd_max_clone_depth = 2
-        self.rbd.RBD.Error = Exception
-        self.rbd.RBD.clone = mock.Mock()
-        self.rbd.RBD.clone.side_effect = self.rbd.RBD.Error
-        self.driver._get_clone_depth = mock.Mock()
-        # Try with no flatten required
-        self.driver._get_clone_depth.return_value = 1
-
-        self.rbd.Image.create_snap = mock.Mock()
-        self.rbd.Image.protect_snap = mock.Mock()
-        self.rbd.Image.unprotect_snap = mock.Mock()
-        self.rbd.Image.remove_snap = mock.Mock()
-        self.rbd.Image.close = mock.Mock()
-
-        self.assertRaises(self.rbd.RBD.Error, self.driver.create_cloned_volume,
-                          dict(name=dst_name), dict(name=src_name))
-
-        self.rbd.Image.create_snap.assert_called_once()
-        self.rbd.Image.protect_snap.assert_called_once()
-        self.rbd.RBD.clone.assert_called_once()
-        self.rbd.Image.unprotect_snap.assert_called_once()
-        self.rbd.Image.remove_snap.assert_called_once()
-        self.rbd.Image.close.assert_called_once()
-
+        self.mock_rbd.RBD.clone = mock.Mock()
+        self.mock_rbd.RBD.clone.side_effect = self.mock_rbd.RBD.Error
+        with mock.patch.object(self.driver, '_get_clone_depth') as \
+                mock_get_clone_depth:
+            # Try with no flatten required
+            mock_get_clone_depth.return_value = 1
+
+            self.mock_rbd.Image.create_snap = mock.Mock()
+            self.mock_rbd.Image.protect_snap = mock.Mock()
+            self.mock_rbd.Image.unprotect_snap = mock.Mock()
+            self.mock_rbd.Image.remove_snap = mock.Mock()
+            self.mock_rbd.Image.close = mock.Mock()
+
+            self.assertRaises(self.mock_rbd.RBD.Error,
+                              self.driver.create_cloned_volume,
+                              dict(name=dst_name), dict(name=src_name))
+
+            self.mock_rbd.Image.create_snap.assert_called_once()
+            self.mock_rbd.Image.protect_snap.assert_called_once()
+            self.mock_rbd.RBD.clone.assert_called_once()
+            self.mock_rbd.Image.unprotect_snap.assert_called_once()
+            self.mock_rbd.Image.remove_snap.assert_called_once()
+            self.mock_rbd.Image.close.assert_called_once()
+
+    @common_mocks
     def test_good_locations(self):
         locations = ['rbd://fsid/pool/image/snap',
                      'rbd://%2F/%2F/%2F/%2F', ]
         map(self.driver._parse_location, locations)
 
+    @common_mocks
     def test_bad_locations(self):
         locations = ['rbd://image',
                      'http://path/to/somewhere/else',
@@ -412,43 +469,47 @@ class RBDTestCase(test.TestCase):
             self.assertFalse(
                 self.driver._is_cloneable(loc, {'disk_format': 'raw'}))
 
-    @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy')
-    def test_cloneable(self, mock_proxy):
-        self.driver._get_fsid = mock.Mock()
-        self.driver._get_fsid.return_value = 'abc'
-        location = 'rbd://abc/pool/image/snap'
-        info = {'disk_format': 'raw'}
-        self.assertTrue(self.driver._is_cloneable(location, info))
-
-    @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy')
-    def test_uncloneable_different_fsid(self, mock_proxy):
-        self.driver._get_fsid = mock.Mock()
-        self.driver._get_fsid.return_value = 'abc'
-        location = 'rbd://def/pool/image/snap'
-        self.assertFalse(
-            self.driver._is_cloneable(location, {'disk_format': 'raw'}))
-
-    @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy')
-    def test_uncloneable_unreadable(self, mock_proxy):
-        self.driver._get_fsid = mock.Mock()
-        self.driver._get_fsid.return_value = 'abc'
-        location = 'rbd://abc/pool/image/snap'
-
-        self.rbd.Error = Exception
-        mock_proxy.side_effect = self.rbd.Error
-
-        args = [location, {'disk_format': 'raw'}]
-        self.assertFalse(self.driver._is_cloneable(*args))
-        mock_proxy.assert_called_once()
+    @common_mocks
+    def test_cloneable(self):
+        with mock.patch.object(self.driver, '_get_fsid') as mock_get_fsid:
+            mock_get_fsid.return_value = 'abc'
+            location = 'rbd://abc/pool/image/snap'
+            info = {'disk_format': 'raw'}
+            self.assertTrue(self.driver._is_cloneable(location, info))
+            self.assertTrue(mock_get_fsid.called)
+
+    @common_mocks
+    def test_uncloneable_different_fsid(self):
+        with mock.patch.object(self.driver, '_get_fsid') as mock_get_fsid:
+            mock_get_fsid.return_value = 'abc'
+            location = 'rbd://def/pool/image/snap'
+            self.assertFalse(
+                self.driver._is_cloneable(location, {'disk_format': 'raw'}))
+            self.assertTrue(mock_get_fsid.called)
+
+    @common_mocks
+    def test_uncloneable_unreadable(self):
+        with mock.patch.object(self.driver, '_get_fsid') as mock_get_fsid:
+            mock_get_fsid.return_value = 'abc'
+            location = 'rbd://abc/pool/image/snap'
+
+            self.mock_proxy.side_effect = self.mock_rbd.Error
 
+            args = [location, {'disk_format': 'raw'}]
+            self.assertFalse(self.driver._is_cloneable(*args))
+            self.mock_proxy.assert_called_once()
+            self.assertTrue(mock_get_fsid.called)
+
+    @common_mocks
     def test_uncloneable_bad_format(self):
-        self.driver._get_fsid = mock.Mock()
-        self.driver._get_fsid.return_value = 'abc'
-        location = 'rbd://abc/pool/image/snap'
-        formats = ['qcow2', 'vmdk', 'vdi']
-        for f in formats:
-            self.assertFalse(
-                self.driver._is_cloneable(location, {'disk_format': f}))
+        with mock.patch.object(self.driver, '_get_fsid') as mock_get_fsid:
+            mock_get_fsid.return_value = 'abc'
+            location = 'rbd://abc/pool/image/snap'
+            formats = ['qcow2', 'vmdk', 'vdi']
+            for f in formats:
+                self.assertFalse(
+                    self.driver._is_cloneable(location, {'disk_format': f}))
+            self.assertTrue(mock_get_fsid.called)
 
     def _copy_image(self):
         with mock.patch.object(tempfile, 'NamedTemporaryFile'):
@@ -462,17 +523,19 @@ class RBDTestCase(test.TestCase):
                                     mock_image_service, None]
                             self.driver.copy_image_to_volume(*args)
 
+    @common_mocks
     def test_copy_image_no_volume_tmp(self):
         self.cfg.volume_tmp_dir = None
         self._copy_image()
 
+    @common_mocks
     def test_copy_image_volume_tmp(self):
         self.cfg.volume_tmp_dir = '/var/run/cinder/tmp'
         self._copy_image()
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_update_volume_stats(self, mock_client):
-        client = mock_client.return_value
+    @common_mocks
+    def test_update_volume_stats(self):
+        client = self.mock_client.return_value
         client.__enter__.return_value = client
 
         client.cluster = mock.Mock()
@@ -496,9 +559,9 @@ class RBDTestCase(test.TestCase):
         client.cluster.get_cluster_stats.assert_called_once()
         self.assertDictMatch(expected, actual)
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_update_volume_stats_error(self, mock_client):
-        client = mock_client.return_value
+    @common_mocks
+    def test_update_volume_stats_error(self):
+        client = self.mock_client.return_value
         client.__enter__.return_value = client
 
         client.cluster = mock.Mock()
@@ -508,8 +571,6 @@ class RBDTestCase(test.TestCase):
         self.driver.configuration.safe_get = mock.Mock()
         self.driver.configuration.safe_get.return_value = 'RBD'
 
-        self.rados.Error = Exception
-
         expected = dict(volume_backend_name='RBD',
                         vendor_name='Open Source',
                         driver_version=self.driver.VERSION,
@@ -522,39 +583,42 @@ class RBDTestCase(test.TestCase):
         client.cluster.get_cluster_stats.assert_called_once()
         self.assertDictMatch(expected, actual)
 
+    @common_mocks
     def test_get_mon_addrs(self):
-        self.driver._execute = mock.Mock()
-        self.driver._execute.return_value = (CEPH_MON_DUMP, '')
-
-        hosts = ['::1', '::1', '::1', '127.0.0.1', 'example.com']
-        ports = ['6789', '6790', '6791', '6792', '6791']
-        self.assertEqual((hosts, ports), self.driver._get_mon_addrs())
+        with mock.patch.object(self.driver, '_execute') as mock_execute:
+            mock_execute.return_value = (CEPH_MON_DUMP, '')
+            hosts = ['::1', '::1', '::1', '127.0.0.1', 'example.com']
+            ports = ['6789', '6790', '6791', '6792', '6791']
+            self.assertEqual((hosts, ports), self.driver._get_mon_addrs())
 
+    @common_mocks
     def test_initialize_connection(self):
         hosts = ['::1', '::1', '::1', '127.0.0.1', 'example.com']
         ports = ['6789', '6790', '6791', '6792', '6791']
 
-        self.driver._get_mon_addrs = mock.Mock()
-        self.driver._get_mon_addrs.return_value = (hosts, ports)
-
-        expected = {
-            'driver_volume_type': 'rbd',
-            'data': {
-                'name': '%s/%s' % (self.cfg.rbd_pool,
-                                   self.volume_name),
-                'hosts': hosts,
-                'ports': ports,
-                'auth_enabled': False,
-                'auth_username': None,
-                'secret_type': 'ceph',
-                'secret_uuid': None, }
-        }
-        actual = self.driver.initialize_connection(dict(name=self.volume_name),
-                                                   None)
-        self.assertDictMatch(expected, actual)
-
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_clone(self, mock_client):
+        with mock.patch.object(self.driver, '_get_mon_addrs') as \
+                mock_get_mon_addrs:
+            mock_get_mon_addrs.return_value = (hosts, ports)
+
+            expected = {
+                'driver_volume_type': 'rbd',
+                'data': {
+                    'name': '%s/%s' % (self.cfg.rbd_pool,
+                                       self.volume_name),
+                    'hosts': hosts,
+                    'ports': ports,
+                    'auth_enabled': False,
+                    'auth_username': None,
+                    'secret_type': 'ceph',
+                    'secret_uuid': None, }
+            }
+            volume = dict(name=self.volume_name)
+            actual = self.driver.initialize_connection(volume, None)
+            self.assertDictMatch(expected, actual)
+            self.assertTrue(mock_get_mon_addrs.called)
+
+    @common_mocks
+    def test_clone(self):
         src_pool = u'images'
         src_image = u'image-name'
         src_snap = u'snapshot-name'
@@ -567,20 +631,21 @@ class RBDTestCase(test.TestCase):
                 return inst
             return _inner
 
-        client = mock_client.return_value
+        client = self.mock_client.return_value
         # capture both rados client used to perform the clone
         client.__enter__.side_effect = mock__enter__(client)
 
-        self.rbd.RBD.clone = mock.Mock()
+        self.mock_rbd.RBD.clone = mock.Mock()
 
         self.driver._clone(self.volume, src_pool, src_image, src_snap)
 
         args = [client_stack[0].ioctx, str(src_image), str(src_snap),
                 client_stack[1].ioctx, str(self.volume_name)]
-        kwargs = {'features': self.rbd.RBD_FEATURE_LAYERING}
-        self.rbd.RBD.clone.assert_called_once_with(*args, **kwargs)
+        kwargs = {'features': self.mock_rbd.RBD_FEATURE_LAYERING}
+        self.mock_rbd.RBD.clone.assert_called_once_with(*args, **kwargs)
         self.assertEqual(client.__enter__.call_count, 2)
 
+    @common_mocks
     def test_extend_volume(self):
         fake_size = '20'
         fake_vol = {'project_id': 'testprjid', 'name': self.volume_name,
@@ -596,63 +661,67 @@ class RBDTestCase(test.TestCase):
 
         self.mox.VerifyAll()
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_rbd_volume_proxy_init(self, mock_client):
+    @common_mocks
+    def test_rbd_volume_proxy_init(self):
         snap = u'snapshot-name'
 
-        client = mock_client.return_value
+        client = self.mock_client.return_value
         client.__enter__.return_value = client
 
-        self.driver._connect_to_rados = mock.Mock()
-        self.driver._connect_to_rados.return_value = (None, None)
-        self.driver._disconnect_from_rados = mock.Mock()
-        self.driver._disconnect_from_rados.return_value = (None, None)
+        with mock.patch.object(self.driver, '_connect_to_rados') as \
+                mock_connect_from_rados:
+            with mock.patch.object(self.driver, '_disconnect_from_rados') as \
+                    mock_disconnect_from_rados:
+                mock_connect_from_rados.return_value = (None, None)
+                mock_disconnect_from_rados.return_value = (None, None)
 
-        with driver.RBDVolumeProxy(self.driver, self.volume_name):
-            self.driver._connect_to_rados.assert_called_once()
-            self.assertFalse(self.driver._disconnect_from_rados.called)
+                with driver.RBDVolumeProxy(self.driver, self.volume_name):
+                    mock_connect_from_rados.assert_called_once()
+                    self.assertFalse(mock_disconnect_from_rados.called)
 
-        self.driver._disconnect_from_rados.assert_called_once()
+                mock_disconnect_from_rados.assert_called_once()
 
-        self.driver._connect_to_rados.reset_mock()
-        self.driver._disconnect_from_rados.reset_mock()
+                mock_connect_from_rados.reset_mock()
+                mock_disconnect_from_rados.reset_mock()
 
-        with driver.RBDVolumeProxy(self.driver, self.volume_name,
-                                   snapshot=snap):
-            self.driver._connect_to_rados.assert_called_once()
-            self.assertFalse(self.driver._disconnect_from_rados.called)
+                with driver.RBDVolumeProxy(self.driver, self.volume_name,
+                                           snapshot=snap):
+                    mock_connect_from_rados.assert_called_once()
+                    self.assertFalse(mock_disconnect_from_rados.called)
 
-        self.driver._disconnect_from_rados.assert_called_once()
+                mock_disconnect_from_rados.assert_called_once()
 
-    @mock.patch('cinder.volume.drivers.rbd.RADOSClient')
-    def test_connect_to_rados(self, mock_client):
-        client = mock_client.return_value
-        client.__enter__.return_value = client
-        client.open_ioctx = mock.Mock()
-
-        mock_ioctx = mock.Mock()
-        client.open_ioctx.return_value = mock_ioctx
-
-        self.rados.Error = test.TestingException
-        self.rados.Rados.return_value = client
+    @common_mocks
+    def test_connect_to_rados(self):
+        self.mock_rados.Rados.connect = mock.Mock()
+        self.mock_rados.Rados.shutdown = mock.Mock()
+        self.mock_rados.Rados.open_ioctx = mock.Mock()
+        self.mock_rados.Rados.open_ioctx.return_value = \
+            self.mock_rados.Rados.ioctx
 
         # default configured pool
-        self.assertEqual((client, mock_ioctx),
-                         self.driver._connect_to_rados())
-        client.open_ioctx.assert_called_with(self.cfg.rbd_pool)
+        ret = self.driver._connect_to_rados()
+        self.assertTrue(self.mock_rados.Rados.connect.called)
+        self.assertTrue(self.mock_rados.Rados.open_ioctx.called)
+        self.assertIsInstance(ret[0], self.mock_rados.Rados)
+        self.assertEqual(ret[1], self.mock_rados.Rados.ioctx)
+        self.mock_rados.Rados.open_ioctx.assert_called_with(self.cfg.rbd_pool)
 
         # different pool
-        self.assertEqual((client, mock_ioctx),
-                         self.driver._connect_to_rados('images'))
-        client.open_ioctx.assert_called_with('images')
+        ret = self.driver._connect_to_rados('alt_pool')
+        self.assertTrue(self.mock_rados.Rados.connect.called)
+        self.assertTrue(self.mock_rados.Rados.open_ioctx.called)
+        self.assertIsInstance(ret[0], self.mock_rados.Rados)
+        self.assertEqual(ret[1], self.mock_rados.Rados.ioctx)
+        self.mock_rados.Rados.open_ioctx.assert_called_with('alt_pool')
 
         # error
-        client.open_ioctx.reset_mock()
-        client.shutdown.reset_mock()
-        client.open_ioctx.side_effect = self.rados.Error
-        self.assertRaises(test.TestingException, self.driver._connect_to_rados)
-        client.open_ioctx.assert_called_once()
-        client.shutdown.assert_called_once()
+        self.mock_rados.Rados.open_ioctx.reset_mock()
+        self.mock_rados.Rados.shutdown.reset_mock()
+        self.mock_rados.Rados.open_ioctx.side_effect = self.mock_rados.Error
+        self.assertRaises(self.mock_rados.Error, self.driver._connect_to_rados)
+        self.mock_rados.Rados.open_ioctx.assert_called_once()
+        self.mock_rados.Rados.shutdown.assert_called_once()
 
 
 class RBDImageIOWrapperTestCase(test.TestCase):
@@ -666,7 +735,7 @@ class RBDImageIOWrapperTestCase(test.TestCase):
         self.meta.image.read = mock.Mock()
         self.meta.image.write = mock.Mock()
         self.meta.image.size = mock.Mock()
-        self.rbd_wrapper = driver.RBDImageIOWrapper(self.meta)
+        self.mock_rbd_wrapper = driver.RBDImageIOWrapper(self.meta)
         self.data_length = 1024
         self.full_data = 'abcd' * 256
 
@@ -674,25 +743,25 @@ class RBDImageIOWrapperTestCase(test.TestCase):
         super(RBDImageIOWrapperTestCase, self).tearDown()
 
     def test_init(self):
-        self.assertEqual(self.rbd_wrapper._rbd_meta, self.meta)
-        self.assertEqual(self.rbd_wrapper._offset, 0)
+        self.assertEqual(self.mock_rbd_wrapper._rbd_meta, self.meta)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 0)
 
     def test_inc_offset(self):
-        self.rbd_wrapper._inc_offset(10)
-        self.rbd_wrapper._inc_offset(10)
-        self.assertEqual(self.rbd_wrapper._offset, 20)
+        self.mock_rbd_wrapper._inc_offset(10)
+        self.mock_rbd_wrapper._inc_offset(10)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 20)
 
     def test_rbd_image(self):
-        self.assertEqual(self.rbd_wrapper.rbd_image, self.meta.image)
+        self.assertEqual(self.mock_rbd_wrapper.rbd_image, self.meta.image)
 
     def test_rbd_user(self):
-        self.assertEqual(self.rbd_wrapper.rbd_user, self.meta.user)
+        self.assertEqual(self.mock_rbd_wrapper.rbd_user, self.meta.user)
 
     def test_rbd_pool(self):
-        self.assertEqual(self.rbd_wrapper.rbd_conf, self.meta.conf)
+        self.assertEqual(self.mock_rbd_wrapper.rbd_conf, self.meta.conf)
 
     def test_rbd_conf(self):
-        self.assertEqual(self.rbd_wrapper.rbd_pool, self.meta.pool)
+        self.assertEqual(self.mock_rbd_wrapper.rbd_pool, self.meta.pool)
 
     def test_read(self):
 
@@ -702,77 +771,77 @@ class RBDImageIOWrapperTestCase(test.TestCase):
         self.meta.image.read.side_effect = mock_read
         self.meta.image.size.return_value = self.data_length
 
-        data = self.rbd_wrapper.read()
+        data = self.mock_rbd_wrapper.read()
         self.assertEqual(data, self.full_data)
 
-        data = self.rbd_wrapper.read()
+        data = self.mock_rbd_wrapper.read()
         self.assertEqual(data, '')
 
-        self.rbd_wrapper.seek(0)
-        data = self.rbd_wrapper.read()
+        self.mock_rbd_wrapper.seek(0)
+        data = self.mock_rbd_wrapper.read()
         self.assertEqual(data, self.full_data)
 
-        self.rbd_wrapper.seek(0)
-        data = self.rbd_wrapper.read(10)
+        self.mock_rbd_wrapper.seek(0)
+        data = self.mock_rbd_wrapper.read(10)
         self.assertEqual(data, self.full_data[:10])
 
     def test_write(self):
-        self.rbd_wrapper.write(self.full_data)
-        self.assertEqual(self.rbd_wrapper._offset, 1024)
+        self.mock_rbd_wrapper.write(self.full_data)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 1024)
 
     def test_seekable(self):
-        self.assertTrue(self.rbd_wrapper.seekable)
+        self.assertTrue(self.mock_rbd_wrapper.seekable)
 
     def test_seek(self):
-        self.assertEqual(self.rbd_wrapper._offset, 0)
-        self.rbd_wrapper.seek(10)
-        self.assertEqual(self.rbd_wrapper._offset, 10)
-        self.rbd_wrapper.seek(10)
-        self.assertEqual(self.rbd_wrapper._offset, 10)
-        self.rbd_wrapper.seek(10, 1)
-        self.assertEqual(self.rbd_wrapper._offset, 20)
-
-        self.rbd_wrapper.seek(0)
-        self.rbd_wrapper.write(self.full_data)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 0)
+        self.mock_rbd_wrapper.seek(10)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 10)
+        self.mock_rbd_wrapper.seek(10)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 10)
+        self.mock_rbd_wrapper.seek(10, 1)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 20)
+
+        self.mock_rbd_wrapper.seek(0)
+        self.mock_rbd_wrapper.write(self.full_data)
         self.meta.image.size.return_value = self.data_length
-        self.rbd_wrapper.seek(0)
-        self.assertEqual(self.rbd_wrapper._offset, 0)
+        self.mock_rbd_wrapper.seek(0)
+        self.assertEqual(self.mock_rbd_wrapper._offset, 0)
 
-        self.rbd_wrapper.seek(10, 2)
-        self.assertEqual(self.rbd_wrapper._offset, self.data_length + 10)
-        self.rbd_wrapper.seek(-10, 2)
-        self.assertEqual(self.rbd_wrapper._offset, self.data_length - 10)
+        self.mock_rbd_wrapper.seek(10, 2)
+        self.assertEqual(self.mock_rbd_wrapper._offset, self.data_length + 10)
+        self.mock_rbd_wrapper.seek(-10, 2)
+        self.assertEqual(self.mock_rbd_wrapper._offset, self.data_length - 10)
 
         # test exceptions.
-        self.assertRaises(IOError, self.rbd_wrapper.seek, 0, 3)
-        self.assertRaises(IOError, self.rbd_wrapper.seek, -1)
+        self.assertRaises(IOError, self.mock_rbd_wrapper.seek, 0, 3)
+        self.assertRaises(IOError, self.mock_rbd_wrapper.seek, -1)
         # offset should not have been changed by any of the previous
         # operations.
-        self.assertEqual(self.rbd_wrapper._offset, self.data_length - 10)
+        self.assertEqual(self.mock_rbd_wrapper._offset, self.data_length - 10)
 
     def test_tell(self):
-        self.assertEqual(self.rbd_wrapper.tell(), 0)
-        self.rbd_wrapper._inc_offset(10)
-        self.assertEqual(self.rbd_wrapper.tell(), 10)
+        self.assertEqual(self.mock_rbd_wrapper.tell(), 0)
+        self.mock_rbd_wrapper._inc_offset(10)
+        self.assertEqual(self.mock_rbd_wrapper.tell(), 10)
 
     def test_flush(self):
         with mock.patch.object(driver, 'LOG') as mock_logger:
             self.meta.image.flush = mock.Mock()
-            self.rbd_wrapper.flush()
+            self.mock_rbd_wrapper.flush()
             self.meta.image.flush.assert_called_once()
             self.meta.image.flush.reset_mock()
             # this should be caught and logged silently.
             self.meta.image.flush.side_effect = AttributeError
-            self.rbd_wrapper.flush()
+            self.mock_rbd_wrapper.flush()
             self.meta.image.flush.assert_called_once()
             msg = _("flush() not supported in this version of librbd")
             mock_logger.warning.assert_called_with(msg)
 
     def test_fileno(self):
-        self.assertRaises(IOError, self.rbd_wrapper.fileno)
+        self.assertRaises(IOError, self.mock_rbd_wrapper.fileno)
 
     def test_close(self):
-        self.rbd_wrapper.close()
+        self.mock_rbd_wrapper.close()
 
 
 class ManagedRBDTestCase(DriverTestCase):
@@ -834,55 +903,56 @@ class ManagedRBDTestCase(DriverTestCase):
     def test_create_vol_from_image_status_available(self):
         """Clone raw image then verify volume is in available state."""
 
-        def mock_clone_image(volume, image_location, image_id, image_meta):
+        def _mock_clone_image(volume, image_location, image_id, image_meta):
             return {'provider_location': None}, True
 
-        self.volume.driver.clone_image = mock.Mock()
-        self.volume.driver.clone_image.side_effect = mock_clone_image
-        self.volume.driver.create_volume = mock.Mock()
-
-        with mock.patch.object(create_volume.CreateVolumeFromSpecTask,
-                               '_copy_image_to_volume') as mock_copy:
-            self._create_volume_from_image('available', raw=True)
+        with mock.patch.object(self.volume.driver, 'clone_image') as \
+                mock_clone_image:
+            mock_clone_image.side_effect = _mock_clone_image
+            with mock.patch.object(self.volume.driver, 'create_volume') as \
+                    mock_create:
+                with mock.patch.object(create_volume.CreateVolumeFromSpecTask,
+                                       '_copy_image_to_volume') as mock_copy:
+                    self._create_volume_from_image('available', raw=True)
+                    self.assertFalse(mock_copy.called)
 
-        self.volume.driver.clone_image.assert_called_once()
-        self.assertFalse(self.volume.driver.create_volume.called)
-        self.assertFalse(mock_copy.called)
+                mock_clone_image.assert_called_once()
+                self.assertFalse(mock_create.called)
 
     def test_create_vol_from_non_raw_image_status_available(self):
         """Clone non-raw image then verify volume is in available state."""
 
-        def mock_clone_image(volume, image_location, image_id, image_meta):
+        def _mock_clone_image(volume, image_location, image_id, image_meta):
             return {'provider_location': None}, False
 
-        self.volume.driver.clone_image = mock.Mock()
-        self.volume.driver.clone_image.side_effect = mock_clone_image
-        self.volume.driver.create_volume = mock.Mock()
-        self.volume.driver.create_volume.return_value = None
+        with mock.patch.object(self.volume.driver, 'clone_image') as \
+                mock_clone_image:
+            mock_clone_image.side_effect = _mock_clone_image
+            with mock.patch.object(self.volume.driver, 'create_volume') as \
+                    mock_create:
+                with mock.patch.object(create_volume.CreateVolumeFromSpecTask,
+                                       '_copy_image_to_volume') as mock_copy:
+                    self._create_volume_from_image('available', raw=False)
+                    mock_copy.assert_called_once()
 
-        with mock.patch.object(create_volume.CreateVolumeFromSpecTask,
-                               '_copy_image_to_volume') as mock_copy:
-            self._create_volume_from_image('available', raw=False)
-
-        self.volume.driver.clone_image.assert_called_once()
-        self.volume.driver.create_volume.assert_called_once()
-        mock_copy.assert_called_once()
+                mock_clone_image.assert_called_once()
+                mock_create.assert_called_once()
 
     def test_create_vol_from_image_status_error(self):
         """Fail to clone raw image then verify volume is in error state."""
-
-        self.volume.driver.clone_image = mock.Mock()
-        self.volume.driver.clone_image.side_effect = exception.CinderException
-        self.volume.driver.create_volume = mock.Mock()
-        self.volume.driver.create_volume.return_value = None
-
-        with mock.patch.object(create_volume.CreateVolumeFromSpecTask,
-                               '_copy_image_to_volume') as mock_copy:
-            self._create_volume_from_image('error', raw=True, clone_error=True)
-
-        self.volume.driver.clone_image.assert_called_once()
-        self.assertFalse(self.volume.driver.create_volume.called)
-        self.assertFalse(mock_copy.called)
+        with mock.patch.object(self.volume.driver, 'clone_image') as \
+                mock_clone_image:
+            mock_clone_image.side_effect = exception.CinderException
+            with mock.patch.object(self.volume.driver, 'create_volume') as \
+                    mock_create:
+                with mock.patch.object(create_volume.CreateVolumeFromSpecTask,
+                                       '_copy_image_to_volume') as mock_copy:
+                    self._create_volume_from_image('error', raw=True,
+                                                   clone_error=True)
+                    self.assertFalse(mock_copy.called)
+
+                mock_clone_image.assert_called_once()
+                self.assertFalse(self.volume.driver.create_volume.called)
 
     def test_clone_failure(self):
         driver = self.volume.driver
@@ -900,17 +970,19 @@ class ManagedRBDTestCase(DriverTestCase):
         expected = ({'provider_location': None}, True)
         driver = self.volume.driver
 
-        self.volume.driver._is_cloneable = mock.Mock()
-        self.volume.driver._is_cloneable.return_value = True
-        self.volume.driver._clone = mock.Mock()
-        self.volume.driver._resize = mock.Mock()
-
-        image_loc = ('rbd://fee/fi/fo/fum', None)
-        actual = driver.clone_image({'name': 'vol1'},
-                                    image_loc,
-                                    'id.foo',
-                                    {'disk_format': 'raw'})
-
-        self.assertEqual(expected, actual)
-        self.volume.driver._clone.assert_called_once()
-        self.volume.driver._resize.assert_called_once()
+        with mock.patch.object(self.volume.driver, '_is_cloneable') as \
+                mock_is_cloneable:
+            mock_is_cloneable.return_value = True
+            with mock.patch.object(self.volume.driver, '_clone') as \
+                    mock_clone:
+                with mock.patch.object(self.volume.driver, '_resize') as \
+                        mock_resize:
+                    image_loc = ('rbd://fee/fi/fo/fum', None)
+
+                    actual = driver.clone_image({'name': 'vol1'}, image_loc,
+                                                'id.foo',
+                                                {'disk_format': 'raw'})
+
+                    self.assertEqual(expected, actual)
+                    mock_clone.assert_called_once()
+                    mock_resize.assert_called_once()