Skip to content

Commit 4f5f834

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Set migrate_data.vifs only when using multiple port bindings"
2 parents ef76944 + b8f3be6 commit 4f5f834

File tree

5 files changed

+110
-23
lines changed

5 files changed

+110
-23
lines changed

nova/compute/manager.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7720,15 +7720,18 @@ def check_can_live_migrate_destination(self, ctxt, instance,
77207720
LOG.info('Destination was ready for NUMA live migration, '
77217721
'but source is either too old, or is set to an '
77227722
'older upgrade level.', instance=instance)
7723-
# Create migrate_data vifs
7724-
migrate_data.vifs = \
7725-
migrate_data_obj.VIFMigrateData.create_skeleton_migrate_vifs(
7726-
instance.get_network_info())
7727-
# Claim PCI devices for VIFs on destination (if needed)
7728-
port_id_to_pci = self._claim_pci_for_instance_vifs(ctxt, instance)
7729-
# Update migrate VIFs with the newly claimed PCI devices
7730-
self._update_migrate_vifs_profile_with_pci(migrate_data.vifs,
7731-
port_id_to_pci)
7723+
if self.network_api.supports_port_binding_extension(ctxt):
7724+
# Create migrate_data vifs
7725+
migrate_data.vifs = \
7726+
migrate_data_obj.\
7727+
VIFMigrateData.create_skeleton_migrate_vifs(
7728+
instance.get_network_info())
7729+
# Claim PCI devices for VIFs on destination (if needed)
7730+
port_id_to_pci = self._claim_pci_for_instance_vifs(
7731+
ctxt, instance)
7732+
# Update migrate VIFs with the newly claimed PCI devices
7733+
self._update_migrate_vifs_profile_with_pci(
7734+
migrate_data.vifs, port_id_to_pci)
77327735
finally:
77337736
self.driver.cleanup_live_migration_destination_check(ctxt,
77347737
dest_check_data)
@@ -7896,8 +7899,12 @@ def pre_live_migration(self, context, instance, block_migration, disk,
78967899
# determine if it should wait for a 'network-vif-plugged' event
78977900
# from neutron before starting the actual guest transfer in the
78987901
# hypervisor
7902+
using_multiple_port_bindings = (
7903+
'vifs' in migrate_data and migrate_data.vifs)
78997904
migrate_data.wait_for_vif_plugged = (
7900-
CONF.compute.live_migration_wait_for_vif_plug)
7905+
CONF.compute.live_migration_wait_for_vif_plug and
7906+
using_multiple_port_bindings
7907+
)
79017908

79027909
# NOTE(tr3buchet): setup networks on destination host
79037910
self.network_api.setup_networks_on_host(context, instance,

nova/tests/functional/regressions/test_bug_1888395.py

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
import fixtures
1414

15+
from lxml import etree
16+
from urllib import parse as urlparse
17+
1518
from nova import context
1619
from nova.network import constants as neutron_constants
1720
from nova.network import neutron
@@ -67,6 +70,40 @@ def setUp(self):
6770
kB_mem=10740000)})
6871

6972
self.ctxt = context.get_admin_context()
73+
# TODO(sean-k-mooney): remove this when it is part of ServersTestBase
74+
self.useFixture(fixtures.MonkeyPatch(
75+
'nova.tests.unit.virt.libvirt.fakelibvirt.Domain.migrateToURI3',
76+
self._migrate_stub))
77+
78+
def _migrate_stub(self, domain, destination, params, flags):
79+
"""Stub out migrateToURI3."""
80+
81+
src_hostname = domain._connection.hostname
82+
dst_hostname = urlparse.urlparse(destination).netloc
83+
84+
# In a real live migration, libvirt and QEMU on the source and
85+
# destination talk it out, resulting in the instance starting to exist
86+
# on the destination. Fakelibvirt cannot do that, so we have to
87+
# manually create the "incoming" instance on the destination
88+
# fakelibvirt.
89+
dst = self.computes[dst_hostname]
90+
dst.driver._host.get_connection().createXML(
91+
params['destination_xml'],
92+
'fake-createXML-doesnt-care-about-flags')
93+
94+
src = self.computes[src_hostname]
95+
conn = src.driver._host.get_connection()
96+
97+
# because migrateToURI3 is spawned in a background thread, this method
98+
# does not block the upper nova layers. Because we don't want nova to
99+
# think the live migration has finished until this method is done, the
100+
# last thing we do is make fakelibvirt's Domain.jobStats() return
101+
# VIR_DOMAIN_JOB_COMPLETED.
102+
server = etree.fromstring(
103+
params['destination_xml']
104+
).find('./uuid').text
105+
dom = conn.lookupByUUIDString(server)
106+
dom.complete_job()
70107

71108
def test_live_migrate(self):
72109
server = self._create_server(
@@ -86,14 +123,7 @@ def test_live_migrate(self):
86123
}
87124
)
88125

89-
# FIXME(sean-k-mooney): this should succeed but because of bug #188395
90-
# it will fail.
91-
# self._wait_for_server_parameter(
92-
# server, {'OS-EXT-SRV-ATTR:host': 'end_host', 'status': 'ACTIVE'})
93-
# because of the bug the migration will fail in pre_live_migrate so
94-
# the vm should still be active on the start_host
95126
self._wait_for_server_parameter(
96-
server, {'OS-EXT-SRV-ATTR:host': 'start_host', 'status': 'ACTIVE'})
97-
127+
server, {'OS-EXT-SRV-ATTR:host': 'end_host', 'status': 'ACTIVE'})
98128
msg = "NotImplementedError: Cannot load 'vif_type' in the base class"
99-
self.assertIn(msg, self.stdlog.logger.output)
129+
self.assertNotIn(msg, self.stdlog.logger.output)

nova/tests/unit/compute/test_compute.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"""Tests for compute service."""
1919

2020
import datetime
21+
import fixtures as std_fixtures
2122
from itertools import chain
2223
import operator
2324
import sys
@@ -6108,13 +6109,19 @@ def stupid(*args, **kwargs):
61086109
return fake_network.fake_get_instance_nw_info(self)
61096110

61106111
self.stub_out('nova.network.neutron.API.get_instance_nw_info', stupid)
6111-
6112+
self.useFixture(
6113+
std_fixtures.MonkeyPatch(
6114+
'nova.network.neutron.API.supports_port_binding_extension',
6115+
lambda *args: True))
61126116
# creating instance testdata
61136117
instance = self._create_fake_instance_obj({'host': 'dummy'})
61146118
c = context.get_admin_context()
61156119
fake_notifier.NOTIFICATIONS = []
61166120
migrate_data = objects.LibvirtLiveMigrateData(
61176121
is_shared_instance_path=False)
6122+
vifs = migrate_data_obj.VIFMigrateData.create_skeleton_migrate_vifs(
6123+
stupid())
6124+
migrate_data.vifs = vifs
61186125
mock_pre.return_value = migrate_data
61196126

61206127
with mock.patch.object(self.compute.network_api,

nova/tests/unit/compute/test_compute_mgr.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import contextlib
1616
import copy
1717
import datetime
18+
import fixtures as std_fixtures
1819
import time
1920

2021
from cinderclient import exceptions as cinder_exception
@@ -3372,20 +3373,48 @@ def _test_check_can_live_migrate_destination(self, do_raise=False,
33723373
mock_event.assert_called_once_with(
33733374
self.context, 'compute_check_can_live_migrate_destination',
33743375
CONF.host, instance.uuid, graceful_exit=False)
3376+
return result
33753377

33763378
def test_check_can_live_migrate_destination_success(self):
3379+
self.useFixture(std_fixtures.MonkeyPatch(
3380+
'nova.network.neutron.API.supports_port_binding_extension',
3381+
lambda *args: True))
33773382
self._test_check_can_live_migrate_destination()
33783383

33793384
def test_check_can_live_migrate_destination_fail(self):
3385+
self.useFixture(std_fixtures.MonkeyPatch(
3386+
'nova.network.neutron.API.supports_port_binding_extension',
3387+
lambda *args: True))
33803388
self.assertRaises(
3381-
test.TestingException,
3382-
self._test_check_can_live_migrate_destination,
3383-
do_raise=True)
3389+
test.TestingException,
3390+
self._test_check_can_live_migrate_destination,
3391+
do_raise=True)
3392+
3393+
def test_check_can_live_migrate_destination_contins_vifs(self):
3394+
self.useFixture(std_fixtures.MonkeyPatch(
3395+
'nova.network.neutron.API.supports_port_binding_extension',
3396+
lambda *args: True))
3397+
migrate_data = self._test_check_can_live_migrate_destination()
3398+
self.assertIn('vifs', migrate_data)
3399+
self.assertIsNotNone(migrate_data.vifs)
3400+
3401+
def test_check_can_live_migrate_destination_no_binding_extended(self):
3402+
self.useFixture(std_fixtures.MonkeyPatch(
3403+
'nova.network.neutron.API.supports_port_binding_extension',
3404+
lambda *args: False))
3405+
migrate_data = self._test_check_can_live_migrate_destination()
3406+
self.assertNotIn('vifs', migrate_data)
33843407

33853408
def test_check_can_live_migrate_destination_src_numa_lm_false(self):
3409+
self.useFixture(std_fixtures.MonkeyPatch(
3410+
'nova.network.neutron.API.supports_port_binding_extension',
3411+
lambda *args: True))
33863412
self._test_check_can_live_migrate_destination(src_numa_lm=False)
33873413

33883414
def test_check_can_live_migrate_destination_src_numa_lm_true(self):
3415+
self.useFixture(std_fixtures.MonkeyPatch(
3416+
'nova.network.neutron.API.supports_port_binding_extension',
3417+
lambda *args: True))
33893418
self._test_check_can_live_migrate_destination(src_numa_lm=True)
33903419

33913420
def test_dest_can_numa_live_migrate(self):
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
fixes:
3+
- |
4+
In the Rocky (18.0.0) release support was added to nova to use neutron's
5+
multiple port binding feature when the binding-extended API extension
6+
is available. In the Train (20.0.0) release the SR-IOV live migration
7+
feature broke the semantics of the vifs field in the ``migration_data``
8+
object that signals if the new multiple port binding workflow should
9+
be used by always populating it even when the ``binding-extended`` API
10+
extension is not present. This broke live migration for any deployment
11+
that did not support the optional ``binding-extended`` API extension.
12+
The Rocky behavior has now been restored enabling live migration
13+
using the single port binding workflow when multiple port bindings
14+
are not available.

0 commit comments

Comments
 (0)