diff options
author | Rajat Dhasmana <rajatdhasmana@gmail.com> | 2022-10-13 14:05:02 +0000 |
---|---|---|
committer | Rajat Dhasmana <rajatdhasmana@gmail.com> | 2023-04-06 15:15:05 +0000 |
commit | 27ab8a6aeb7a59bc56ed0ad26ffb5a83d426b447 (patch) | |
tree | ec4fc3a26b070edb4a97b03c7a970c19b51c9a95 /glance_store/tests | |
parent | 1f56f5a4239a83f7aee2d4dab73b7ebaf25a3adc (diff) | |
download | glance_store-27ab8a6aeb7a59bc56ed0ad26ffb5a83d426b447.tar.gz |
RBD: Wrap RBD calls in native threads
librbd methods call lower level C code which runs in native thread
and isn't aware about the eventlet threads hence hangs the eventlet loop
until the native thread is executed.
This could cause problems when we are creating multiple images
with large size where one call to librados can cause the process to
hang and other operations can starve for execution and error out.
This patch wraps each RBD call in it's own native thread that won't
affect other RBD call from executing.
Change-Id: I8efb0460df9fcba050b5ce949eb10caea325c851
Diffstat (limited to 'glance_store/tests')
-rw-r--r-- | glance_store/tests/unit/test_rbd_store.py | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/glance_store/tests/unit/test_rbd_store.py b/glance_store/tests/unit/test_rbd_store.py index 08ade51..09eddc4 100644 --- a/glance_store/tests/unit/test_rbd_store.py +++ b/glance_store/tests/unit/test_rbd_store.py @@ -692,3 +692,53 @@ class TestStore(base.StoreBaseTest, self.assertEqual(self.called_commands_expected, self.called_commands_actual) super(TestStore, self).tearDown() + + def test_create_image_in_native_thread(self): + # Tests that we use non-0 features from ceph.conf and cast to int. + fsid = 'fake' + features = '3' + conf_get_mock = mock.Mock(return_value=features) + conn = mock.Mock(conf_get=conf_get_mock) + ioctxt = mock.sentinel.ioctxt + name = '1' + size = 1024 + order = 3 + fake_proxy = mock.MagicMock() + fake_rbd = mock.MagicMock() + + with mock.patch.object(rbd_store.tpool, 'Proxy') as tpool_mock, \ + mock.patch.object(rbd_store.rbd, 'RBD') as rbd_mock: + tpool_mock.return_value = fake_proxy + rbd_mock.return_value = fake_rbd + location = self.store._create_image( + fsid, conn, ioctxt, name, size, order) + self.assertEqual(fsid, location.specs['fsid']) + self.assertEqual(rbd_store.DEFAULT_POOL, location.specs['pool']) + self.assertEqual(name, location.specs['image']) + self.assertEqual(rbd_store.DEFAULT_SNAPNAME, + location.specs['snapshot']) + + tpool_mock.assert_called_once_with(fake_rbd) + fake_proxy.create.assert_called_once_with(ioctxt, name, size, order, + old_format=False, features=3) + + def test_delete_image_in_native_thread(self): + fake_proxy = mock.MagicMock() + fake_rbd = mock.MagicMock() + fake_ioctx = mock.MagicMock() + + with mock.patch.object(rbd_store.tpool, 'Proxy') as tpool_mock, \ + mock.patch.object(rbd_store.rbd, 'RBD') as rbd_mock, \ + mock.patch.object(self.store, 'get_connection') as mock_conn: + + mock_get_conn = mock_conn.return_value.__enter__.return_value + mock_ioctx = mock_get_conn.open_ioctx.return_value.__enter__ + mock_ioctx.return_value = fake_ioctx + tpool_mock.return_value = fake_proxy + rbd_mock.return_value = fake_rbd + + self.store._delete_image('fake_pool', self.location.image) + + tpool_mock.assert_called_once_with(fake_rbd) + fake_proxy.remove.assert_called_once_with(fake_ioctx, + self.location.image) |