Use of logging in native thread causes deadlock connecting to libvirtd

When connecting to libvirtd daemon we were calling the _connect
method in a native thread. The use of logging in this method hit this
bug in eventlet https://bitbucket.org/eventlet/eventlet/issue/137/
causing nova-compute to hang.

Closes-Bug: #1252409

Conflicts:
        nova/virt/libvirt/driver.py

NOTE(mriedem): The conflict is due to set_host_enabled
being used in the original change in Icehouse and the
option rename for libvirt_nonblocking.

Change-Id: I0d22c3ed1b3288aeb1afae130f11a4f38dc6440a
(cherry picked from commit e4b0d8e944)
This commit is contained in:
Michael Kerrin 2013-11-18 17:25:50 +00:00 committed by Matt Riedemann
parent fd5b2bd67f
commit 48d19691e2
2 changed files with 23 additions and 7 deletions

View File

@ -7391,6 +7391,19 @@ class LibvirtNonblockingTestCase(test.TestCase):
connection = libvirt_driver.LibvirtDriver('')
jsonutils.to_primitive(connection._conn, convert_instances=True)
def test_tpool_execute_calls_libvirt(self):
self.mox.StubOutWithMock(eventlet.tpool, 'execute')
conn = libvirt.virConnect()
conn.is_expected = True
eventlet.tpool.execute(
libvirt.openAuth, 'test:///default',
mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn)
self.mox.ReplayAll()
driver = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
c = driver._get_connection()
self.assertEqual(True, c.is_expected)
class LibvirtVolumeSnapshotTestCase(test.TestCase):
"""Tests for libvirtDriver.volume_snapshot_create/delete."""

View File

@ -583,12 +583,7 @@ class LibvirtDriver(driver.ComputeDriver):
def _get_new_connection(self):
# call with _wrapped_conn_lock held
LOG.debug(_('Connecting to libvirt: %s'), self.uri())
if not CONF.libvirt_nonblocking:
wrapped_conn = self._connect(self.uri(), self.read_only)
else:
wrapped_conn = tpool.proxy_call(
(libvirt.virDomain, libvirt.virConnect),
self._connect, self.uri(), self.read_only)
wrapped_conn = self._connect(self.uri(), self.read_only)
self._wrapped_conn = wrapped_conn
@ -685,7 +680,15 @@ class LibvirtDriver(driver.ComputeDriver):
flags = 0
if read_only:
flags = libvirt.VIR_CONNECT_RO
return libvirt.openAuth(uri, auth, flags)
if not CONF.libvirt_nonblocking:
return libvirt.openAuth(uri, auth, flags)
else:
# tpool.proxy_call creates a native thread. Due to limitations
# with eventlet locking we cannot use the logging API inside
# the called function.
return tpool.proxy_call(
(libvirt.virDomain, libvirt.virConnect),
libvirt.openAuth, uri, auth, flags)
except libvirt.libvirtError as ex:
LOG.exception(_("Connection to libvirt failed: %s"), ex)
payload = dict(ip=LibvirtDriver.get_host_ip_addr(),