Merge "Remove Mock class monkey patching"

This commit is contained in:
Jenkins
2014-11-24 11:11:48 +00:00
committed by Gerrit Code Review
2 changed files with 151 additions and 202 deletions

View File

@@ -77,8 +77,8 @@ def common_mocks(f):
@mock.patch('time.time', spec=True)
# NOTE(dosaboy): set spec to empty object so that hasattr calls return
# False by default.
@mock.patch('cinder.backup.drivers.ceph.rbd', spec=object)
@mock.patch('cinder.backup.drivers.ceph.rados', spec=object)
@mock.patch('cinder.backup.drivers.ceph.rbd')
@mock.patch('cinder.backup.drivers.ceph.rados')
def _common_inner_inner2(mock_rados, mock_rbd, mock_time, mock_sleep,
mock_popen):
mock_time.side_effect = inst.time_inc
@@ -86,11 +86,6 @@ def common_mocks(f):
inst.mock_rados = mock_rados
inst.mock_rbd = mock_rbd
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.ImageBusy = MockImageBusyException
inst.mock_rbd.ImageNotFound = MockImageNotFoundException
@@ -201,6 +196,8 @@ class BackupCephTestCase(test.TestCase):
@common_mocks
def test_get_rbd_support(self):
del self.service.rbd.RBD_FEATURE_LAYERING
del self.service.rbd.RBD_FEATURE_STRIPINGV2
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_LAYERING'))
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_STRIPINGV2'))
@@ -224,14 +221,14 @@ class BackupCephTestCase(test.TestCase):
def test_get_most_recent_snap(self):
last = 'backup.%s.snap.9824923.1212' % (uuid.uuid4())
self.mock_rbd.Image.list_snaps = mock.Mock()
self.mock_rbd.Image.list_snaps.return_value = \
image = self.mock_rbd.Image.return_value
image.list_snaps.return_value = \
[{'name': 'backup.%s.snap.6423868.2342' % (uuid.uuid4())},
{'name': 'backup.%s.snap.1321319.3235' % (uuid.uuid4())},
{'name': last},
{'name': 'backup.%s.snap.3824923.1412' % (uuid.uuid4())}]
snap = self.service._get_most_recent_snap(self.service.rbd.Image())
snap = self.service._get_most_recent_snap(image)
self.assertEqual(last, snap)
@common_mocks
@@ -261,21 +258,24 @@ class BackupCephTestCase(test.TestCase):
@common_mocks
def test_get_backup_snaps(self):
self.mock_rbd.Image.list_snaps = mock.Mock()
self.mock_rbd.Image.list_snaps.return_value = \
[{'name': 'backup.%s.snap.6423868.2342' % (uuid.uuid4())},
{'name': 'backup.%s.wambam.6423868.2342' % (uuid.uuid4())},
{'name': 'backup.%s.snap.1321319.3235' % (uuid.uuid4())},
{'name': 'bbbackup.%s.snap.1321319.3235' % (uuid.uuid4())},
{'name': 'backup.%s.snap.3824923.1412' % (uuid.uuid4())}]
snaps = self.service.get_backup_snaps(self.service.rbd.Image())
image = self.mock_rbd.Image.return_value
image.list_snaps.return_value = [
{'name': 'backup.%s.snap.6423868.2342' % (uuid.uuid4())},
{'name': 'backup.%s.wambam.6423868.2342' % (uuid.uuid4())},
{'name': 'backup.%s.snap.1321319.3235' % (uuid.uuid4())},
{'name': 'bbbackup.%s.snap.1321319.3235' % (uuid.uuid4())},
{'name': 'backup.%s.snap.3824923.1412' % (uuid.uuid4())}]
snaps = self.service.get_backup_snaps(image)
self.assertEqual(len(snaps), 3)
@common_mocks
def test_transfer_data_from_rbd_to_file(self):
self.mock_rbd.Image.read = mock.Mock()
self.mock_rbd.Image.read.return_value = \
self.volume_file.read(self.data_length)
def fake_read(offset, length):
self.volume_file.seek(offset)
return self.volume_file.read(length)
self.mock_rbd.Image.return_value.read.side_effect = fake_read
self.mock_rbd.Image.return_value.size.return_value = self.data_length
with tempfile.NamedTemporaryFile() as test_file:
self.volume_file.seek(0)
@@ -294,29 +294,24 @@ class BackupCephTestCase(test.TestCase):
@common_mocks
def test_transfer_data_from_rbd_to_rbd(self):
def fake_read(offset, length):
self.volume_file.seek(offset)
return self.volume_file.read(length)
def mock_write_data(data, offset):
checksum.update(data)
test_file.write(data)
self.mock_rbd.Image.read = mock.Mock()
self.mock_rbd.Image.read.return_value = \
self.volume_file.read(self.data_length)
rbd1 = mock.Mock()
rbd1.read.side_effect = fake_read
self.mock_rbd.Image.size = mock.Mock()
self.mock_rbd.Image.size.return_value = \
self.chunk_size * self.num_chunks
self.mock_rbd.Image.write = mock.Mock()
self.mock_rbd.Image.write.side_effect = mock_write_data
rbd2 = mock.Mock()
rbd2.write.side_effect = mock_write_data
with tempfile.NamedTemporaryFile() as test_file:
self.volume_file.seek(0)
checksum = hashlib.sha256()
rbd1 = self.service.rbd.Image()
rbd2 = self.service.rbd.Image()
src_rbd_io = self._get_wrapped_rbd_io(rbd1)
dest_rbd_io = self._get_wrapped_rbd_io(rbd2)
self.service._transfer_data(src_rbd_io, 'src_foo', dest_rbd_io,
@@ -332,8 +327,7 @@ class BackupCephTestCase(test.TestCase):
checksum.update(data)
test_file.write(data)
self.mock_rbd.Image.write = mock.Mock()
self.mock_rbd.Image.write.side_effect = mock_write_data
self.mock_rbd.Image.return_value.write.side_effect = mock_write_data
with tempfile.NamedTemporaryFile() as test_file:
self.volume_file.seek(0)
@@ -371,8 +365,7 @@ class BackupCephTestCase(test.TestCase):
checksum.update(data)
test_file.write(data)
self.service.rbd.Image.write = mock.Mock()
self.service.rbd.Image.write.side_effect = mock_write_data
self.service.rbd.Image.return_value.write.side_effect = mock_write_data
with mock.patch.object(self.service, '_backup_metadata'):
with mock.patch.object(self.service, '_discard_bytes'):
@@ -382,7 +375,7 @@ class BackupCephTestCase(test.TestCase):
# Ensure the files are equal
self.assertEqual(checksum.digest(), self.checksum.digest())
self.assertTrue(self.service.rbd.Image.write.called)
self.assertTrue(self.service.rbd.Image.return_value.write.called)
@common_mocks
def test_get_backup_base_name(self):
@@ -614,17 +607,14 @@ class BackupCephTestCase(test.TestCase):
backup_name = self.service._get_backup_base_name(self.backup_id,
diff_format=True)
self.mock_rbd.RBD.list = mock.Mock()
self.mock_rbd.RBD.list.return_value = [backup_name]
self.mock_rbd.RBD.return_value.list.return_value = [backup_name]
def mock_read_data(offset, length):
return self.volume_file.read(self.data_length)
self.mock_rbd.Image.read = mock.Mock()
self.mock_rbd.Image.read.side_effect = mock_read_data
self.mock_rbd.Image.return_value.read.side_effect = mock_read_data
self.mock_rbd.Image.size = mock.Mock()
self.mock_rbd.Image.size.return_value = \
self.mock_rbd.Image.return_value.size.return_value = \
self.chunk_size * self.num_chunks
with mock.patch.object(self.service, '_restore_metadata') as \
@@ -649,22 +639,19 @@ class BackupCephTestCase(test.TestCase):
self.assertTrue(mock_discard_bytes.called)
self.assertTrue(mock_discard_bytes.called)
self.assertTrue(self.service.rbd.Image.read.called)
self.assertTrue(self.service.rbd.Image.return_value.read.called)
@common_mocks
def test_discard_bytes(self):
self.mock_rbd.Image.discard = mock.Mock()
wrapped_rbd = self._get_wrapped_rbd_io(self.mock_rbd.Image())
image = self.mock_rbd.Image.return_value
wrapped_rbd = self._get_wrapped_rbd_io(image)
self.service._discard_bytes(wrapped_rbd, 0, 0)
self.assertEqual(self.mock_rbd.Image.discard.call_count, 0)
self.assertEqual(image.discard.call_count, 0)
self.service._discard_bytes(wrapped_rbd, 0, 1234)
self.assertEqual(self.mock_rbd.Image.discard.call_count, 1)
self.mock_rbd.Image.discard.reset_mock()
self.mock_rbd.Image.write = mock.Mock()
self.mock_rbd.Image.flush = mock.Mock()
self.assertEqual(image.discard.call_count, 1)
image.reset_mock()
# Test discard with no remainder
with mock.patch.object(self.service, '_file_is_rbd') as \
@@ -674,13 +661,11 @@ class BackupCephTestCase(test.TestCase):
self.service._discard_bytes(wrapped_rbd, 0,
self.service.chunk_size * 2)
self.assertEqual(self.mock_rbd.Image.write.call_count, 2)
self.assertEqual(self.mock_rbd.Image.flush.call_count, 2)
self.assertFalse(self.mock_rbd.Image.discard.called)
self.assertEqual(image.write.call_count, 2)
self.assertEqual(image.flush.call_count, 2)
self.assertFalse(image.discard.called)
self.mock_rbd.Image.write.reset_mock()
self.mock_rbd.Image.flush.reset_mock()
self.mock_rbd.Image.discard.reset_mock()
image.reset_mock()
# Now test with a remainder.
with mock.patch.object(self.service, '_file_is_rbd') as \
@@ -690,9 +675,9 @@ class BackupCephTestCase(test.TestCase):
self.service._discard_bytes(wrapped_rbd, 0,
(self.service.chunk_size * 2) + 1)
self.assertEqual(self.mock_rbd.Image.write.call_count, 3)
self.assertEqual(self.mock_rbd.Image.flush.call_count, 3)
self.assertFalse(self.mock_rbd.Image.discard.called)
self.assertEqual(image.write.call_count, 3)
self.assertEqual(image.flush.call_count, 3)
self.assertFalse(image.discard.called)
@common_mocks
def test_delete_backup_snapshot(self):
@@ -721,9 +706,7 @@ class BackupCephTestCase(test.TestCase):
backup_name = self.service._get_backup_base_name(self.volume_id,
diff_format=True)
self.mock_rbd.RBD.list = mock.Mock()
self.mock_rbd.RBD.list.return_value = [backup_name]
self.mock_rbd.RBD.remove = mock.Mock()
self.mock_rbd.RBD.return_value.list.return_value = [backup_name]
with mock.patch.object(self.service, '_delete_backup_snapshot') as \
mock_del_backup_snap:
@@ -734,8 +717,8 @@ class BackupCephTestCase(test.TestCase):
self.assertTrue(mock_del_backup_snap.called)
#self.assertFalse(self.mock_rbd.ImageNotFound.called)
self.assertTrue(self.mock_rbd.RBD.list.called)
self.assertTrue(self.mock_rbd.RBD.remove.called)
self.assertTrue(self.mock_rbd.RBD.return_value.list.called)
self.assertTrue(self.mock_rbd.RBD.return_value.remove.called)
@common_mocks
@mock.patch('cinder.backup.drivers.ceph.VolumeMetadataBackup', spec=True)
@@ -743,13 +726,11 @@ class BackupCephTestCase(test.TestCase):
backup_name = self.service._get_backup_base_name(self.volume_id,
self.backup_id)
self.mock_rbd.RBD.list = mock.Mock()
self.mock_rbd.RBD.list.return_value = [backup_name]
self.mock_rbd.RBD.remove = mock.Mock()
self.mock_rbd.RBD.return_value.list.return_value = [backup_name]
with mock.patch.object(self.service, 'get_backup_snaps'):
self.service.delete(self.backup)
self.assertTrue(self.mock_rbd.RBD.remove.called)
self.assertTrue(self.mock_rbd.RBD.return_value.remove.called)
@common_mocks
def test_try_delete_base_image_busy(self):
@@ -757,10 +738,9 @@ class BackupCephTestCase(test.TestCase):
backup_name = self.service._get_backup_base_name(self.volume_id,
self.backup_id)
self.mock_rbd.RBD.list = mock.Mock()
self.mock_rbd.RBD.list.return_value = [backup_name]
self.mock_rbd.RBD.remove = mock.Mock()
self.mock_rbd.RBD.remove.side_effect = self.mock_rbd.ImageBusy
rbd = self.mock_rbd.RBD.return_value
rbd.list.return_value = [backup_name]
rbd.remove.side_effect = self.mock_rbd.ImageBusy
with mock.patch.object(self.service, 'get_backup_snaps') as \
mock_get_backup_snaps:
@@ -769,8 +749,8 @@ class BackupCephTestCase(test.TestCase):
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(rbd.list.called)
self.assertTrue(rbd.remove.called)
self.assertTrue(MockImageBusyException in RAISED_EXCEPTIONS)
@common_mocks
@@ -940,15 +920,12 @@ class BackupCephTestCase(test.TestCase):
glance_tag: {'image_name': 'image.glance'},
'version': version})
self.mock_rados.Object = mock.Mock
self.mock_rados.Object.read = mock.Mock()
self.mock_rados.Object.read.side_effect = mock_read
self.mock_rados.Object.stat = mock.Mock()
self.mock_rados.Object.return_value.read.side_effect = mock_read
self.service._restore_metadata(self.backup, self.volume_id)
self.assertTrue(self.mock_rados.Object.stat.called)
self.assertTrue(self.mock_rados.Object.read.called)
self.assertTrue(self.mock_rados.Object.return_value.stat.called)
self.assertTrue(self.mock_rados.Object.return_value.read.called)
version = 2
try:
@@ -1019,9 +996,7 @@ class BackupCephTestCase(test.TestCase):
glance_tag: {'image_name': 'image.glance'},
'version': 2})
self.mock_rados.Object = mock.Mock
self.mock_rados.Object.read = mock.Mock()
self.mock_rados.Object.read.side_effect = mock_read
self.mock_rados.Object.return_value.read.side_effect = mock_read
with mock.patch.object(ceph.VolumeMetadataBackup, '_exists') as \
mock_exists:
mock_exists.return_value = True
@@ -1032,7 +1007,7 @@ class BackupCephTestCase(test.TestCase):
self.assertTrue(mock_exists.called)
self.assertTrue(self.mock_rados.Object.read.called)
self.assertTrue(self.mock_rados.Object.return_value.read.called)
def common_meta_backup_mocks(f):
@@ -1042,12 +1017,11 @@ def common_meta_backup_mocks(f):
mocks that can't/don't get unset.
"""
def _common_inner_inner1(inst, *args, **kwargs):
@mock.patch('cinder.backup.drivers.ceph.rbd', spec=object)
@mock.patch('cinder.backup.drivers.ceph.rados', spec=object)
@mock.patch('cinder.backup.drivers.ceph.rbd')
@mock.patch('cinder.backup.drivers.ceph.rados')
def _common_inner_inner2(mock_rados, mock_rbd):
inst.mock_rados = mock_rados
inst.mock_rbd = mock_rbd
inst.mock_rados.Object = mock.Mock
inst.mock_rados.ObjectNotFound = MockObjectNotFoundException
return f(inst, *args, **kwargs)
@@ -1071,16 +1045,16 @@ class VolumeMetadataBackupTestCase(test.TestCase):
@common_meta_backup_mocks
def test_exists(self):
# True
with mock.patch.object(self.mock_rados.Object, 'stat') as mock_stat:
self.assertTrue(self.mb.exists)
self.assertTrue(mock_stat.called)
self.assertTrue(self.mb.exists)
self.assertTrue(self.mock_rados.Object.return_value.stat.called)
self.mock_rados.Object.return_value.reset_mock()
# False
with mock.patch.object(self.mock_rados.Object, 'stat') as mock_stat:
mock_stat.side_effect = self.mock_rados.ObjectNotFound
self.assertFalse(self.mb.exists)
self.assertTrue(mock_stat.called)
self.assertEqual(RAISED_EXCEPTIONS, [MockObjectNotFoundException])
self.mock_rados.Object.return_value.stat.side_effect = (
self.mock_rados.ObjectNotFound)
self.assertFalse(self.mb.exists)
self.assertTrue(self.mock_rados.Object.return_value.stat.called)
self.assertEqual(RAISED_EXCEPTIONS, [MockObjectNotFoundException])
@common_meta_backup_mocks
def test_set(self):
@@ -1120,14 +1094,12 @@ class VolumeMetadataBackupTestCase(test.TestCase):
@common_meta_backup_mocks
def test_get(self):
with mock.patch.object(self.mock_rados.Object, 'stat') as mock_stat:
mock_stat.side_effect = self.mock_rados.ObjectNotFound
with mock.patch.object(self.mock_rados.Object, 'read') as \
mock_read:
mock_read.return_value = 'meta'
self.assertIsNone(self.mb.get())
mock_stat.side_effect = None
self.assertEqual(self.mb.get(), 'meta')
self.mock_rados.Object.return_value.stat.side_effect = (
self.mock_rados.ObjectNotFound)
self.mock_rados.Object.return_value.read.return_value = 'meta'
self.assertIsNone(self.mb.get())
self.mock_rados.Object.return_value.stat.side_effect = None
self.assertEqual(self.mb.get(), 'meta')
@common_meta_backup_mocks
def remove_if_exists(self):

View File

@@ -81,11 +81,6 @@ def common_mocks(f):
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
@@ -167,7 +162,6 @@ class RBDTestCase(test.TestCase):
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)
@@ -177,16 +171,17 @@ class RBDTestCase(test.TestCase):
self.volume_size * units.Gi, order]
kwargs = {'old_format': False,
'features': self.mock_rbd.RBD_FEATURE_LAYERING}
self.mock_rbd.RBD.create.assert_called_once_with(*args, **kwargs)
self.mock_rbd.RBD.return_value.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_manage_existing_get_size(self):
with mock.patch.object(self.driver.rbd.Image, 'size') as \
with mock.patch.object(self.driver.rbd.Image(), 'size') as \
mock_rbd_image_size:
with mock.patch.object(self.driver.rbd.Image, 'close') \
with mock.patch.object(self.driver.rbd.Image(), 'close') \
as mock_rbd_image_close:
mock_rbd_image_size.return_value = 2 * units.Gi
existing_ref = {'source-name': self.volume_name}
@@ -200,9 +195,9 @@ class RBDTestCase(test.TestCase):
@common_mocks
def test_manage_existing_get_invalid_size(self):
with mock.patch.object(self.driver.rbd.Image, 'size') as \
with mock.patch.object(self.driver.rbd.Image(), 'size') as \
mock_rbd_image_size:
with mock.patch.object(self.driver.rbd.Image, 'close') \
with mock.patch.object(self.driver.rbd.Image(), 'close') \
as mock_rbd_image_close:
mock_rbd_image_size.return_value = 'abcd'
existing_ref = {'source-name': self.volume_name}
@@ -218,29 +213,24 @@ class RBDTestCase(test.TestCase):
client = self.mock_client.return_value
client.__enter__.return_value = client
with mock.patch.object(driver, 'RADOSClient') as mock_rados_client:
with mock.patch.object(self.driver.rbd.RBD(), 'rename') as \
mock_rbd_image_rename:
exist_volume = 'vol-exist'
existing_ref = {'source-name': exist_volume}
mock_rbd_image_rename.return_value = 0
mock_rbd_image_rename(mock_rados_client.ioctx,
exist_volume,
self.volume_name)
self.driver.manage_existing(self.volume, existing_ref)
mock_rbd_image_rename.assert_called_with(
mock_rados_client.ioctx,
exist_volume,
self.volume_name)
with mock.patch.object(self.driver.rbd.RBD(), 'rename') as \
mock_rbd_image_rename:
exist_volume = 'vol-exist'
existing_ref = {'source-name': exist_volume}
mock_rbd_image_rename.return_value = 0
self.driver.manage_existing(self.volume, existing_ref)
mock_rbd_image_rename.assert_called_with(
client.ioctx,
exist_volume,
self.volume_name)
@common_mocks
def test_manage_existing_with_exist_rbd_image(self):
client = self.mock_client.return_value
client.__enter__.return_value = client
self.mock_rbd.Image.rename = mock.Mock()
self.mock_rbd.Image.rename.side_effect = \
MockImageExistsException
self.mock_rbd.RBD.return_value.rename.side_effect = (
MockImageExistsException)
exist_volume = 'vol-exist'
existing_ref = {'source-name': exist_volume}
@@ -260,7 +250,6 @@ class RBDTestCase(test.TestCase):
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()
self.driver.create_volume(self.volume)
@@ -270,7 +259,8 @@ class RBDTestCase(test.TestCase):
self.volume_size * units.Gi, order]
kwargs = {'old_format': True,
'features': 0}
self.mock_rbd.RBD.create.assert_called_once_with(*args, **kwargs)
self.mock_rbd.RBD.return_value.create.assert_called_once_with(
*args, **kwargs)
client.__enter__.assert_called_once()
client.__exit__.assert_called_once()
mock_supports_layering.assert_called_once()
@@ -284,17 +274,14 @@ class RBDTestCase(test.TestCase):
rbd_image = self.driver.rbd.Image()
self.driver._delete_backup_snaps(rbd_image)
mock_get_backup_snaps.assert_called_once_with(rbd_image)
self.assertTrue(self.driver.rbd.Image.remove_snap.called)
self.assertTrue(
self.driver.rbd.Image.return_value.remove_snap.called)
@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 = []
self.driver.rbd.Image.close = mock.Mock()
self.driver.rbd.Image.remove = mock.Mock()
self.driver.rbd.Image.unprotect_snap = mock.Mock()
self.driver.rbd.Image.return_value.list_snaps.return_value = []
with mock.patch.object(self.driver, '_get_clone_info') as \
mock_get_clone_info:
@@ -305,12 +292,14 @@ class RBDTestCase(test.TestCase):
self.driver.delete_volume(self.volume)
mock_get_clone_info.assert_called_once()
self.driver.rbd.Image.list_snaps.assert_called_once()
(self.driver.rbd.Image.return_value
.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()
self.assertFalse(
self.driver.rbd.Image.return_value.unprotect_snap.called)
self.driver.rbd.RBD.return_value.remove.assert_called_once()
@common_mocks
def delete_volume_not_found(self):
@@ -322,12 +311,10 @@ class RBDTestCase(test.TestCase):
@common_mocks
def test_delete_busy_volume(self):
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.Image.return_value.list_snaps.return_value = []
self.mock_rbd.RBD.remove = mock.Mock()
self.mock_rbd.RBD.remove.side_effect = self.mock_rbd.ImageBusy
self.mock_rbd.RBD.return_value.remove.side_effect = (
self.mock_rbd.ImageBusy)
with mock.patch.object(self.driver, '_get_clone_info') as \
mock_get_clone_info:
@@ -340,11 +327,13 @@ class RBDTestCase(test.TestCase):
self.driver.delete_volume, self.volume)
mock_get_clone_info.assert_called_once()
self.mock_rbd.Image.list_snaps.assert_called_once()
(self.mock_rbd.Image.return_value.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()
self.assertFalse(
self.mock_rbd.Image.return_value.unprotect_snap.called)
self.mock_rbd.RBD.return_value.remove.assert_called_once()
# Make sure the exception was raised
self.assertEqual(RAISED_EXCEPTIONS,
[self.mock_rbd.ImageBusy])
@@ -473,30 +462,25 @@ class RBDTestCase(test.TestCase):
dst_name = u'volume-00000002'
self.cfg.rbd_max_clone_depth = 1
self.mock_rbd.RBD.clone = mock.Mock()
self.mock_rbd.RBD.clone.side_effect = self.mock_rbd.RBD.Error
self.mock_rbd.RBD.return_value.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.mock_rbd.Image.return_value.create_snap.assert_called_once()
self.mock_rbd.Image.return_value.protect_snap.assert_called_once()
self.mock_rbd.RBD.return_value.clone.assert_called_once()
(self.mock_rbd.Image.return_value
.unprotect_snap.assert_called_once())
self.mock_rbd.Image.return_value.remove_snap.assert_called_once()
self.mock_rbd.Image.return_value.close.assert_called_once()
self.assertTrue(mock_get_clone_depth.called)
@common_mocks
@@ -505,19 +489,13 @@ class RBDTestCase(test.TestCase):
dst_name = u'volume-00000002'
self.cfg.rbd_max_clone_depth = 2
self.mock_rbd.RBD.clone = mock.Mock()
self.mock_rbd.RBD.clone.side_effect = self.mock_rbd.RBD.Error
self.mock_rbd.RBD.return_value.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))
@@ -575,7 +553,8 @@ class RBDTestCase(test.TestCase):
mock_get_fsid.return_value = 'abc'
location = 'rbd://abc/pool/image/snap'
self.mock_proxy.side_effect = self.mock_rbd.Error
self.driver.rbd.Error = Exception
self.mock_proxy.side_effect = Exception
args = [location, {'disk_format': 'raw'}]
self.assertFalse(self.driver._is_cloneable(*args))
@@ -717,14 +696,13 @@ class RBDTestCase(test.TestCase):
# capture both rados client used to perform the clone
client.__enter__.side_effect = mock__enter__(client)
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.mock_rbd.RBD_FEATURE_LAYERING}
self.mock_rbd.RBD.clone.assert_called_once_with(*args, **kwargs)
self.mock_rbd.RBD.return_value.clone.assert_called_once_with(
*args, **kwargs)
self.assertEqual(client.__enter__.call_count, 2)
@common_mocks
@@ -778,44 +756,43 @@ class RBDTestCase(test.TestCase):
# Default
self.cfg.rados_connect_timeout = -1
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
self.mock_rados.Rados.return_value.open_ioctx.return_value = \
self.mock_rados.Rados.return_value.ioctx
# default configured pool
ret = self.driver._connect_to_rados()
self.assertTrue(self.mock_rados.Rados.connect.called)
self.assertTrue(self.mock_rados.Rados.return_value.connect.called)
# Expect no timeout if default is used
self.mock_rados.Rados.connect.assert_called_once_with()
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)
self.mock_rados.Rados.return_value.connect.assert_called_once_with()
self.assertTrue(self.mock_rados.Rados.return_value.open_ioctx.called)
self.assertEqual(ret[1], self.mock_rados.Rados.return_value.ioctx)
self.mock_rados.Rados.return_value.open_ioctx.assert_called_with(
self.cfg.rbd_pool)
# different pool
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')
self.assertTrue(self.mock_rados.Rados.return_value.connect.called)
self.assertTrue(self.mock_rados.Rados.return_value.open_ioctx.called)
self.assertEqual(ret[1], self.mock_rados.Rados.return_value.ioctx)
self.mock_rados.Rados.return_value.open_ioctx.assert_called_with(
'alt_pool')
# With timeout
self.cfg.rados_connect_timeout = 1
self.mock_rados.Rados.connect.reset_mock()
self.mock_rados.Rados.return_value.connect.reset_mock()
self.driver._connect_to_rados()
self.mock_rados.Rados.connect.assert_called_once_with(timeout=1)
self.mock_rados.Rados.return_value.connect.assert_called_once_with(
timeout=1)
# error
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.mock_rados.Rados.return_value.open_ioctx.reset_mock()
self.mock_rados.Rados.return_value.shutdown.reset_mock()
self.mock_rados.Rados.return_value.open_ioctx.side_effect = (
self.mock_rados.Error)
self.assertRaises(exception.VolumeBackendAPIException,
self.driver._connect_to_rados)
self.mock_rados.Rados.open_ioctx.assert_called_once()
self.mock_rados.Rados.shutdown.assert_called_once()
self.mock_rados.Rados.return_value.open_ioctx.assert_called_once()
self.mock_rados.Rados.return_value.shutdown.assert_called_once()
class RBDImageIOWrapperTestCase(test.TestCase):