pci: avoid parsing whitelist repeatedly

Prior to this patch, everytime a pci device
was added or removed, get_pci_device_devspec() in
whitelist was called which creates Whitelist object
and parses CONF.pci_passthrough_whitelist.

This patch fixes it by storing the whitelist/device filter
as an attribute of PciDeviceStats class similar to
PciDevTracker.

Change-Id: I0aadd57f7833ac5da42abf557a4602fb1d5db5f8
This commit is contained in:
Giridhar Jayavelu 2016-01-06 16:24:17 -08:00
parent 027be87591
commit 4be8f84754
4 changed files with 25 additions and 5 deletions

View File

@ -55,8 +55,8 @@ class PciDevTracker(object):
super(PciDevTracker, self).__init__()
self.stale = {}
self.node_id = node_id
self.stats = stats.PciDeviceStats()
self.dev_filter = whitelist.Whitelist(CONF.pci_passthrough_whitelist)
self.stats = stats.PciDeviceStats(dev_filter=self.dev_filter)
self._context = context
if node_id:
self.pci_devs = objects.PciDeviceList.get_by_compute_node(

View File

@ -16,6 +16,7 @@
import copy
from oslo_config import cfg
from oslo_log import log as logging
import six
@ -28,6 +29,7 @@ from nova.pci import utils
from nova.pci import whitelist
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
@ -57,12 +59,14 @@ class PciDeviceStats(object):
pool_keys = ['product_id', 'vendor_id', 'numa_node', 'dev_type']
def __init__(self, stats=None):
def __init__(self, stats=None, dev_filter=None):
super(PciDeviceStats, self).__init__()
# NOTE(sbauza): Stats are a PCIDevicePoolList object
self.pools = [pci_pool.to_dict()
for pci_pool in stats] if stats else []
self.pools.sort(key=lambda item: len(item))
self.dev_filter = dev_filter or whitelist.Whitelist(
CONF.pci_passthrough_whitelist)
def _equal_properties(self, dev, entry, matching_keys):
return all(dev.get(prop) == entry.get(prop)
@ -86,7 +90,7 @@ class PciDeviceStats(object):
"""
# Don't add a device that doesn't have a matching device spec.
# This can happen during initial sync up with the controller
devspec = whitelist.get_pci_device_devspec(dev)
devspec = self.dev_filter.get_devspec(dev)
if not devspec:
return
tags = devspec.get_tags()

View File

@ -23,7 +23,7 @@ from nova.pci import whitelist
def fake_pci_whitelist():
devspec = mock.Mock()
devspec.get_tags.return_value = None
patcher = mock.patch.object(whitelist, 'get_pci_device_devspec',
patcher = mock.patch.object(whitelist.Whitelist, 'get_devspec',
return_value=devspec)
patcher.start()
return patcher

View File

@ -16,12 +16,17 @@
import mock
import six
from oslo_config import cfg
from nova import exception
from nova import objects
from nova.objects import fields
from nova.pci import stats
from nova.pci import whitelist
from nova import test
from nova.tests.unit.pci import fakes
CONF = cfg.CONF
fake_pci_1 = {
'compute_node_id': 1,
'address': '0000:00:00.1',
@ -202,6 +207,16 @@ class PciDeviceStatsTestCase(test.NoDBTestCase):
self.assertEqual(set(['v3']),
set([dev.vendor_id for dev in devs]))
@mock.patch(
'nova.pci.whitelist.Whitelist._parse_white_list_from_config')
def test_white_list_parsing(self, mock_whitelist_parse):
white_list = '{"product_id":"0001", "vendor_id":"8086"}'
CONF.set_override('pci_passthrough_whitelist', white_list)
pci_stats = stats.PciDeviceStats()
pci_stats.add_device(self.fake_dev_2)
pci_stats.remove_device(self.fake_dev_2)
self.assertEqual(1, mock_whitelist_parse.call_count)
class PciDeviceStatsWithTagsTestCase(test.NoDBTestCase):
@ -211,7 +226,8 @@ class PciDeviceStatsWithTagsTestCase(test.NoDBTestCase):
'"address":"*:0a:00.*","physical_network":"physnet1"}',
'{"vendor_id":"1137","product_id":"0072"}']
self.flags(pci_passthrough_whitelist=white_list)
self.pci_stats = stats.PciDeviceStats()
dev_filter = whitelist.Whitelist(white_list)
self.pci_stats = stats.PciDeviceStats(dev_filter=dev_filter)
def _create_pci_devices(self):
self.pci_tagged_devices = []