diff --git a/config.yaml b/config.yaml index ae673ed1..44b3c45c 100644 --- a/config.yaml +++ b/config.yaml @@ -234,7 +234,10 @@ options: pci-alias='{"vendor_id":"8086","product_id":"10ca","name":"a1"}' . This configures a new PCI alias 'a1' which will request a PCI device with - a vendor id of 0x8086 and a product id of 10ca. + a vendor id of 0x8086 and a product id of 10ca. To input a list of + aliases, use the following syntax in this charm config option: + . + pci-alias='[{...},{...}]' . For more information about the syntax of pci_alias, refer to https://docs.openstack.org/ocata/config-reference/compute/config-options.html diff --git a/hooks/nova_compute_context.py b/hooks/nova_compute_context.py index 562b254c..b310511a 100644 --- a/hooks/nova_compute_context.py +++ b/hooks/nova_compute_context.py @@ -275,7 +275,13 @@ class NovaComputeLibvirtContext(context.OSContextGenerator): config('pci-passthrough-whitelist') if config('pci-alias'): - ctxt['pci_alias'] = config('pci-alias') + aliases = json.loads(config('pci-alias')) + # Behavior previous to queens is maintained as it was + if isinstance(aliases, list) and cmp_os_release >= 'queens': + ctxt['pci_aliases'] = [json.dumps(x, sort_keys=True) + for x in aliases] + else: + ctxt['pci_alias'] = json.dumps(aliases, sort_keys=True) if config('cpu-dedicated-set'): ctxt['cpu_dedicated_set'] = config('cpu-dedicated-set') diff --git a/templates/queens/nova.conf b/templates/queens/nova.conf index 54e58666..b9a9af35 100644 --- a/templates/queens/nova.conf +++ b/templates/queens/nova.conf @@ -150,6 +150,9 @@ passthrough_whitelist = {{ pci_passthrough_whitelist }} {% if pci_alias %} alias = {{ pci_alias }} {% endif %} +{% for alias in pci_aliases -%} +alias = {{ alias }} +{% endfor -%} {% if network_manager == 'neutron' and network_manager_config -%} [neutron] diff --git a/templates/rocky/nova.conf b/templates/rocky/nova.conf index 47bcf83e..ed70809e 100644 --- a/templates/rocky/nova.conf +++ b/templates/rocky/nova.conf @@ -150,6 +150,9 @@ passthrough_whitelist = {{ pci_passthrough_whitelist }} {% if pci_alias %} alias = {{ pci_alias }} {% endif %} +{% for alias in pci_aliases -%} +alias = {{ alias }} +{% endfor -%} {% if network_manager == 'neutron' and network_manager_config -%} [neutron] diff --git a/templates/stein/nova.conf b/templates/stein/nova.conf index 7ab78f2f..8e20586a 100644 --- a/templates/stein/nova.conf +++ b/templates/stein/nova.conf @@ -154,6 +154,9 @@ passthrough_whitelist = {{ pci_passthrough_whitelist }} {% if pci_alias %} alias = {{ pci_alias }} {% endif %} +{% for alias in pci_aliases -%} +alias = {{ alias }} +{% endfor -%} {% if network_manager == 'neutron' and network_manager_config -%} [neutron] diff --git a/templates/train/nova.conf b/templates/train/nova.conf index 2f6ebab8..8cb18031 100644 --- a/templates/train/nova.conf +++ b/templates/train/nova.conf @@ -161,6 +161,9 @@ passthrough_whitelist = {{ pci_passthrough_whitelist }} {% if pci_alias %} alias = {{ pci_alias }} {% endif %} +{% for alias in pci_aliases -%} +alias = {{ alias }} +{% endfor -%} {% if network_manager == 'neutron' and network_manager_config -%} [neutron] diff --git a/unit_tests/test_nova_compute_contexts.py b/unit_tests/test_nova_compute_contexts.py index ca50dc75..cd799506 100644 --- a/unit_tests/test_nova_compute_contexts.py +++ b/unit_tests/test_nova_compute_contexts.py @@ -864,6 +864,99 @@ class NovaComputeContextTests(CharmTestCase): self.assertEqual(libvirt()['cpu_model_extra_flags'], 'pcid, vmx, pdpe1gb') + _pci_alias1 = ( + '{' + '"name": "IntelNIC",' + '"capability_type": "pci",' + '"product_id": "1111",' + '"vendor_id": "8086",' + '"device_type": "type-PF"' + '}' + ) + + _pci_alias2 = ( + '{' + '"name": " Cirrus Logic ",' + '"capability_type": "pci",' + '"product_id": "0ff2",' + '"vendor_id": "10de",' + '"device_type": "type-PCI"' + '}' + ) + + _pci_alias_list = "[" + _pci_alias1 + "," + _pci_alias2 + "]" + + @patch('charmhelpers.contrib.openstack.ip.unit_get') + @patch('charmhelpers.contrib.hahelpers.cluster.relation_ids') + @patch('charmhelpers.core.hookenv.local_unit') + @patch('charmhelpers.contrib.openstack.context.config') + def test_nova_config_context_multi_pci_alias_pike(self, mock_config, + local_unit, + mock_relation_ids, + mock_unit_get): + self.os_release.return_value = 'pike' + local_unit.return_value = 'nova-compute/0' + self.lsb_release.return_value = {'DISTRIB_CODENAME': 'xenial'} + mock_config.side_effect = self.test_config.get + mock_unit_get.return_value = '127.0.0.1' + self.test_config.set('pci-alias', self._pci_alias_list) + ctxt = context.NovaComputeLibvirtContext()() + self.assertEqual( + ctxt['pci_alias'], + ('[{"capability_type": "pci", "device_type": "type-PF", ' + '"name": "IntelNIC", "product_id": "1111", ' + '"vendor_id": "8086"}, ' + '{"capability_type": "pci", "device_type": "type-PCI", ' + '"name": " Cirrus Logic ", "product_id": "0ff2", ' + '"vendor_id": "10de"}]')) + + @patch('charmhelpers.contrib.openstack.ip.unit_get') + @patch('charmhelpers.contrib.hahelpers.cluster.relation_ids') + @patch('charmhelpers.core.hookenv.local_unit') + @patch('charmhelpers.contrib.openstack.context.config') + def test_nova_config_context_multi_pci_alias(self, mock_config, + local_unit, + mock_relation_ids, + mock_unit_get): + local_unit.return_value = 'nova-compute/0' + self.os_release.return_value = 'queens' + self.lsb_release.return_value = {'DISTRIB_CODENAME': 'bionic'} + mock_config.side_effect = self.test_config.get + mock_unit_get.return_value = '127.0.0.1' + self.test_config.set('pci-alias', self._pci_alias1) + ctxt = context.NovaComputeLibvirtContext()() + self.assertEqual( + ctxt['pci_alias'], + ('{"capability_type": "pci", "device_type": "type-PF", ' + '"name": "IntelNIC", "product_id": "1111", ' + '"vendor_id": "8086"}')) + + @patch('charmhelpers.contrib.openstack.ip.unit_get') + @patch('charmhelpers.contrib.hahelpers.cluster.relation_ids') + @patch('charmhelpers.core.hookenv.local_unit') + @patch('charmhelpers.contrib.openstack.context.config') + def test_nova_config_context_multi_pci_aliases(self, mock_config, + local_unit, + mock_relation_ids, + mock_unit_get): + local_unit.return_value = 'nova-compute/0' + self.os_release.return_value = 'queens' + self.lsb_release.return_value = {'DISTRIB_CODENAME': 'bionic'} + mock_config.side_effect = self.test_config.get + mock_unit_get.return_value = '127.0.0.1' + self.test_config.set('pci-alias', self._pci_alias_list) + ctxt = context.NovaComputeLibvirtContext()() + self.assertEqual( + ctxt['pci_aliases'][0], + ('{"capability_type": "pci", "device_type": "type-PF", ' + '"name": "IntelNIC", "product_id": "1111", ' + '"vendor_id": "8086"}')) + self.assertEqual( + ctxt['pci_aliases'][1], + ('{"capability_type": "pci", "device_type": "type-PCI", ' + '"name": " Cirrus Logic ", "product_id": "0ff2", ' + '"vendor_id": "10de"}')) + class IronicAPIContextTests(CharmTestCase):