Skip to content

Commit 57c39d4

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Fix migration with remote-managed ports & add FT"
2 parents 2b7e44b + 3fd7e94 commit 57c39d4

File tree

7 files changed

+739
-51
lines changed

7 files changed

+739
-51
lines changed

nova/compute/manager.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
from nova.objects import instance as obj_instance
8585
from nova.objects import migrate_data as migrate_data_obj
8686
from nova.pci import request as pci_req_module
87+
from nova.pci import utils as pci_utils
8788
from nova.pci import whitelist
8889
from nova import safe_utils
8990
from nova.scheduler.client import query
@@ -10885,6 +10886,17 @@ def _update_migrate_vifs_profile_with_pci(self,
1088510886
profile['pci_slot'] = pci_dev.address
1088610887
profile['pci_vendor_info'] = ':'.join([pci_dev.vendor_id,
1088710888
pci_dev.product_id])
10889+
if profile.get('card_serial_number'):
10890+
# Assume it is there since Nova makes sure that PCI devices
10891+
# tagged as remote-managed have a serial in PCI VPD.
10892+
profile['card_serial_number'] = pci_dev.card_serial_number
10893+
if profile.get('pf_mac_address'):
10894+
profile['pf_mac_address'] = pci_utils.get_mac_by_pci_address(
10895+
pci_dev.parent_addr)
10896+
if profile.get('vf_num'):
10897+
profile['vf_num'] = pci_utils.get_vf_num_by_pci_address(
10898+
pci_dev.address)
10899+
1088810900
mig_vif.profile = profile
1088910901
LOG.debug("Updating migrate VIF profile for port %(port_id)s:"
1089010902
"%(profile)s", {'port_id': port_id,

nova/compute/resource_tracker.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,12 @@ def _move_claim(
328328
migration_id=migration.id,
329329
old_numa_topology=instance.numa_topology,
330330
new_numa_topology=claim.claimed_numa_topology,
331-
old_pci_devices=instance.pci_devices,
331+
# NOTE(gibi): the _update_usage_from_migration call below appends
332+
# the newly claimed pci devices to the instance.pci_devices list
333+
# to keep the migration context independent we need to make a copy
334+
# that list here. We need a deep copy as we need to duplicate
335+
# the instance.pci_devices.objects list
336+
old_pci_devices=copy.deepcopy(instance.pci_devices),
332337
new_pci_devices=claimed_pci_devices,
333338
old_pci_requests=instance.pci_requests,
334339
new_pci_requests=new_pci_requests,

nova/network/neutron.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3663,15 +3663,15 @@ def _get_pci_mapping_for_migration(self, instance, migration):
36633663
migration.get('status') == 'reverted')
36643664
return instance.migration_context.get_pci_mapping_for_migration(revert)
36653665

3666-
def _get_port_pci_slot(self, context, instance, port):
3667-
"""Find the PCI address of the device corresponding to the port.
3666+
def _get_port_pci_dev(self, context, instance, port):
3667+
"""Find the PCI device corresponding to the port.
36683668
Assumes the port is an SRIOV one.
36693669
36703670
:param context: The request context.
36713671
:param instance: The instance to which the port is attached.
36723672
:param port: The Neutron port, as obtained from the Neutron API
36733673
JSON form.
3674-
:return: The PCI address as a string, or None if unable to find.
3674+
:return: The PciDevice object, or None if unable to find.
36753675
"""
36763676
# Find the port's PCIRequest, or return None
36773677
for r in instance.pci_requests.requests:
@@ -3691,8 +3691,26 @@ def _get_port_pci_slot(self, context, instance, port):
36913691
LOG.debug('No PCI device found for request %s',
36923692
request.request_id, instance=instance)
36933693
return None
3694-
# Return the device's PCI address
3695-
return device.address
3694+
return device
3695+
3696+
def _update_port_pci_binding_profile(self, pci_dev, binding_profile):
3697+
"""Update the binding profile dict with new PCI device data.
3698+
3699+
:param pci_dev: The PciDevice object to update the profile with.
3700+
:param binding_profile: The dict to update.
3701+
"""
3702+
binding_profile.update({'pci_slot': pci_dev.address})
3703+
if binding_profile.get('card_serial_number'):
3704+
binding_profile.update({
3705+
'card_serial_number': pci_dev.card_serial_number})
3706+
if binding_profile.get('pf_mac_address'):
3707+
binding_profile.update({
3708+
'pf_mac_address': pci_utils.get_mac_by_pci_address(
3709+
pci_dev.parent_addr)})
3710+
if binding_profile.get('vf_num'):
3711+
binding_profile.update({
3712+
'vf_num': pci_utils.get_vf_num_by_pci_address(
3713+
pci_dev.address)})
36963714

36973715
def _update_port_binding_for_instance(
36983716
self, context, instance, host, migration=None,
@@ -3760,9 +3778,10 @@ def _update_port_binding_for_instance(
37603778
# need to figure out the pci_slot from the InstancePCIRequest
37613779
# and PciDevice objects.
37623780
else:
3763-
pci_slot = self._get_port_pci_slot(context, instance, p)
3764-
if pci_slot:
3765-
binding_profile.update({'pci_slot': pci_slot})
3781+
pci_dev = self._get_port_pci_dev(context, instance, p)
3782+
if pci_dev:
3783+
self._update_port_pci_binding_profile(pci_dev,
3784+
binding_profile)
37663785
updates[constants.BINDING_PROFILE] = binding_profile
37673786

37683787
# NOTE(gibi): during live migration the conductor already sets the

nova/tests/fixtures/libvirt.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ class FakePCIDevice(object):
275275
<product id='0x%(prod_id)s'>%(prod_name)s</product>
276276
<vendor id='0x%(vend_id)s'>%(vend_name)s</vendor>
277277
%(capability)s
278+
%(vpd_capability)s
278279
<iommuGroup number='%(iommu_group)d'>
279280
<address domain='0x0000' bus='%(bus)#02x' slot='%(slot)#02x' function='0x%(function)d'/>
280281
</iommuGroup>
@@ -293,13 +294,22 @@ class FakePCIDevice(object):
293294
<availableInstances>%(instances)s</availableInstances>
294295
</type>""".strip()) # noqa
295296

297+
vpd_cap_templ = textwrap.dedent("""
298+
<capability type='vpd'>
299+
<name>%(name)s</name>
300+
%(fields)s
301+
</capability>""".strip())
302+
vpd_fields_templ = textwrap.dedent("""
303+
<fields access='%(access)s'>%(section_fields)s</fields>""".strip())
304+
vpd_field_templ = """<%(field_name)s>%(field_value)s</%(field_name)s>"""
305+
296306
is_capable_of_mdevs = False
297307

298308
def __init__(
299309
self, dev_type, bus, slot, function, iommu_group, numa_node, *,
300310
vf_ratio=None, multiple_gpu_types=False, generic_types=False,
301311
parent=None, vend_id=None, vend_name=None, prod_id=None,
302-
prod_name=None, driver_name=None,
312+
prod_name=None, driver_name=None, vpd_fields=None
303313
):
304314
"""Populate pci devices
305315
@@ -340,6 +350,8 @@ def __init__(
340350
self.prod_name = prod_name
341351
self.driver_name = driver_name
342352

353+
self.vpd_fields = vpd_fields
354+
343355
self.generate_xml()
344356

345357
def generate_xml(self, skip_capability=False):
@@ -447,6 +459,7 @@ def generate_xml(self, skip_capability=False):
447459
'prod_name': prod_name,
448460
'driver': driver,
449461
'capability': capability,
462+
'vpd_capability': self.format_vpd_cap(),
450463
'iommu_group': self.iommu_group,
451464
'numa_node': self.numa_node,
452465
'parent': parent,
@@ -457,6 +470,30 @@ def generate_xml(self, skip_capability=False):
457470
if self.numa_node == -1:
458471
self.pci_device = self.pci_device.replace("<numa node='-1'/>", "")
459472

473+
def format_vpd_cap(self):
474+
if not self.vpd_fields:
475+
return ''
476+
fields = []
477+
for access_type in ('readonly', 'readwrite'):
478+
section_fields = []
479+
for field_name, field_value in self.vpd_fields.get(
480+
access_type, {}).items():
481+
section_fields.append(self.vpd_field_templ % {
482+
'field_name': field_name,
483+
'field_value': field_value,
484+
})
485+
if section_fields:
486+
fields.append(
487+
self.vpd_fields_templ % {
488+
'access': access_type,
489+
'section_fields': '\n'.join(section_fields),
490+
}
491+
)
492+
return self.vpd_cap_templ % {
493+
'name': self.vpd_fields.get('name', ''),
494+
'fields': '\n'.join(fields)
495+
}
496+
460497
def XMLDesc(self, flags):
461498
return self.pci_device
462499

@@ -572,7 +609,7 @@ def add_device(
572609
self, dev_type, bus, slot, function, iommu_group, numa_node,
573610
vf_ratio=None, multiple_gpu_types=False, generic_types=False,
574611
parent=None, vend_id=None, vend_name=None, prod_id=None,
575-
prod_name=None, driver_name=None,
612+
prod_name=None, driver_name=None, vpd_fields=None,
576613
):
577614
pci_dev_name = _get_libvirt_nodedev_name(bus, slot, function)
578615

@@ -593,7 +630,9 @@ def add_device(
593630
vend_name=vend_name,
594631
prod_id=prod_id,
595632
prod_name=prod_name,
596-
driver_name=driver_name)
633+
driver_name=driver_name,
634+
vpd_fields=vpd_fields,
635+
)
597636
self.devices[pci_dev_name] = dev
598637
return dev
599638

nova/tests/functional/libvirt/base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,21 @@ class LibvirtNeutronFixture(nova_fixtures.NeutronFixture):
316316
'binding:vif_type': 'ovs',
317317
'binding:vnic_type': 'normal',
318318
}
319+
network_3_port_2 = {
320+
'id': '132c3875-b175-4b20-8a57-7a76219a13ae',
321+
'network_id': network_3['id'],
322+
'status': 'ACTIVE',
323+
'mac_address': 'd2:0b:fd:99:89:8b',
324+
'fixed_ips': [
325+
{
326+
'ip_address': '192.168.2.7',
327+
'subnet_id': subnet_3['id']
328+
}
329+
],
330+
'binding:vif_details': {},
331+
'binding:vif_type': 'ovs',
332+
'binding:vnic_type': 'remote-managed',
333+
}
319334
network_4_port_1 = {
320335
'id': 'b4cd0b93-2ac8-40a7-9fa4-2cd680ccdf3e',
321336
'network_id': network_4['id'],
@@ -361,6 +376,21 @@ class LibvirtNeutronFixture(nova_fixtures.NeutronFixture):
361376
'binding:vif_type': 'hw_veb',
362377
'binding:vnic_type': 'direct',
363378
}
379+
network_4_port_4 = {
380+
'id': 'a31e381d-41ec-41e4-b5a5-ec4ef705fafa',
381+
'network_id': network_1['id'],
382+
'status': 'ACTIVE',
383+
'mac_address': '71:ce:c7:2b:cd:dd',
384+
'fixed_ips': [
385+
{
386+
'ip_address': '192.168.4.9',
387+
'subnet_id': subnet_4['id']
388+
}
389+
],
390+
'binding:vif_details': {},
391+
'binding:vif_type': 'ovs',
392+
'binding:vnic_type': 'remote-managed',
393+
}
364394

365395
def __init__(self, test):
366396
super(LibvirtNeutronFixture, self).__init__(test)

0 commit comments

Comments
 (0)