conf: Move PCI options to a PCI group

This allows us to remove the final TODO.

Change-Id: I886045ab4e6bdb8418fd1ccdcd811417ecb4ad4a
Implements: bp centralize-config-options-ocata
This commit is contained in:
Stephen Finucane
2016-08-17 17:47:43 +01:00
parent a997c96670
commit 4e5ed1c489
11 changed files with 81 additions and 57 deletions

View File

@@ -1123,7 +1123,7 @@ class ComputeManager(manager.Manager):
def init_host(self): def init_host(self):
"""Initialization for a standalone compute service.""" """Initialization for a standalone compute service."""
if CONF.pci_passthrough_whitelist: if CONF.pci.passthrough_whitelist:
# Simply loading the PCI passthrough whitelist will do a bunch of # Simply loading the PCI passthrough whitelist will do a bunch of
# validation that would otherwise wait until the PciDevTracker is # validation that would otherwise wait until the PciDevTracker is
# constructed when updating available resources for the compute # constructed when updating available resources for the compute
@@ -1131,7 +1131,7 @@ class ComputeManager(manager.Manager):
# So load up the whitelist when starting the compute service to # So load up the whitelist when starting the compute service to
# flush any invalid configuration early so we can kill the service # flush any invalid configuration early so we can kill the service
# if the configuration is wrong. # if the configuration is wrong.
whitelist.Whitelist(CONF.pci_passthrough_whitelist) whitelist.Whitelist(CONF.pci.passthrough_whitelist)
self.driver.init_host(host=self.host) self.driver.init_host(host=self.host)
context = nova.context.get_admin_context() context = nova.context.get_admin_context()

View File

@@ -16,9 +16,15 @@
from oslo_config import cfg from oslo_config import cfg
pci_group = cfg.OptGroup(
name='pci',
title='PCI passthrough options')
pci_opts = [ pci_opts = [
cfg.MultiStrOpt('pci_alias', cfg.MultiStrOpt('alias',
default=[], default=[],
deprecated_name='pci_alias',
deprecated_group='DEFAULT',
help=""" help="""
An alias for a PCI passthrough device requirement. An alias for a PCI passthrough device requirement.
@@ -29,7 +35,7 @@ Possible Values:
* A list of JSON values which describe the aliases. For example: * A list of JSON values which describe the aliases. For example:
pci_alias = { alias = {
"name": "QuickAssist", "name": "QuickAssist",
"product_id": "0443", "product_id": "0443",
"vendor_id": "8086", "vendor_id": "8086",
@@ -45,8 +51,10 @@ Possible Values:
* "device_type": Type of PCI device. Valid values are: "type-PCI", * "device_type": Type of PCI device. Valid values are: "type-PCI",
"type-PF" and "type-VF". "type-PF" and "type-VF".
"""), """),
cfg.MultiStrOpt('pci_passthrough_whitelist', cfg.MultiStrOpt('passthrough_whitelist',
default=[], default=[],
deprecated_name='pci_passthrough_whitelist',
deprecated_group='DEFAULT',
help=""" help="""
White list of PCI devices available to VMs. White list of PCI devices available to VMs.
@@ -76,38 +84,37 @@ Possible values:
Valid examples are: Valid examples are:
pci_passthrough_whitelist = {"devname":"eth0", passthrough_whitelist = {"devname":"eth0",
"physical_network":"physnet"} "physical_network":"physnet"}
pci_passthrough_whitelist = {"address":"*:0a:00.*"} passthrough_whitelist = {"address":"*:0a:00.*"}
pci_passthrough_whitelist = {"address":":0a:00.", passthrough_whitelist = {"address":":0a:00.",
"physical_network":"physnet1"} "physical_network":"physnet1"}
pci_passthrough_whitelist = {"vendor_id":"1137", passthrough_whitelist = {"vendor_id":"1137",
"product_id":"0071"} "product_id":"0071"}
pci_passthrough_whitelist = {"vendor_id":"1137", passthrough_whitelist = {"vendor_id":"1137",
"product_id":"0071", "product_id":"0071",
"address": "0000:0a:00.1", "address": "0000:0a:00.1",
"physical_network":"physnet1"} "physical_network":"physnet1"}
The following are invalid, as they specify mutually exclusive options: The following are invalid, as they specify mutually exclusive options:
pci_passthrough_whitelist = {"devname":"eth0", passthrough_whitelist = {"devname":"eth0",
"physical_network":"physnet", "physical_network":"physnet",
"address":"*:0a:00.*"} "address":"*:0a:00.*"}
* A JSON list of JSON dictionaries corresponding to the above format. For * A JSON list of JSON dictionaries corresponding to the above format. For
example: example:
pci_passthrough_whitelist = [{"product_id":"0001", "vendor_id":"8086"}, passthrough_whitelist = [{"product_id":"0001", "vendor_id":"8086"},
{"product_id":"0002", "vendor_id":"8086"}] {"product_id":"0002", "vendor_id":"8086"}]
""") """)
] ]
def register_opts(conf): def register_opts(conf):
conf.register_opts(pci_opts) conf.register_group(pci_group)
conf.register_opts(pci_opts, group=pci_group)
def list_opts(): def list_opts():
# TODO(sfinucan): This should be moved into the PCI group and return {pci_group: pci_opts}
# oslo_config.cfg.OptGroup used
return {'DEFAULT': pci_opts}

View File

@@ -45,13 +45,14 @@ def get_pci_dev_info(pci_obj, property, max, hex_value):
class PciAddress(object): class PciAddress(object):
"""Manages the address fields of the whitelist. """Manages the address fields of the whitelist.
This class checks the address fields of the pci_passthrough_whitelist This class checks the address fields of the pci.passthrough_whitelist
configuration option, validating the address fields. configuration option, validating the address fields.
Example config are: Example config are:
| pci_passthrough_whitelist = {"address":"*:0a:00.*", | [pci]
| passthrough_whitelist = {"address":"*:0a:00.*",
| "physical_network":"physnet1"} | "physical_network":"physnet1"}
| pci_passthrough_whitelist = {"vendor_id":"1137","product_id":"0071"} | passthrough_whitelist = {"vendor_id":"1137","product_id":"0071"}
This function class will validate the address fields, check for wildcards, This function class will validate the address fields, check for wildcards,
and insert wildcards where the field is left blank. and insert wildcards where the field is left blank.

View File

@@ -64,7 +64,7 @@ class PciDevTracker(object):
super(PciDevTracker, self).__init__() super(PciDevTracker, self).__init__()
self.stale = {} self.stale = {}
self.node_id = node_id self.node_id = node_id
self.dev_filter = whitelist.Whitelist(CONF.pci_passthrough_whitelist) self.dev_filter = whitelist.Whitelist(CONF.pci.passthrough_whitelist)
self.stats = stats.PciDeviceStats(dev_filter=self.dev_filter) self.stats = stats.PciDeviceStats(dev_filter=self.dev_filter)
self._context = context self._context = context
if node_id: if node_id:

View File

@@ -15,7 +15,8 @@
""" Example of a PCI alias:: """ Example of a PCI alias::
| pci_alias = '{ | [pci]
| alias = '{
| "name": "QuicAssist", | "name": "QuicAssist",
| "product_id": "0443", | "product_id": "0443",
| "vendor_id": "8086", | "vendor_id": "8086",
@@ -24,7 +25,8 @@
Aliases with the same name and the same device_type are OR operation:: Aliases with the same name and the same device_type are OR operation::
| pci_alias = '{ | [pci]
| alias = '{
| "name": "QuicAssist", | "name": "QuicAssist",
| "product_id": "0442", | "product_id": "0442",
| "vendor_id": "8086", | "vendor_id": "8086",
@@ -97,7 +99,7 @@ _ALIAS_SCHEMA = {
def _get_alias_from_config(): def _get_alias_from_config():
"""Parse and validate PCI aliases from the nova config.""" """Parse and validate PCI aliases from the nova config."""
jaliases = CONF.pci_alias jaliases = CONF.pci.alias
aliases = {} # map alias name to alias spec list aliases = {} # map alias name to alias spec list
try: try:
for jsonspecs in jaliases: for jsonspecs in jaliases:
@@ -150,7 +152,7 @@ def get_pci_requests_from_flavor(flavor):
describes the flavor's pci requests, the key is describes the flavor's pci requests, the key is
'pci_passthrough:alias' and the value has format 'pci_passthrough:alias' and the value has format
'alias_name_x:count, alias_name_y:count, ... '. The alias_name is 'alias_name_x:count, alias_name_y:count, ... '. The alias_name is
defined in 'pci_alias' configurations. defined in 'pci.alias' configurations.
The flavor's requirement is translated into pci requests list, The flavor's requirement is translated into pci requests list,
each entry in the list is a dictionary. The dictionary has each entry in the list is a dictionary. The dictionary has

View File

@@ -65,7 +65,7 @@ class PciDeviceStats(object):
for pci_pool in stats] if stats else [] for pci_pool in stats] if stats else []
self.pools.sort(key=lambda item: len(item)) self.pools.sort(key=lambda item: len(item))
self.dev_filter = dev_filter or whitelist.Whitelist( self.dev_filter = dev_filter or whitelist.Whitelist(
CONF.pci_passthrough_whitelist) CONF.pci.passthrough_whitelist)
def _equal_properties(self, dev, entry, matching_keys): def _equal_properties(self, dev, entry, matching_keys):
return all(dev.get(prop) == entry.get(prop) return all(dev.get(prop) == entry.get(prop)

View File

@@ -96,5 +96,5 @@ class Whitelist(object):
def get_pci_device_devspec(pci_dev): def get_pci_device_devspec(pci_dev):
dev_filter = Whitelist(CONF.pci_passthrough_whitelist) dev_filter = Whitelist(CONF.pci.passthrough_whitelist)
return dev_filter.get_devspec(pci_dev) return dev_filter.get_devspec(pci_dev)

View File

@@ -2730,11 +2730,12 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
self.assertIn('appears to not be owned by this host', msg[0][0]) self.assertIn('appears to not be owned by this host', msg[0][0])
def test_init_host_pci_passthrough_whitelist_validation_failure(self): def test_init_host_pci_passthrough_whitelist_validation_failure(self):
# Tests that we fail init_host if there is a pci_passthrough_whitelist # Tests that we fail init_host if there is a pci.passthrough_whitelist
# configured incorrectly. # configured incorrectly.
self.flags(pci_passthrough_whitelist=[ self.flags(passthrough_whitelist=[
# it's invalid to specify both in the same devspec # it's invalid to specify both in the same devspec
jsonutils.dumps({'address': 'foo', 'devname': 'bar'})]) jsonutils.dumps({'address': 'foo', 'devname': 'bar'})],
group='pci')
self.assertRaises(exception.PciDeviceInvalidDeviceName, self.assertRaises(exception.PciDeviceInvalidDeviceName,
self.compute.init_host) self.compute.init_host)

View File

@@ -55,7 +55,7 @@ _fake_alias3 = """{
class AliasTestCase(test.NoDBTestCase): class AliasTestCase(test.NoDBTestCase):
def test_good_alias(self): def test_good_alias(self):
self.flags(pci_alias=[_fake_alias1]) self.flags(alias=[_fake_alias1], group='pci')
als = request._get_alias_from_config() als = request._get_alias_from_config()
self.assertIsInstance(als['QuicAssist'], list) self.assertIsInstance(als['QuicAssist'], list)
expect_dict = { expect_dict = {
@@ -67,7 +67,7 @@ class AliasTestCase(test.NoDBTestCase):
self.assertEqual(expect_dict, als['QuicAssist'][0]) self.assertEqual(expect_dict, als['QuicAssist'][0])
def test_multispec_alias(self): def test_multispec_alias(self):
self.flags(pci_alias=[_fake_alias1, _fake_alias11]) self.flags(alias=[_fake_alias1, _fake_alias11], group='pci')
als = request._get_alias_from_config() als = request._get_alias_from_config()
self.assertIsInstance(als['QuicAssist'], list) self.assertIsInstance(als['QuicAssist'], list)
expect_dict1 = { expect_dict1 = {
@@ -87,48 +87,51 @@ class AliasTestCase(test.NoDBTestCase):
self.assertEqual(expect_dict2, als['QuicAssist'][1]) self.assertEqual(expect_dict2, als['QuicAssist'][1])
def test_wrong_type_aliase(self): def test_wrong_type_aliase(self):
self.flags(pci_alias=[_fake_alias2]) self.flags(alias=[_fake_alias2], group='pci')
self.assertRaises(exception.PciInvalidAlias, self.assertRaises(exception.PciInvalidAlias,
request._get_alias_from_config) request._get_alias_from_config)
def test_wrong_product_id_aliase(self): def test_wrong_product_id_aliase(self):
self.flags(pci_alias=[ self.flags(alias=[
"""{ """{
"name": "xxx", "name": "xxx",
"capability_type": "pci", "capability_type": "pci",
"product_id": "g111", "product_id": "g111",
"vendor_id": "1111", "vendor_id": "1111",
"device_type": "NIC" "device_type": "NIC"
}"""]) }"""],
group='pci')
self.assertRaises(exception.PciInvalidAlias, self.assertRaises(exception.PciInvalidAlias,
request._get_alias_from_config) request._get_alias_from_config)
def test_wrong_vendor_id_aliase(self): def test_wrong_vendor_id_aliase(self):
self.flags(pci_alias=[ self.flags(alias=[
"""{ """{
"name": "xxx", "name": "xxx",
"capability_type": "pci", "capability_type": "pci",
"product_id": "1111", "product_id": "1111",
"vendor_id": "0xg111", "vendor_id": "0xg111",
"device_type": "NIC" "device_type": "NIC"
}"""]) }"""],
group='pci')
self.assertRaises(exception.PciInvalidAlias, self.assertRaises(exception.PciInvalidAlias,
request._get_alias_from_config) request._get_alias_from_config)
def test_wrong_cap_type_aliase(self): def test_wrong_cap_type_aliase(self):
self.flags(pci_alias=[ self.flags(alias=[
"""{ """{
"name": "xxx", "name": "xxx",
"capability_type": "usb", "capability_type": "usb",
"product_id": "1111", "product_id": "1111",
"vendor_id": "8086", "vendor_id": "8086",
"device_type": "NIC" "device_type": "NIC"
}"""]) }"""],
group='pci')
self.assertRaises(exception.PciInvalidAlias, self.assertRaises(exception.PciInvalidAlias,
request._get_alias_from_config) request._get_alias_from_config)
def test_dup_aliase(self): def test_dup_aliase(self):
self.flags(pci_alias=[ self.flags(alias=[
"""{ """{
"name": "xxx", "name": "xxx",
"capability_type": "pci", "capability_type": "pci",
@@ -142,7 +145,8 @@ class AliasTestCase(test.NoDBTestCase):
"product_id": "1111", "product_id": "1111",
"vendor_id": "8086", "vendor_id": "8086",
"device_type": "type-PCI" "device_type": "type-PCI"
}"""]) }"""],
group='pci')
self.assertRaises( self.assertRaises(
exception.PciInvalidAlias, exception.PciInvalidAlias,
request._get_alias_from_config) request._get_alias_from_config)
@@ -155,7 +159,7 @@ class AliasTestCase(test.NoDBTestCase):
self.assertEqual(exp['spec'], real.spec) self.assertEqual(exp['spec'], real.spec)
def test_aliase_2_request(self): def test_aliase_2_request(self):
self.flags(pci_alias=[_fake_alias1, _fake_alias3]) self.flags(alias=[_fake_alias1, _fake_alias3], group='pci')
expect_request = [ expect_request = [
{'count': 3, {'count': 3,
'spec': [{'vendor_id': '8086', 'product_id': '4443', 'spec': [{'vendor_id': '8086', 'product_id': '4443',
@@ -175,13 +179,13 @@ class AliasTestCase(test.NoDBTestCase):
self._verify_result(expect_request, requests) self._verify_result(expect_request, requests)
def test_aliase_2_request_invalid(self): def test_aliase_2_request_invalid(self):
self.flags(pci_alias=[_fake_alias1, _fake_alias3]) self.flags(alias=[_fake_alias1, _fake_alias3], group='pci')
self.assertRaises(exception.PciRequestAliasNotDefined, self.assertRaises(exception.PciRequestAliasNotDefined,
request._translate_alias_to_requests, request._translate_alias_to_requests,
"QuicAssistX : 3") "QuicAssistX : 3")
def test_get_pci_requests_from_flavor(self): def test_get_pci_requests_from_flavor(self):
self.flags(pci_alias=[_fake_alias1, _fake_alias3]) self.flags(alias=[_fake_alias1, _fake_alias3], group='pci')
expect_request = [ expect_request = [
{'count': 3, {'count': 3,
'spec': [{'vendor_id': '8086', 'product_id': '4443', 'spec': [{'vendor_id': '8086', 'product_id': '4443',
@@ -203,7 +207,7 @@ class AliasTestCase(test.NoDBTestCase):
self._verify_result(expect_request, requests.requests) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor_no_extra_spec(self): def test_get_pci_requests_from_flavor_no_extra_spec(self):
self.flags(pci_alias=[_fake_alias1, _fake_alias3]) self.flags(alias=[_fake_alias1, _fake_alias3], group='pci')
flavor = {} flavor = {}
requests = request.get_pci_requests_from_flavor(flavor) requests = request.get_pci_requests_from_flavor(flavor)
self.assertEqual([], requests.requests) self.assertEqual([], requests.requests)

View File

@@ -212,7 +212,7 @@ class PciDeviceStatsTestCase(test.NoDBTestCase):
'nova.pci.whitelist.Whitelist._parse_white_list_from_config') 'nova.pci.whitelist.Whitelist._parse_white_list_from_config')
def test_white_list_parsing(self, mock_whitelist_parse): def test_white_list_parsing(self, mock_whitelist_parse):
white_list = '{"product_id":"0001", "vendor_id":"8086"}' white_list = '{"product_id":"0001", "vendor_id":"8086"}'
CONF.set_override('pci_passthrough_whitelist', white_list) CONF.set_override('passthrough_whitelist', white_list, 'pci')
pci_stats = stats.PciDeviceStats() pci_stats = stats.PciDeviceStats()
pci_stats.add_device(self.fake_dev_2) pci_stats.add_device(self.fake_dev_2)
pci_stats.remove_device(self.fake_dev_2) pci_stats.remove_device(self.fake_dev_2)
@@ -226,7 +226,7 @@ class PciDeviceStatsWithTagsTestCase(test.NoDBTestCase):
white_list = ['{"vendor_id":"1137","product_id":"0071",' white_list = ['{"vendor_id":"1137","product_id":"0071",'
'"address":"*:0a:00.*","physical_network":"physnet1"}', '"address":"*:0a:00.*","physical_network":"physnet1"}',
'{"vendor_id":"1137","product_id":"0072"}'] '{"vendor_id":"1137","product_id":"0072"}']
self.flags(pci_passthrough_whitelist=white_list) self.flags(passthrough_whitelist=white_list, group='pci')
dev_filter = whitelist.Whitelist(white_list) dev_filter = whitelist.Whitelist(white_list)
self.pci_stats = stats.PciDeviceStats(dev_filter=dev_filter) self.pci_stats = stats.PciDeviceStats(dev_filter=dev_filter)
@@ -356,7 +356,7 @@ class PciDeviceVFPFStatsTestCase(test.NoDBTestCase):
super(PciDeviceVFPFStatsTestCase, self).setUp() super(PciDeviceVFPFStatsTestCase, self).setUp()
white_list = ['{"vendor_id":"8086","product_id":"1528"}', white_list = ['{"vendor_id":"8086","product_id":"1528"}',
'{"vendor_id":"8086","product_id":"1515"}'] '{"vendor_id":"8086","product_id":"1515"}']
self.flags(pci_passthrough_whitelist=white_list) self.flags(passthrough_whitelist=white_list, group='pci')
self.pci_stats = stats.PciDeviceStats() self.pci_stats = stats.PciDeviceStats()
def _create_pci_devices(self, vf_product_id=1515, pf_product_id=1528): def _create_pci_devices(self, vf_product_id=1515, pf_product_id=1528):

View File

@@ -0,0 +1,9 @@
---
upgrade:
- |
All pci configuration options have been added to the 'pci' group. They
should no longer be included in the 'DEFAULT' group. These options are as
below:
- pci_alias (now pci.alias)
- pci_passthrough_whitelist (now pci.passthrough_whitelist)