Update pci stat pools based on PCI device changes

At start up of nova-compute service, the PCI stat pools are
populated based on information in pci_devices table in Nova
database. The pools are updated only when new device is added
or removed but not on any device changes like device type.

If an existing device is configured as SRIOV and nova-compute
is restarted, the pci_devices table gets updated but the device
is still listed under the old pool in pci_tracker.stats.pool
(in-memory object).

This patch looks for device type updates in existing devices
and updates the pools accordingly.

Conflicts:
    nova/tests/functional/libvirt/test_pci_sriov_servers.py
    nova/tests/unit/virt/libvirt/fakelibvirt.py

The functional test requires to skip the capabilities of pci
device. This can be done by getting capability template out of
pci_dev_template [1] which is introduced by commit
b927748c25. Not able to clean
backport the mentioned commit and so removed funtional test
case.

[1] b0a451d428/nova/tests/unit/virt/libvirt/fakelibvirt.py (L186)

Change-Id: Id4ebb06e634a612c8be4be6c678d8265e0b99730
Closes-Bug: #1892361
(cherry picked from commit b8695de6da)
(cherry picked from commit d8b8a8193b)
(cherry picked from commit f58399cf49)
(cherry picked from commit 8378785f99)
(cherry picked from commit 73e631862a)
This commit is contained in:
Hemanth Nakkina 2020-09-01 09:36:51 +05:30 committed by Hemanth N
parent ddbcf57947
commit 1fb4cc03e3
4 changed files with 63 additions and 0 deletions

View File

@ -225,6 +225,7 @@ class PciDevTracker(object):
self.stale[new_value['address']] = new_value self.stale[new_value['address']] = new_value
else: else:
existed.update_device(new_value) existed.update_device(new_value)
self.stats.update_device(existed)
# Track newly discovered devices. # Track newly discovered devices.
for dev in [dev for dev in devices if for dev in [dev for dev in devices if

View File

@ -97,6 +97,32 @@ class PciDeviceStats(object):
pool.update(tags) pool.update(tags)
return pool return pool
def _get_pool_with_device_type_mismatch(self, dev):
"""Check for device type mismatch in the pools for a given device.
Return (pool, device) if device type does not match or a single None
if the device type matches.
"""
for pool in self.pools:
for device in pool['devices']:
if device.address == dev.address:
if dev.dev_type != pool["dev_type"]:
return pool, device
return None
return None
def update_device(self, dev):
"""Update a device to its matching pool."""
pool_device_info = self._get_pool_with_device_type_mismatch(dev)
if pool_device_info is None:
return
pool, device = pool_device_info
pool['devices'].remove(device)
self._decrease_pool_count(self.pools, pool)
self.add_device(dev)
def add_device(self, dev): def add_device(self, dev):
"""Add a device to its matching pool.""" """Add a device to its matching pool."""
dev_pool = self._create_pool_keys_from_dev(dev) dev_pool = self._create_pool_keys_from_dev(dev)

View File

@ -533,6 +533,30 @@ class PciDeviceStatsWithTagsTestCase(test.NoDBTestCase):
self.pci_stats.remove_device(dev2) self.pci_stats.remove_device(dev2)
self._assertPools() self._assertPools()
def test_update_device(self):
# Update device type of one of the device from type-PCI to
# type-PF. Verify if the existing pool is updated and a new
# pool is created with dev_type type-PF.
self._create_pci_devices()
dev1 = self.pci_tagged_devices.pop()
dev1.dev_type = 'type-PF'
self.pci_stats.update_device(dev1)
self.assertEqual(3, len(self.pci_stats.pools))
self._assertPoolContent(self.pci_stats.pools[0], '1137', '0072',
len(self.pci_untagged_devices))
self.assertEqual(self.pci_untagged_devices,
self.pci_stats.pools[0]['devices'])
self._assertPoolContent(self.pci_stats.pools[1], '1137', '0071',
len(self.pci_tagged_devices),
physical_network='physnet1')
self.assertEqual(self.pci_tagged_devices,
self.pci_stats.pools[1]['devices'])
self._assertPoolContent(self.pci_stats.pools[2], '1137', '0071',
1,
physical_network='physnet1')
self.assertEqual(dev1,
self.pci_stats.pools[2]['devices'][0])
class PciDeviceVFPFStatsTestCase(test.NoDBTestCase): class PciDeviceVFPFStatsTestCase(test.NoDBTestCase):

View File

@ -0,0 +1,12 @@
---
fixes:
- |
Fixes `bug 1892361`_ in which the pci stat pools are not updated when an
existing device is enabled with SRIOV capability. Restart of nova-compute
service updates the pci device type from type-PCI to type-PF but the pools
still maintain the device type as type-PCI. And so the PF is considered for
allocation to instance that requests vnic_type=direct. With this fix, the
pci device type updates are detected and the pci stat pools are updated
properly.
.. _bug 1892361: https://bugs.launchpad.net/nova/+bug/1892361