diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index aba87fbb5ee1..c012baefd42f 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -2048,6 +2048,7 @@ class API(base_api.NetworkAPI): tunneled_ = False vnic_type = network_model.VNIC_TYPE_NORMAL pci_request_id = None + requester_id = None if request_net.port_id: result = self._get_port_vnic_info( @@ -2057,6 +2058,9 @@ class API(base_api.NetworkAPI): context, neutron, network_id) if resource_request: + # InstancePCIRequest.requester_id is semantically linked + # to a port with a resource_request. + requester_id = request_net.port_id # NOTE(gibi): explicitly orphan the RequestGroup by setting # context=None as we never intended to save it to the DB. resource_requests.append( @@ -2101,7 +2105,8 @@ class API(base_api.NetworkAPI): request = objects.InstancePCIRequest( count=1, spec=[spec], - request_id=uuidutils.generate_uuid()) + request_id=uuidutils.generate_uuid(), + requester_id=requester_id) pci_requests.requests.append(request) pci_request_id = request.request_id diff --git a/nova/objects/instance_pci_requests.py b/nova/objects/instance_pci_requests.py index 7a4f0b62c824..7e3a920c5a9e 100644 --- a/nova/objects/instance_pci_requests.py +++ b/nova/objects/instance_pci_requests.py @@ -25,7 +25,8 @@ class InstancePCIRequest(base.NovaObject, # Version 1.0: Initial version # Version 1.1: Add request_id # Version 1.2: Add PCI NUMA affinity policy - VERSION = '1.2' + # Version 1.3: Add requester_id + VERSION = '1.3' fields = { 'count': fields.IntegerField(), @@ -35,6 +36,7 @@ class InstancePCIRequest(base.NovaObject, # on major version bump 'is_new': fields.BooleanField(default=False), 'request_id': fields.UUIDField(nullable=True), + 'requester_id': fields.StringField(nullable=True), 'numa_policy': fields.PCINUMAAffinityPolicyField(nullable=True), } @@ -45,6 +47,8 @@ class InstancePCIRequest(base.NovaObject, super(InstancePCIRequest, self).obj_make_compatible(primitive, target_version) target_version = versionutils.convert_version_to_tuple(target_version) + if target_version < (1, 3) and 'requester_id' in primitive: + del primitive['requester_id'] if target_version < (1, 2) and 'numa_policy' in primitive: del primitive['numa_policy'] if target_version < (1, 1) and 'request_id' in primitive: @@ -86,7 +90,8 @@ class InstancePCIRequests(base.NovaObject, request_obj = InstancePCIRequest( count=request['count'], spec=request['spec'], alias_name=request['alias_name'], is_new=False, - request_id=request['request_id']) + request_id=request['request_id'], + requester_id=request.get('requester_id')) request_obj.obj_reset_changes() self.requests.append(request_obj) self.obj_reset_changes() @@ -137,7 +142,8 @@ class InstancePCIRequests(base.NovaObject, 'spec': x.spec, 'alias_name': x.alias_name, 'is_new': x.is_new, - 'request_id': x.request_id} for x in self.requests] + 'request_id': x.request_id, + 'requester_id': x.requester_id} for x in self.requests] return jsonutils.dumps(blob) @classmethod diff --git a/nova/pci/request.py b/nova/pci/request.py index c16c49102992..688caf064e74 100644 --- a/nova/pci/request.py +++ b/nova/pci/request.py @@ -159,6 +159,10 @@ def _translate_alias_to_requests(alias_spec): count = int(count) numa_policy, spec = pci_aliases[name] + # NOTE(gibi): InstancePCIRequest has a requester_id field that could + # be filled with the flavor.flavorid but currently there is no special + # handling for InstancePCIRequests created from the flavor. So it is + # left empty. pci_requests.append(objects.InstancePCIRequest( count=count, spec=spec, diff --git a/nova/tests/unit/network/test_neutronv2.py b/nova/tests/unit/network/test_neutronv2.py index 8bbc769a4663..449cd182d138 100644 --- a/nova/tests/unit/network/test_neutronv2.py +++ b/nova/tests/unit/network/test_neutronv2.py @@ -5463,6 +5463,11 @@ class TestNeutronv2WithMock(_TestNeutronv2Common): else: self.assertNotIn(pci_request.PCI_TRUSTED_TAG, spec) + # Only the port with a resource_request will have pci_req.requester_id. + self.assertEqual( + [None, None, None, None, uuids.trusted_port], + [pci_req.requester_id for pci_req in pci_requests.requests]) + self.assertItemsEqual( ['physnet1', 'physnet2', 'physnet3', 'physnet4'], network_metadata.physnets) diff --git a/nova/tests/unit/objects/test_instance.py b/nova/tests/unit/objects/test_instance.py index e193a5ce0a91..4b301ee280c9 100644 --- a/nova/tests/unit/objects/test_instance.py +++ b/nova/tests/unit/objects/test_instance.py @@ -572,7 +572,8 @@ class _TestInstanceObject(object): @mock.patch('nova.db.api.instance_extra_update_by_uuid') def test_save_object_pci_requests(self, mock_instance_extra_update): expected_json = ('[{"count": 1, "alias_name": null, "is_new": false,' - '"request_id": null, "spec": [{"vendor_id": "8086",' + '"request_id": null, "requester_id": null,' + '"spec": [{"vendor_id": "8086", ' '"product_id": "1502"}]}]') inst = objects.Instance() diff --git a/nova/tests/unit/objects/test_instance_pci_requests.py b/nova/tests/unit/objects/test_instance_pci_requests.py index c5ea05048739..98f5255cf03a 100644 --- a/nova/tests/unit/objects/test_instance_pci_requests.py +++ b/nova/tests/unit/objects/test_instance_pci_requests.py @@ -38,7 +38,8 @@ fake_pci_requests = [ 'device_id': '07B5'}], 'alias_name': 'alias_2', 'is_new': True, - 'request_id': FAKE_REQUEST_UUID}, + 'request_id': FAKE_REQUEST_UUID, + 'requester_id': uuids.requester_id}, ] fake_legacy_pci_requests = [ @@ -117,6 +118,8 @@ class _TestInstancePCIRequests(object): self.assertEqual(FAKE_UUID, req.instance_uuid) self.assertEqual(2, len(req.requests)) self.assertEqual('alias_1', req.requests[0].alias_name) + self.assertIsNone(None, req.requests[0].requester_id) + self.assertEqual(uuids.requester_id, req.requests[1].requester_id) def test_from_request_spec_instance_props(self): requests = objects.InstancePCIRequests( @@ -159,6 +162,20 @@ class _TestInstancePCIRequests(object): self.assertNotIn('request_id', primitive['nova_object.data']) + def test_obj_make_compatible_pre_1_3(self): + topo_obj = objects.InstancePCIRequest( + count=1, + spec=[{'vendor_id': '8086', 'device_id': '1502'}], + request_id=uuids.pci_request_id, + requester_id=uuids.requester_id, + numa_policy=fields.PCINUMAAffinityPolicy.PREFERRED) + versions = ovo_base.obj_tree_get_versions('InstancePCIRequest') + primitive = topo_obj.obj_to_primitive(target_version='1.2', + version_manifest=versions) + + self.assertNotIn('requester_id', primitive['nova_object.data']) + self.assertIn('numa_policy', primitive['nova_object.data']) + class TestInstancePCIRequests(test_objects._LocalTest, _TestInstancePCIRequests): diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 12efdf353107..37947c87ec6a 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1111,7 +1111,7 @@ object_data = { 'InstanceMappingList': '1.2-ee638619aa3d8a82a59c0c83bfa64d78', 'InstanceNUMACell': '1.4-7c1eb9a198dee076b4de0840e45f4f55', 'InstanceNUMATopology': '1.3-ec0030cb0402a49c96da7051c037082a', - 'InstancePCIRequest': '1.2-6344dd8bd1bf873e7325c07afe47f774', + 'InstancePCIRequest': '1.3-f6d324f1c337fad4f34892ed5f484c9a', 'InstancePCIRequests': '1.1-65e38083177726d806684cb1cc0136d2', 'KeyPair': '1.4-1244e8d1b103cc69d038ed78ab3a8cc6', 'KeyPairList': '1.3-94aad3ac5c938eef4b5e83da0212f506', diff --git a/nova/tests/unit/pci/test_request.py b/nova/tests/unit/pci/test_request.py index 7ac20859c8b0..bfeea10711c8 100644 --- a/nova/tests/unit/pci/test_request.py +++ b/nova/tests/unit/pci/test_request.py @@ -208,12 +208,14 @@ class AliasTestCase(test.NoDBTestCase): self.flags(alias=[_fake_alias1, _fake_alias3], group='pci') expect_request = [ {'count': 3, + 'requester_id': None, 'spec': [{'vendor_id': '8086', 'product_id': '4443', 'dev_type': 'type-PCI', 'capability_type': 'pci'}], 'alias_name': 'QuicAssist'}, {'count': 1, + 'requester_id': None, 'spec': [{'vendor_id': '8086', 'product_id': '1111', 'dev_type': "type-PF", 'capability_type': 'pci'}],