libvirt: Wrap un-proxied listDevices() and listAllDevices()
This is similar to change I668643c836d46a25df46d4c99a973af5e50a39db where the objects returned in a list from a libvirt call were not tpool.Proxy wrapped. Because the objects are not wrapped, calling methods on them such as listCaps() can block all other greenthreads and can cause nova-compute to freeze for hours in certain scenarios. This adds the same wrapping to libvirt calls which return lists of virNodeDevice. Closes-Bug: #2091033 Change-Id: I60d6f04d374e9ede5895a43b7a75e955b0fea3c5
This commit is contained in:

committed by
Stephen Finucane

parent
a67ab85678
commit
f304b9eaad
@@ -2245,6 +2245,48 @@ class LibvirtTpoolProxyTestCase(test.NoDBTestCase):
|
|||||||
self.assertIsInstance(domain, tpool.Proxy)
|
self.assertIsInstance(domain, tpool.Proxy)
|
||||||
self.assertIn(domain.UUIDString(), (uuids.vm1, uuids.vm2))
|
self.assertIn(domain.UUIDString(), (uuids.vm1, uuids.vm2))
|
||||||
|
|
||||||
|
def _add_fake_host_devices(self):
|
||||||
|
self.conn._obj.pci_info = fakelibvirt.HostPCIDevicesInfo(
|
||||||
|
num_pci=1, num_pfs=2, num_vfs=2, num_mdevcap=3)
|
||||||
|
mdevs = {
|
||||||
|
'mdev_4b20d080_1b54_4048_85b3_a6a62d165c01':
|
||||||
|
fakelibvirt.FakeMdevDevice(
|
||||||
|
dev_name='mdev_4b20d080_1b54_4048_85b3_a6a62d165c01',
|
||||||
|
type_id=fakelibvirt.NVIDIA_11_VGPU_TYPE,
|
||||||
|
parent=fakelibvirt.MDEVCAP_DEV1_PCI_ADDR),
|
||||||
|
}
|
||||||
|
self.conn._obj.mdev_info = fakelibvirt.HostMdevDevicesInfo(
|
||||||
|
devices=mdevs)
|
||||||
|
|
||||||
|
def test_tpool_list_all_devices(self):
|
||||||
|
self._add_fake_host_devices()
|
||||||
|
devs = self.host.list_all_devices(
|
||||||
|
fakelibvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV)
|
||||||
|
self.assertEqual(8, len(devs))
|
||||||
|
for dev in devs:
|
||||||
|
self.assertIsInstance(dev, tpool.Proxy)
|
||||||
|
|
||||||
|
def test_tpool_list_pci_devices(self):
|
||||||
|
self._add_fake_host_devices()
|
||||||
|
devs = self.host.list_pci_devices()
|
||||||
|
self.assertEqual(8, len(devs))
|
||||||
|
for dev in devs:
|
||||||
|
self.assertIsInstance(dev, tpool.Proxy)
|
||||||
|
|
||||||
|
def test_tpool_list_mdev_capable_devices(self):
|
||||||
|
self._add_fake_host_devices()
|
||||||
|
devs = self.host.list_mdev_capable_devices()
|
||||||
|
self.assertEqual(3, len(devs))
|
||||||
|
for dev in devs:
|
||||||
|
self.assertIsInstance(dev, tpool.Proxy)
|
||||||
|
|
||||||
|
def test_tpool_list_mediated_devices(self):
|
||||||
|
self._add_fake_host_devices()
|
||||||
|
devs = self.host.list_mediated_devices()
|
||||||
|
self.assertEqual(1, len(devs))
|
||||||
|
for dev in devs:
|
||||||
|
self.assertIsInstance(dev, tpool.Proxy)
|
||||||
|
|
||||||
|
|
||||||
class LoadersTestCase(test.NoDBTestCase):
|
class LoadersTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
|
@@ -1647,7 +1647,9 @@ class Host(object):
|
|||||||
:returns: a list of virNodeDevice instance
|
:returns: a list of virNodeDevice instance
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.get_connection().listDevices(cap, flags)
|
devs = [self._wrap_libvirt_proxy(dev)
|
||||||
|
for dev in self.get_connection().listDevices(cap, flags)]
|
||||||
|
return devs
|
||||||
except libvirt.libvirtError as ex:
|
except libvirt.libvirtError as ex:
|
||||||
error_code = ex.get_error_code()
|
error_code = ex.get_error_code()
|
||||||
if error_code == libvirt.VIR_ERR_NO_SUPPORT:
|
if error_code == libvirt.VIR_ERR_NO_SUPPORT:
|
||||||
@@ -1667,7 +1669,10 @@ class Host(object):
|
|||||||
:returns: a list of virNodeDevice instances.
|
:returns: a list of virNodeDevice instances.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.get_connection().listAllDevices(flags) or []
|
alldevs = [
|
||||||
|
self._wrap_libvirt_proxy(dev)
|
||||||
|
for dev in self.get_connection().listAllDevices(flags)] or []
|
||||||
|
return alldevs
|
||||||
except libvirt.libvirtError as ex:
|
except libvirt.libvirtError as ex:
|
||||||
LOG.warning(ex)
|
LOG.warning(ex)
|
||||||
return []
|
return []
|
||||||
|
@@ -0,0 +1,11 @@
|
|||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
`Bug #2091033`_: Fixed calls to libvirt ``listDevices()`` and
|
||||||
|
``listAllDevices()`` from potentially blocking all other greenthreads
|
||||||
|
in ``nova-compute``. Under certain circumstances, it was possible for
|
||||||
|
the ``nova-compute`` service to freeze with all other greenthreads
|
||||||
|
blocked and unable to perform any other activities including logging.
|
||||||
|
This issue has been fixed by wrapping the libvirt ``listDevices()``
|
||||||
|
and ``listAllDevices()`` calls with ``eventlet.tpool.Proxy``.
|
||||||
|
|
||||||
|
.. _Bug #2091033: https://bugs.launchpad.net/nova/+bug/2091033
|
Reference in New Issue
Block a user