summaryrefslogtreecommitdiff
path: root/glance_store
diff options
context:
space:
mode:
authorwhoami-rajat <rajatdhasmana@gmail.com>2022-03-17 14:11:15 +0530
committerwhoami-rajat <rajatdhasmana@gmail.com>2022-03-22 14:37:38 +0530
commitf9253a4adea0cc8cb84b17b7c95ee600224f19a0 (patch)
treeaa411f4174c9a6a732cffc9c476ef363c243ba94 /glance_store
parent4bd0304efbdfb98e2742741af42b483708f48a41 (diff)
downloadglance_store-f9253a4adea0cc8cb84b17b7c95ee600224f19a0.tar.gz
Add coverage for add method
This patch adds test coverage of code paths like extend volume, exception blocks, when image_size is zero, volume delete call etc Change-Id: I59b1579dc9877668b82d4195431c14cc41cfe892
Diffstat (limited to 'glance_store')
-rw-r--r--glance_store/tests/unit/test_cinder_base.py167
-rw-r--r--glance_store/tests/unit/test_cinder_store.py3
-rw-r--r--glance_store/tests/unit/test_multistore_cinder.py3
3 files changed, 173 insertions, 0 deletions
diff --git a/glance_store/tests/unit/test_cinder_base.py b/glance_store/tests/unit/test_cinder_base.py
index 245372d..d9e6c2d 100644
--- a/glance_store/tests/unit/test_cinder_base.py
+++ b/glance_store/tests/unit/test_cinder_base.py
@@ -570,6 +570,173 @@ class TestCinderStoreBase(object):
if is_multi_store:
self.assertEqual(backend, metadata["store"])
+ def test_cinder_add_volume_not_found(self):
+ image_file = mock.MagicMock()
+ fake_image_id = str(uuid.uuid4())
+ expected_size = 0
+ fake_volumes = mock.MagicMock(create=mock.MagicMock(
+ side_effect=cinder.cinder_exception.NotFound(code=404)))
+
+ with mock.patch.object(cinder.Store, 'get_cinderclient') as mock_cc:
+ mock_cc.return_value = mock.MagicMock(volumes=fake_volumes)
+ self.assertRaises(
+ exceptions.BackendException, self.store.add,
+ fake_image_id, image_file, expected_size, self.hash_algo,
+ self.context, None)
+
+ def _test_cinder_add_extend(self, is_multi_store=False):
+
+ expected_volume_size = 2 * units.Gi
+ expected_multihash = 'fake_hash'
+
+ fakebuffer = mock.MagicMock()
+ fakebuffer.__len__.return_value = expected_volume_size
+
+ def get_fake_hash(type, secure=False):
+ if type == 'md5':
+ return mock.MagicMock(hexdigest=lambda: expected_checksum)
+ else:
+ return mock.MagicMock(hexdigest=lambda: expected_multihash)
+
+ expected_image_id = str(uuid.uuid4())
+ expected_volume_id = str(uuid.uuid4())
+ expected_size = 0
+ image_file = mock.MagicMock(
+ read=mock.MagicMock(side_effect=[fakebuffer, None]))
+ fake_volume = mock.MagicMock(id=expected_volume_id, status='available',
+ size=1)
+ expected_checksum = 'fake_checksum'
+ verifier = None
+ backend = 'glance_store'
+
+ expected_location = 'cinder://%s' % fake_volume.id
+ if is_multi_store:
+ # Default backend is 'glance_store' for single store but in case
+ # of multi store, if the backend option is not passed, we should
+ # assign it to the default i.e. 'cinder1'
+ backend = 'cinder1'
+ expected_location = 'cinder://%s/%s' % (backend, fake_volume.id)
+ self.config(cinder_volume_type='some_type', group=backend)
+
+ fake_client = mock.MagicMock(auth_token=None, management_url=None)
+ fake_volume.manager.get.return_value = fake_volume
+ fake_volumes = mock.MagicMock(create=mock.Mock(
+ return_value=fake_volume))
+
+ @contextlib.contextmanager
+ def fake_open(client, volume, mode):
+ self.assertEqual('wb', mode)
+ yield mock.MagicMock()
+
+ with mock.patch.object(cinder.Store, 'get_cinderclient') as mock_cc, \
+ mock.patch.object(self.store, '_open_cinder_volume',
+ side_effect=fake_open), \
+ mock.patch.object(cinder.Store, '_wait_resize_device'), \
+ mock.patch.object(cinder.utils, 'get_hasher') as fake_hasher, \
+ mock.patch.object(cinder.Store, '_wait_volume_status',
+ return_value=fake_volume) as mock_wait:
+ mock_cc.return_value = mock.MagicMock(client=fake_client,
+ volumes=fake_volumes)
+
+ fake_hasher.side_effect = get_fake_hash
+ loc, size, checksum, multihash, metadata = self.store.add(
+ expected_image_id, image_file, expected_size, self.hash_algo,
+ self.context, verifier)
+ self.assertEqual(expected_location, loc)
+ self.assertEqual(expected_volume_size, size)
+ self.assertEqual(expected_checksum, checksum)
+ self.assertEqual(expected_multihash, multihash)
+ fake_volumes.create.assert_called_once_with(
+ 1,
+ name='image-%s' % expected_image_id,
+ metadata={'image_owner': self.context.project_id,
+ 'glance_image_id': expected_image_id,
+ 'image_size': str(expected_volume_size)},
+ volume_type='some_type')
+ if is_multi_store:
+ self.assertEqual(backend, metadata["store"])
+ fake_volume.extend.assert_called_once_with(
+ fake_volume, expected_volume_size // units.Gi)
+ mock_wait.assert_has_calls(
+ [mock.call(fake_volume, 'creating', 'available'),
+ mock.call(fake_volume, 'extending', 'available')])
+
+ def test_cinder_add_extend_storage_full(self):
+
+ expected_volume_size = 2 * units.Gi
+
+ fakebuffer = mock.MagicMock()
+ fakebuffer.__len__.return_value = expected_volume_size
+
+ expected_image_id = str(uuid.uuid4())
+ expected_volume_id = str(uuid.uuid4())
+ expected_size = 0
+ image_file = mock.MagicMock(
+ read=mock.MagicMock(side_effect=[fakebuffer, None]))
+ fake_volume = mock.MagicMock(id=expected_volume_id, status='available',
+ size=1)
+ verifier = None
+
+ fake_client = mock.MagicMock()
+ fake_volume.manager.get.return_value = fake_volume
+ fake_volumes = mock.MagicMock(create=mock.Mock(
+ return_value=fake_volume))
+
+ with mock.patch.object(cinder.Store, 'get_cinderclient') as mock_cc, \
+ mock.patch.object(self.store, '_open_cinder_volume'), \
+ mock.patch.object(cinder.Store, '_wait_resize_device'), \
+ mock.patch.object(cinder.utils, 'get_hasher'), \
+ mock.patch.object(
+ cinder.Store, '_wait_volume_status') as mock_wait:
+
+ mock_cc.return_value = mock.MagicMock(client=fake_client,
+ volumes=fake_volumes)
+
+ mock_wait.side_effect = [fake_volume, exceptions.BackendException]
+ self.assertRaises(
+ exceptions.StorageFull, self.store.add, expected_image_id,
+ image_file, expected_size, self.hash_algo, self.context,
+ verifier)
+
+ def test_cinder_add_extend_volume_delete_exception(self):
+
+ expected_volume_size = 2 * units.Gi
+
+ fakebuffer = mock.MagicMock()
+ fakebuffer.__len__.return_value = expected_volume_size
+
+ expected_image_id = str(uuid.uuid4())
+ expected_volume_id = str(uuid.uuid4())
+ expected_size = 0
+ image_file = mock.MagicMock(
+ read=mock.MagicMock(side_effect=[fakebuffer, None]))
+ fake_volume = mock.MagicMock(
+ id=expected_volume_id, status='available', size=1,
+ delete=mock.MagicMock(side_effect=Exception()))
+
+ fake_client = mock.MagicMock()
+ fake_volume.manager.get.return_value = fake_volume
+ fake_volumes = mock.MagicMock(create=mock.Mock(
+ return_value=fake_volume))
+ verifier = None
+
+ with mock.patch.object(cinder.Store, 'get_cinderclient') as mock_cc, \
+ mock.patch.object(self.store, '_open_cinder_volume'), \
+ mock.patch.object(cinder.Store, '_wait_resize_device'), \
+ mock.patch.object(cinder.utils, 'get_hasher'), \
+ mock.patch.object(
+ cinder.Store, '_wait_volume_status') as mock_wait:
+
+ mock_cc.return_value = mock.MagicMock(client=fake_client,
+ volumes=fake_volumes)
+
+ mock_wait.side_effect = [fake_volume, exceptions.BackendException]
+ self.assertRaises(
+ Exception, self.store.add, expected_image_id, # noqa
+ image_file, expected_size, self.hash_algo, self.context,
+ verifier)
+ fake_volume.delete.assert_called_once()
+
def _test_cinder_delete(self, is_multi_store=False):
fake_client = mock.MagicMock(auth_token=None, management_url=None)
fake_volume_uuid = str(uuid.uuid4())
diff --git a/glance_store/tests/unit/test_cinder_store.py b/glance_store/tests/unit/test_cinder_store.py
index 25e098c..efd5419 100644
--- a/glance_store/tests/unit/test_cinder_store.py
+++ b/glance_store/tests/unit/test_cinder_store.py
@@ -145,6 +145,9 @@ class TestCinderStore(base.StoreBaseTest,
fail_resize=True)
fake_volume.delete.assert_called_once()
+ def test_cinder_add_extend(self):
+ self._test_cinder_add_extend()
+
def test_cinder_delete(self):
self._test_cinder_delete()
diff --git a/glance_store/tests/unit/test_multistore_cinder.py b/glance_store/tests/unit/test_multistore_cinder.py
index 40e6f51..9161275 100644
--- a/glance_store/tests/unit/test_multistore_cinder.py
+++ b/glance_store/tests/unit/test_multistore_cinder.py
@@ -283,6 +283,9 @@ class TestMultiCinderStore(base.MultiStoreBaseTest,
fail_resize=True, is_multi_store=True)
fake_volume.delete.assert_called_once()
+ def test_cinder_add_extend(self):
+ self._test_cinder_add_extend(is_multi_store=True)
+
def test_cinder_delete(self):
self._test_cinder_delete(is_multi_store=True)