diff --git a/nova/objects/fields.py b/nova/objects/fields.py index 8c4fc299aab6..960fcc849641 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -757,8 +757,12 @@ class PciDeviceType(BaseNovaEnum): STANDARD = "type-PCI" SRIOV_PF = "type-PF" SRIOV_VF = "type-VF" + # NOTE(sean-k-mooney): The DB field is Column(String(8), nullable=False) + # type-vdpa is 9 long...and as Jay notes above the prefix is silly so + # for the new vdpa value we drop the prefix to avoid a DB migration + VDPA = "vdpa" - ALL = (STANDARD, SRIOV_PF, SRIOV_VF) + ALL = (STANDARD, SRIOV_PF, SRIOV_VF, VDPA) class PCINUMAAffinityPolicy(BaseNovaEnum): diff --git a/nova/objects/pci_device.py b/nova/objects/pci_device.py index 14db00ebc3e9..2119a9ccdcc0 100644 --- a/nova/objects/pci_device.py +++ b/nova/objects/pci_device.py @@ -98,7 +98,8 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject): # Version 1.4: Added parent_addr field # Version 1.5: Added 2 new device statuses: UNCLAIMABLE and UNAVAILABLE # Version 1.6: Added uuid field - VERSION = '1.6' + # Version 1.7: Added 'vdpa' to 'dev_type' field + VERSION = '1.7' fields = { 'id': fields.IntegerField(), @@ -140,6 +141,13 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject): status, target_version)) if target_version < (1, 6) and 'uuid' in primitive: del primitive['uuid'] + if target_version < (1, 7) and 'dev_type' in primitive: + dev_type = primitive['dev_type'] + if dev_type == fields.PciDeviceType.VDPA: + raise exception.ObjectActionError( + action='obj_make_compatible', + reason='dev_type=%s not supported in version %s' % ( + dev_type, target_version)) def update_device(self, dev_dict): """Sync the content from device dictionary to device object. diff --git a/nova/pci/request.py b/nova/pci/request.py index 1a451d873787..5a9c08232d6f 100644 --- a/nova/pci/request.py +++ b/nova/pci/request.py @@ -86,7 +86,13 @@ _ALIAS_SCHEMA = { }, "device_type": { "type": "string", - "enum": list(obj_fields.PciDeviceType.ALL), + # NOTE(sean-k-mooney): vDPA devices cannot currently be used with + # alias-based PCI passthrough so we exclude it here + "enum": [ + obj_fields.PciDeviceType.STANDARD, + obj_fields.PciDeviceType.SRIOV_PF, + obj_fields.PciDeviceType.SRIOV_VF, + ], }, "numa_policy": { "type": "string", diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 38761463f4dc..b2f4f0616d01 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1115,7 +1115,7 @@ object_data = { 'NetworkRequestList': '1.1-15ecf022a68ddbb8c2a6739cfc9f8f5e', 'NicDiagnostics': '1.0-895e9ad50e0f56d5258585e3e066aea5', 'PCIDeviceBus': '1.0-2b891cb77e42961044689f3dc2718995', - 'PciDevice': '1.6-25ca0542a22bc25386a72c0065a79c01', + 'PciDevice': '1.7-680e4c590aae154958ccf9677774413b', 'PciDeviceList': '1.3-52ff14355491c8c580bdc0ba34c26210', 'PciDevicePool': '1.1-3f5ddc3ff7bfa14da7f6c7e9904cc000', 'PciDevicePoolList': '1.1-15ecf022a68ddbb8c2a6739cfc9f8f5e', diff --git a/nova/tests/unit/objects/test_pci_device.py b/nova/tests/unit/objects/test_pci_device.py index 88f5f2c1a838..845333622ca9 100644 --- a/nova/tests/unit/objects/test_pci_device.py +++ b/nova/tests/unit/objects/test_pci_device.py @@ -224,6 +224,24 @@ class _TestPciDeviceObject(object): self.assertIsNotNone(dev.uuid) self.assertEqual(1, mock_create_uuid.call_count) + def test_dev_type_vdpa_1_6_fails(self): + ctxt = context.get_admin_context() + fake_dev = copy.deepcopy(fake_db_dev) + fake_dev['dev_type'] = fields.PciDeviceType.VDPA + dev = pci_device.PciDevice._from_db_object( + ctxt, pci_device.PciDevice(), fake_dev) + self.assertRaises(exception.ObjectActionError, + dev.obj_to_primitive, '1.6') + + def test_dev_type_vdpa_1_6(self): + ctxt = context.get_admin_context() + fake_dev = copy.deepcopy(fake_db_dev) + fake_dev['dev_type'] = fields.PciDeviceType.STANDARD + dev = pci_device.PciDevice._from_db_object( + ctxt, pci_device.PciDevice(), fake_dev) + dev.obj_make_compatible(dev.obj_to_primitive(), '1.6') + self.assertEqual(dev.dev_type, fake_dev['dev_type']) + def test_save_empty_parent_addr(self): ctxt = context.get_admin_context() dev = pci_device.PciDevice._from_db_object( diff --git a/nova/tests/unit/pci/test_request.py b/nova/tests/unit/pci/test_request.py index 74a6928b5a07..3c2ba5b61f26 100644 --- a/nova/tests/unit/pci/test_request.py +++ b/nova/tests/unit/pci/test_request.py @@ -128,6 +128,13 @@ class PciRequestTestCase(test.NoDBTestCase): }) self._test_get_alias_from_config_invalid(fake_alias) + def test_get_alias_from_config_device_type_vdpa(self): + fake_alias = jsonutils.dumps({ + "name": "xxx", + "device_type": "vdpa", + }) + self._test_get_alias_from_config_invalid(fake_alias) + def test_get_alias_from_config_invalid_product_id(self): fake_alias = jsonutils.dumps({ "name": "xxx",