Make libvirt Tpool proxying 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.

The patch_tpool_proxy() logic is removed from the libvirt driver as it
was only needed for python old style classes which is not in use any
more in python3 and the issue is not reproducible any more with
virConnect even without the patching.

❯ python3
Python 3.12.10 (main, Apr  9 2025, 04:44:59) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import eventlet
>>> eventlet.monkey_patch()
>>> from nova.virt.libvirt import host
>>> h = host.Host(uri="qemu:///system")
>>> h.get_connection()
libvirt:  error : internal error: could not initialize domain event timer
URI qemu:///system does not support events: internal error: could not initialize domain event timer
<libvirt.virConnect object at 0x7f829e94c170>
>>> c = h.get_connection()
>>> str(c)
'<libvirt.virConnect object at 0x7f829e94c170>'
>>>

Signed-off-by: Balazs Gibizer <gibi@redhat.com>
Change-Id: Ic60ab78cec2a9f9ba177568b69e738425e56cae1
This commit is contained in:
Balazs Gibizer
2025-07-27 16:05:12 +02:00
parent 8c8047ce2a
commit eda6792632
6 changed files with 30 additions and 65 deletions
@@ -29998,6 +29998,16 @@ class LibvirtNonblockingTestCase(test.NoDBTestCase):
group='libvirt')
def test_connection_to_primitive(self):
if utils.concurrency_mode_threading():
self.skipTest(
"In threading mode nova does not use eventlet.tpool to "
"wrap the libvirt calls. This test case asserts that the "
"libvirt connection having eventlet.tpool.Proxy objects "
"are serializable. See "
"https://bugs.launchpad.net/nova/+bug/962840. "
"As Proxy object is not present in threading mode this test "
"is not valid. ")
# Test bug 962840.
import nova.virt.libvirt.driver as libvirt_driver
drvr = libvirt_driver.LibvirtDriver('')
@@ -30007,6 +30017,13 @@ class LibvirtNonblockingTestCase(test.NoDBTestCase):
@mock.patch.object(eventlet.tpool, 'execute')
@mock.patch.object(objects.Service, 'get_by_compute_host')
def test_tpool_execute_calls_libvirt(self, mock_svc, mock_execute):
if utils.concurrency_mode_threading():
self.skipTest(
"In threading mode nova does not use eventlet.tpool to "
"wrap the libvirt calls. This test case asserts that libvirt "
"connect goes through the tpool, so in threading mode this "
"test case is invalid.")
conn = fakelibvirt.virConnect()
conn.is_expected = True
@@ -2298,6 +2298,13 @@ class TestLibvirtSEVESSupported(TestLibvirtSEV):
class LibvirtTpoolProxyTestCase(test.NoDBTestCase):
def setUp(self):
if utils.concurrency_mode_threading():
self.skipTest(
"In threading mode nova does not use eventlet.tpool.Proxy to "
"wrap the libvirt calls. This test asserts that such calls "
"are returning Proxy objects. So these test cases are not "
"valid.")
super(LibvirtTpoolProxyTestCase, self).setUp()
self.useFixture(nova_fixtures.LibvirtFixture())
+2 -2
View File
@@ -1290,11 +1290,11 @@ def _log_executor_stats(executor):
executor._delayed_work.unfinished_tasks, stats)
def tpool_wrap(target):
def tpool_wrap(target, autowrap=()):
"""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)
return tpool.Proxy(target, autowrap=autowrap)
-19
View File
@@ -48,7 +48,6 @@ import uuid
from castellan import key_manager
from copy import deepcopy
from eventlet import tpool
from lxml import etree
from os_brick import encryptors
from os_brick.encryptors import luks as luks_encryptor
@@ -193,24 +192,6 @@ VOLUME_DRIVERS = {
}
def patch_tpool_proxy():
"""eventlet.tpool.Proxy doesn't work with old-style class in __str__()
or __repr__() calls. See bug #962840 for details.
We perform a monkey patch to replace those two instance methods.
"""
def str_method(self):
return str(self._obj)
def repr_method(self):
return repr(self._obj)
tpool.Proxy.__str__ = str_method
tpool.Proxy.__repr__ = repr_method
patch_tpool_proxy()
# For information about when MIN_{LIBVIRT,QEMU}_VERSION and
# NEXT_MIN_{LIBVIRT,QEMU}_VERSION can be changed, consult the following:
#
+1 -2
View File
@@ -41,7 +41,6 @@ import typing as ty
from eventlet import greenio
from eventlet import greenthread
from eventlet import patcher
from eventlet import tpool
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import excutils
@@ -195,7 +194,7 @@ class Host(object):
# eventlet's event loop, starving all other greenthreads until
# completion. eventlet's tpool.Proxy handles this situation for us by
# executing proxied calls in a native thread.
return tpool.Proxy(obj, autowrap=self._libvirt_proxy_classes)
return utils.tpool_wrap(obj, autowrap=self._libvirt_proxy_classes)
def _native_thread(self):
"""Receives async events coming in from libvirtd.
+3 -42
View File
@@ -2,9 +2,11 @@ nova.tests.unit.console.rfb.test_authvencrypt.RFBAuthSchemeVeNCryptTestCase.test
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.test_context.ContextTestCase.test_scatter_gather_cells_queued_task_cancelled
# Wait until eventlet.Event is removed by https://review.opendev.org/c/openstack/nova/+/949754
nova.tests.unit.virt.libvirt.test_driver.CacheConcurrencyTestCase.test_different_fname_concurrency
nova.tests.unit.virt.libvirt.test_driver.CacheConcurrencyTestCase.test_same_fname_concurrency
nova.tests.unit.virt.libvirt.test_driver.LibvirtDriverTestCase.test_rescue
nova.tests.unit.virt.libvirt.test_driver.TestUpdateProviderTree.test_image_cache_disk_reservation
nova.tests.unit.virt.libvirt.test_driver.TestUpdateProviderTree.test_update_provider_tree
nova.tests.unit.virt.libvirt.test_driver.TestUpdateProviderTree.test_update_provider_tree_for_pcpu_reshape
@@ -18,47 +20,6 @@ nova.tests.unit.virt.libvirt.test_driver.TestUpdateProviderTree.test_update_prov
nova.tests.unit.virt.libvirt.volume.test_mount.HostMountStateTestCase.test_mount_concurrent
nova.tests.unit.virt.libvirt.volume.test_mount.HostMountStateTestCase.test_mount_concurrent_no_interfere
nova.tests.unit.virt.libvirt.volume.test_mount.MountManagerTestCase.test_host_up_waits_for_completion
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_attach_detach_different_power_states
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_attach_detach_volume
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_block_stats
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_destroy_instance
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_force_hard_reboot
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_console_output
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_diagnostics
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_info
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_instance_diagnostics
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_instance_disk_info
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_mks_console
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_serial_console
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_spice_console
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_get_vnc_console
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_live_migration
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_live_migration_force_complete
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_pause
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_poll_rebooting_instances
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_power_off
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_power_on_powered_off
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_power_on_running
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_reboot
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_rescue
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_restore_running
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_restore_soft_deleted
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_resume_state_on_host_boot
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_resume_suspended_instance
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_resume_unsuspended_instance
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_set_admin_password
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_snapshot_running
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_soft_delete
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_spawn
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_suspend
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_swap_volume
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_trigger_crash_dump
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_unpause_paused_instance
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_unpause_unpaused_instance
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_unplug_vifs_with_destroy_vifs_false
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_unplug_vifs_with_destroy_vifs_true
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_unrescue_rescued_instance
nova.tests.unit.virt.test_virt_drivers.LibvirtConnTestCase.test_unrescue_unrescued_instance
nova.tests.unit.virt.vmwareapi.test_vm_util.VMwareVMUtilTestCase.test_create_vm_invalid_guestid
# Independent failure ~10% with multiple possible error:
# - sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) not an error