Skip to content

Commit c20ed18

Browse files
melwittpriteau
authored andcommitted
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 (cherry picked from commit f304b9e) (cherry picked from commit 2298112)
1 parent 8555afb commit c20ed18

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

nova/tests/unit/virt/libvirt/test_host.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,48 @@ def test_tpool_list_all_connections(self):
21722172
self.assertIsInstance(domain, tpool.Proxy)
21732173
self.assertIn(domain.UUIDString(), (uuids.vm1, uuids.vm2))
21742174

2175+
def _add_fake_host_devices(self):
2176+
self.conn._obj.pci_info = fakelibvirt.HostPCIDevicesInfo(
2177+
num_pci=1, num_pfs=2, num_vfs=2, num_mdevcap=3)
2178+
mdevs = {
2179+
'mdev_4b20d080_1b54_4048_85b3_a6a62d165c01':
2180+
fakelibvirt.FakeMdevDevice(
2181+
dev_name='mdev_4b20d080_1b54_4048_85b3_a6a62d165c01',
2182+
type_id=fakelibvirt.NVIDIA_11_VGPU_TYPE,
2183+
parent=fakelibvirt.MDEVCAP_DEV1_PCI_ADDR),
2184+
}
2185+
self.conn._obj.mdev_info = fakelibvirt.HostMdevDevicesInfo(
2186+
devices=mdevs)
2187+
2188+
def test_tpool_list_all_devices(self):
2189+
self._add_fake_host_devices()
2190+
devs = self.host.list_all_devices(
2191+
fakelibvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV)
2192+
self.assertEqual(8, len(devs))
2193+
for dev in devs:
2194+
self.assertIsInstance(dev, tpool.Proxy)
2195+
2196+
def test_tpool_list_pci_devices(self):
2197+
self._add_fake_host_devices()
2198+
devs = self.host.list_pci_devices()
2199+
self.assertEqual(8, len(devs))
2200+
for dev in devs:
2201+
self.assertIsInstance(dev, tpool.Proxy)
2202+
2203+
def test_tpool_list_mdev_capable_devices(self):
2204+
self._add_fake_host_devices()
2205+
devs = self.host.list_mdev_capable_devices()
2206+
self.assertEqual(3, len(devs))
2207+
for dev in devs:
2208+
self.assertIsInstance(dev, tpool.Proxy)
2209+
2210+
def test_tpool_list_mediated_devices(self):
2211+
self._add_fake_host_devices()
2212+
devs = self.host.list_mediated_devices()
2213+
self.assertEqual(1, len(devs))
2214+
for dev in devs:
2215+
self.assertIsInstance(dev, tpool.Proxy)
2216+
21752217

21762218
class LoadersTestCase(test.NoDBTestCase):
21772219

nova/virt/libvirt/host.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,7 +1594,9 @@ def _list_devices(self, cap, flags=0):
15941594
:returns: a list of virNodeDevice instance
15951595
"""
15961596
try:
1597-
return self.get_connection().listDevices(cap, flags)
1597+
devs = [self._wrap_libvirt_proxy(dev)
1598+
for dev in self.get_connection().listDevices(cap, flags)]
1599+
return devs
15981600
except libvirt.libvirtError as ex:
15991601
error_code = ex.get_error_code()
16001602
if error_code == libvirt.VIR_ERR_NO_SUPPORT:
@@ -1614,7 +1616,10 @@ def list_all_devices(
16141616
:returns: a list of virNodeDevice xml strings.
16151617
"""
16161618
try:
1617-
return self.get_connection().listAllDevices(flags) or []
1619+
alldevs = [
1620+
self._wrap_libvirt_proxy(dev)
1621+
for dev in self.get_connection().listAllDevices(flags)] or []
1622+
return alldevs
16181623
except libvirt.libvirtError as ex:
16191624
LOG.warning(ex)
16201625
return []
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fixes:
2+
- |
3+
`Bug #2091033`_: Fixed calls to libvirt ``listDevices()`` and
4+
``listAllDevices()`` from potentially blocking all other greenthreads
5+
in ``nova-compute``. Under certain circumstances, it was possible for
6+
the ``nova-compute`` service to freeze with all other greenthreads
7+
blocked and unable to perform any other activities including logging.
8+
This issue has been fixed by wrapping the libvirt ``listDevices()``
9+
and ``listAllDevices()`` calls with ``eventlet.tpool.Proxy``.
10+
11+
.. _Bug #2091033: https://bugs.launchpad.net/nova/+bug/2091033

0 commit comments

Comments
 (0)