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