From 8c8047ce2afae18ffb272d0e972d63c8acde6e33 Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Sun, 27 Jul 2025 15:33:06 +0200 Subject: [PATCH] Make RBD Tpool usage conditional When running in eventlet mode we keep the original eventlet.tpool usage but when running in threading mode we call the functions directly on the thread of the caller. Signed-off-by: Balazs Gibizer Change-Id: I08f257d49c87d0d8a87127f61157b1b0b5ca7b3c --- nova/storage/rbd_utils.py | 10 ++++------ nova/tests/unit/storage/test_rbd.py | 6 +++++- nova/tests/unit/test_utils.py | 16 ++++++++++++++++ nova/utils.py | 10 ++++++++++ threading_unit_test_excludes.txt | 7 ------- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/nova/storage/rbd_utils.py b/nova/storage/rbd_utils.py index d0436c8e90..9a34526a04 100644 --- a/nova/storage/rbd_utils.py +++ b/nova/storage/rbd_utils.py @@ -16,8 +16,6 @@ import urllib -from eventlet import tpool - from oslo_concurrency import processutils from oslo_log import log as logging from oslo_serialization import jsonutils @@ -28,6 +26,7 @@ from oslo_utils import excutils import nova.conf from nova import exception from nova.i18n import _ +from nova import utils try: import rados @@ -52,7 +51,7 @@ class RbdProxy(object): """ def __init__(self): - self._rbd = tpool.Proxy(rbd.RBD()) + self._rbd = utils.tpool_wrap(rbd.RBD()) def __getattr__(self, attr): return getattr(self._rbd, attr) @@ -72,9 +71,8 @@ class RBDVolumeProxy(object): read_only=False): client, ioctx = driver._connect_to_rados(pool) try: - self.volume = tpool.Proxy(rbd.Image(ioctx, name, - snapshot=snapshot, - read_only=read_only)) + self.volume = utils.tpool_wrap( + rbd.Image(ioctx, name, snapshot=snapshot, read_only=read_only)) except rbd.ImageNotFound: with excutils.save_and_reraise_exception(): LOG.debug("rbd image %s does not exist", name) diff --git a/nova/tests/unit/storage/test_rbd.py b/nova/tests/unit/storage/test_rbd.py index 923b09b846..6fd15a83fb 100644 --- a/nova/tests/unit/storage/test_rbd.py +++ b/nova/tests/unit/storage/test_rbd.py @@ -22,6 +22,7 @@ from nova import exception from nova import objects from nova.storage import rbd_utils from nova import test +from nova import utils CEPH_MON_DUMP = r"""dumped monmap epoch 1 @@ -147,7 +148,10 @@ class RbdTestCase(test.NoDBTestCase): def test_rbdproxy_wraps_rbd(self): proxy = rbd_utils.RbdProxy() - self.assertIsInstance(proxy._rbd, tpool.Proxy) + if utils.concurrency_mode_threading(): + self.assertEqual(proxy._rbd, self.mock_rbd.RBD.return_value) + else: + self.assertIsInstance(proxy._rbd, tpool.Proxy) def test_rbdproxy_attribute_access_proxying(self): client = mock.MagicMock(ioctx='fake_ioctx') diff --git a/nova/tests/unit/test_utils.py b/nova/tests/unit/test_utils.py index 8a5d120602..32827593a5 100644 --- a/nova/tests/unit/test_utils.py +++ b/nova/tests/unit/test_utils.py @@ -232,6 +232,22 @@ class GenericUtilsTestCase(test.NoDBTestCase): project_id = '9b9e3c847e904b0686e8ffb20e4c6381' self.assertEqual('', utils.generate_hostid(None, project_id)) + @mock.patch('nova.utils.concurrency_mode_threading', return_value=False) + def test_tpool_wrap_eventlet(self, mock_concurrency_mode): + mock_target = mock.MagicMock() + target = utils.tpool_wrap(mock_target) + + self.assertEqual(target._obj, mock_target) + mock_concurrency_mode.assert_called_once_with() + + @mock.patch('nova.utils.concurrency_mode_threading', return_value=True) + def test_tpool_wrap_threading(self, mock_concurrency_mode): + mock_target = mock.MagicMock() + target = utils.tpool_wrap(mock_target) + + self.assertEqual(target, mock_target) + mock_concurrency_mode.assert_called_once_with() + class TestCachedFile(test.NoDBTestCase): @mock.patch('os.path.getmtime', return_value=1) diff --git a/nova/utils.py b/nova/utils.py index ae4fea3752..792095dd10 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -1288,3 +1288,13 @@ def _log_executor_stats(executor): name, len(executor._pool.coroutines_running), executor._pool.size, executor._delayed_work.unfinished_tasks, stats) + + +def tpool_wrap(target): + """Wrap the target into an eventlet Tpool Proxy object if running + in eventlet mode. In threading mode no wrapping is applied. + """ + if concurrency_mode_threading(): + return target + else: + return tpool.Proxy(target) diff --git a/threading_unit_test_excludes.txt b/threading_unit_test_excludes.txt index 9f3417ced3..4d88fcfab8 100644 --- a/threading_unit_test_excludes.txt +++ b/threading_unit_test_excludes.txt @@ -1,13 +1,6 @@ nova.tests.unit.console.rfb.test_authvencrypt.RFBAuthSchemeVeNCryptTestCase.test_security_handshake_fails_on_ssl_failure nova.tests.unit.console.rfb.test_authvencrypt.RFBAuthSchemeVeNCryptTestCase.test_security_handshake_without_x509 nova.tests.unit.console.rfb.test_authvencrypt.RFBAuthSchemeVeNCryptTestCase.test_security_handshake_with_x509 -nova.tests.unit.storage.test_rbd.RbdTestCase.test_cleanup_volumes -nova.tests.unit.storage.test_rbd.RbdTestCase.test_cleanup_volumes_fail_not_found -nova.tests.unit.storage.test_rbd.RbdTestCase.test_cleanup_volumes_fail_other -nova.tests.unit.storage.test_rbd.RbdTestCase.test_cleanup_volumes_fail_snapshots -nova.tests.unit.storage.test_rbd.RbdTestCase.test_cleanup_volumes_pending_resize -nova.tests.unit.storage.test_rbd.RbdTestCase.test_cleanup_volumes_reverting_resize -nova.tests.unit.storage.test_rbd.RbdTestCase.test_destroy_volume nova.tests.unit.test_context.ContextTestCase.test_scatter_gather_cells_queued_task_cancelled nova.tests.unit.virt.libvirt.test_driver.CacheConcurrencyTestCase.test_different_fname_concurrency nova.tests.unit.virt.libvirt.test_driver.CacheConcurrencyTestCase.test_same_fname_concurrency