@@ -2106,16 +2106,16 @@ def create_resource_requests(
2106
2106
port_numa_policy = None
2107
2107
2108
2108
if request_net .port_id :
2109
+ # InstancePCIRequest.requester_id is semantically linked
2110
+ # to a port with a resource_request.
2111
+ requester_id = request_net .port_id
2109
2112
(vnic_type , trusted , network_id , resource_request ,
2110
2113
port_numa_policy ) = self ._get_port_vnic_info (
2111
2114
context , neutron , request_net .port_id )
2112
2115
physnet , tunneled_ = self ._get_physnet_tunneled_info (
2113
2116
context , neutron , network_id )
2114
2117
2115
2118
if resource_request :
2116
- # InstancePCIRequest.requester_id is semantically linked
2117
- # to a port with a resource_request.
2118
- requester_id = request_net .port_id
2119
2119
# NOTE(gibi): explicitly orphan the RequestGroup by setting
2120
2120
# context=None as we never intended to save it to the DB.
2121
2121
resource_requests .append (
@@ -3363,6 +3363,37 @@ def _get_pci_mapping_for_migration(self, instance, migration):
3363
3363
migration .get ('status' ) == 'reverted' )
3364
3364
return instance .migration_context .get_pci_mapping_for_migration (revert )
3365
3365
3366
+ def _get_port_pci_slot (self , context , instance , port ):
3367
+ """Find the PCI address of the device corresponding to the port.
3368
+ Assumes the port is an SRIOV one.
3369
+
3370
+ :param context: The request context.
3371
+ :param instance: The instance to which the port is attached.
3372
+ :param port: The Neutron port, as obtained from the Neutron API
3373
+ JSON form.
3374
+ :return: The PCI address as a string, or None if unable to find.
3375
+ """
3376
+ # Find the port's PCIRequest, or return None
3377
+ for r in instance .pci_requests .requests :
3378
+ if r .requester_id == port ['id' ]:
3379
+ request = r
3380
+ break
3381
+ else :
3382
+ LOG .debug ('No PCI request found for port %s' , port ['id' ],
3383
+ instance = instance )
3384
+ return None
3385
+ # Find the request's device, or return None
3386
+ for d in instance .pci_devices :
3387
+ if d .request_id == request .request_id :
3388
+ device = d
3389
+ break
3390
+ else :
3391
+ LOG .debug ('No PCI device found for request %s' ,
3392
+ request .request_id , instance = instance )
3393
+ return None
3394
+ # Return the device's PCI address
3395
+ return device .address
3396
+
3366
3397
def _update_port_binding_for_instance (
3367
3398
self , context , instance , host , migration = None ,
3368
3399
provider_mappings = None ):
@@ -3371,7 +3402,6 @@ def _update_port_binding_for_instance(
3371
3402
search_opts = {'device_id' : instance .uuid ,
3372
3403
'tenant_id' : instance .project_id }
3373
3404
data = neutron .list_ports (** search_opts )
3374
- pci_mapping = None
3375
3405
port_updates = []
3376
3406
ports = data ['ports' ]
3377
3407
FAILED_VIF_TYPES = (network_model .VIF_TYPE_UNBOUND ,
@@ -3404,25 +3434,36 @@ def _update_port_binding_for_instance(
3404
3434
# that this function is called without a migration object, such
3405
3435
# as in an unshelve operation.
3406
3436
vnic_type = p .get ('binding:vnic_type' )
3407
- if (vnic_type in network_model .VNIC_TYPES_SRIOV and
3408
- migration is not None and
3409
- not migration .is_live_migration ):
3410
- # Note(adrianc): for live migration binding profile was already
3411
- # updated in conductor when calling bind_ports_to_host()
3412
- if not pci_mapping :
3413
- pci_mapping = self ._get_pci_mapping_for_migration (
3414
- instance , migration )
3415
-
3416
- pci_slot = binding_profile .get ('pci_slot' )
3417
- new_dev = pci_mapping .get (pci_slot )
3418
- if new_dev :
3419
- binding_profile .update (
3420
- self ._get_pci_device_profile (new_dev ))
3421
- updates [constants .BINDING_PROFILE ] = binding_profile
3437
+ if vnic_type in network_model .VNIC_TYPES_SRIOV :
3438
+ # NOTE(artom) For migrations, update the binding profile from
3439
+ # the migration object...
3440
+ if migration is not None :
3441
+ # NOTE(artom) ... except for live migrations, because the
3442
+ # conductor has already done that whe calling
3443
+ # bind_ports_to_host().
3444
+ if not migration .is_live_migration :
3445
+ pci_mapping = self ._get_pci_mapping_for_migration (
3446
+ instance , migration )
3447
+
3448
+ pci_slot = binding_profile .get ('pci_slot' )
3449
+ new_dev = pci_mapping .get (pci_slot )
3450
+ if new_dev :
3451
+ binding_profile .update (
3452
+ self ._get_pci_device_profile (new_dev ))
3453
+ updates [
3454
+ constants .BINDING_PROFILE ] = binding_profile
3455
+ else :
3456
+ raise exception .PortUpdateFailed (port_id = p ['id' ],
3457
+ reason = _ ("Unable to correlate PCI slot %s" ) %
3458
+ pci_slot )
3459
+ # NOTE(artom) If migration is None, this is an unshevle, and we
3460
+ # need to figure out the pci_slot from the InstancePCIRequest
3461
+ # and PciDevice objects.
3422
3462
else :
3423
- raise exception .PortUpdateFailed (port_id = p ['id' ],
3424
- reason = _ ("Unable to correlate PCI slot %s" ) %
3425
- pci_slot )
3463
+ pci_slot = self ._get_port_pci_slot (context , instance , p )
3464
+ if pci_slot :
3465
+ binding_profile .update ({'pci_slot' : pci_slot })
3466
+ updates [constants .BINDING_PROFILE ] = binding_profile
3426
3467
3427
3468
# NOTE(gibi): during live migration the conductor already sets the
3428
3469
# allocation key in the port binding. However during resize, cold
0 commit comments