Skip to content

Commit

Permalink
only wait for plugtime events in pre-live-migration
Browse files Browse the repository at this point in the history
This change modifies _get_neutron_events_for_live_migration
to filter the event to just the subset that will be sent
at plug-time.

Currently neuton has a bug where by the dhcp agent
send a network-vif-plugged event during live migration after
we update the port profile with "migrating-to:"
this cause a network-vif-plugged event to be sent for
configuration where vif_plugging in nova/os-vif is a noop.

when that is corrected the current logic in nova cause the migration
to time out as its waiting for an event that will never arrive.

This change filters the set of events we wait for to just the plug
time events.

This backport has squashed the follow up change
I37c712ba9a0ab88c44d10f80da3254ab6c463a68 to remove the unused
migration paramater orginally added by this patch to
_get_neutron_events_for_live_migration

Related-Bug: #1815989
Closes-Bug: #1901707
Change-Id: Id2d8d72d30075200d2b07b847c4e5568599b0d3b
(cherry picked from commit 8b33ac0)
(cherry picked from commit ef348c4)
  • Loading branch information
SeanMooney authored and lyarwood committed Feb 18, 2021
1 parent 337ee4f commit d9c833d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 11 deletions.
4 changes: 2 additions & 2 deletions nova/compute/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7922,8 +7922,8 @@ def _get_neutron_events_for_live_migration(instance):
# We don't generate events if CONF.vif_plugging_timeout=0
# meaning that the operator disabled using them.
if CONF.vif_plugging_timeout:
return [('network-vif-plugged', vif['id'])
for vif in instance.get_network_info()]
return (instance.get_network_info()
.get_live_migration_plug_time_events())
else:
return []

Expand Down
23 changes: 19 additions & 4 deletions nova/network/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,14 @@ def has_bind_time_event(self, migration):
return (self.is_hybrid_plug_enabled() and not
migration.is_same_host())

@property
def has_live_migration_plug_time_event(self):
"""Returns whether this VIF's network-vif-plugged external event will
be sent by Neutron at "plugtime" - in other words, as soon as neutron
completes configuring the network backend.
"""
return self.is_hybrid_plug_enabled()

def is_hybrid_plug_enabled(self):
return self['details'].get(VIF_DETAILS_OVS_HYBRID_PLUG, False)

Expand Down Expand Up @@ -530,15 +538,22 @@ def json(self):
return jsonutils.dumps(self)

def get_bind_time_events(self, migration):
"""Returns whether any of our VIFs have "bind-time" events. See
has_bind_time_event() docstring for more details.
"""Returns a list of external events for any VIFs that have
"bind-time" events during cold migration.
"""
return [('network-vif-plugged', vif['id'])
for vif in self if vif.has_bind_time_event(migration)]

def get_live_migration_plug_time_events(self):
"""Returns a list of external events for any VIFs that have
"plug-time" events during live migration.
"""
return [('network-vif-plugged', vif['id'])
for vif in self if vif.has_live_migration_plug_time_event]

def get_plug_time_events(self, migration):
"""Complementary to get_bind_time_events(), any event that does not
fall in that category is a plug-time event.
"""Returns a list of external events for any VIFs that have
"plug-time" events during cold migration.
"""
return [('network-vif-plugged', vif['id'])
for vif in self if not vif.has_bind_time_event(migration)]
Expand Down
32 changes: 27 additions & 5 deletions nova/tests/unit/compute/test_compute_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -9134,12 +9134,18 @@ def test_get_neutron_events_for_live_migration_empty(self):
"""Tests the various ways that _get_neutron_events_for_live_migration
will return an empty list.
"""
migration = mock.Mock()
migration.is_same_host = lambda: False
self.assertFalse(migration.is_same_host())

# 1. no timeout
self.flags(vif_plugging_timeout=0)

with mock.patch.object(self.instance, 'get_network_info') as nw_info:
nw_info.return_value = network_model.NetworkInfo(
[network_model.VIF(uuids.port1)])
[network_model.VIF(uuids.port1, details={
network_model.VIF_DETAILS_OVS_HYBRID_PLUG: True})])
self.assertTrue(nw_info.return_value[0].is_hybrid_plug_enabled())
self.assertEqual(
[], self.compute._get_neutron_events_for_live_migration(
self.instance))
Expand All @@ -9148,7 +9154,18 @@ def test_get_neutron_events_for_live_migration_empty(self):
self.flags(vif_plugging_timeout=300)

with mock.patch.object(self.instance, 'get_network_info') as nw_info:
nw_info.return_value = []
nw_info.return_value = network_model.NetworkInfo([])
self.assertEqual(
[], self.compute._get_neutron_events_for_live_migration(
self.instance))

# 3. no plug time events
with mock.patch.object(self.instance, 'get_network_info') as nw_info:
nw_info.return_value = network_model.NetworkInfo(
[network_model.VIF(
uuids.port1, details={
network_model.VIF_DETAILS_OVS_HYBRID_PLUG: False})])
self.assertFalse(nw_info.return_value[0].is_hybrid_plug_enabled())
self.assertEqual(
[], self.compute._get_neutron_events_for_live_migration(
self.instance))
Expand All @@ -9166,9 +9183,11 @@ def test_live_migration_wait_vif_plugged(
wait_for_vif_plugged=True)
mock_get_bdms.return_value = objects.BlockDeviceMappingList(objects=[])
mock_pre_live_mig.return_value = migrate_data
details = {network_model.VIF_DETAILS_OVS_HYBRID_PLUG: True}
self.instance.info_cache = objects.InstanceInfoCache(
network_info=network_model.NetworkInfo([
network_model.VIF(uuids.port1), network_model.VIF(uuids.port2)
network_model.VIF(uuids.port1, details=details),
network_model.VIF(uuids.port2, details=details)
]))
self.compute._waiting_live_migrations[self.instance.uuid] = (
self.migration, mock.MagicMock()
Expand Down Expand Up @@ -9198,11 +9217,12 @@ def test_live_migration_wait_vif_plugged_old_dest_host(
of not waiting.
"""
migrate_data = objects.LibvirtLiveMigrateData()
details = {network_model.VIF_DETAILS_OVS_HYBRID_PLUG: True}
mock_get_bdms.return_value = objects.BlockDeviceMappingList(objects=[])
mock_pre_live_mig.return_value = migrate_data
self.instance.info_cache = objects.InstanceInfoCache(
network_info=network_model.NetworkInfo([
network_model.VIF(uuids.port1)]))
network_model.VIF(uuids.port1, details=details)]))
self.compute._waiting_live_migrations[self.instance.uuid] = (
self.migration, mock.MagicMock()
)
Expand Down Expand Up @@ -9346,9 +9366,11 @@ def test_live_migration_aborted_before_running(self, mock_rpc,
mock_get_bdms.return_value = source_bdms
migrate_data = objects.LibvirtLiveMigrateData(
wait_for_vif_plugged=True)
details = {network_model.VIF_DETAILS_OVS_HYBRID_PLUG: True}
self.instance.info_cache = objects.InstanceInfoCache(
network_info=network_model.NetworkInfo([
network_model.VIF(uuids.port1), network_model.VIF(uuids.port2)
network_model.VIF(uuids.port1, details=details),
network_model.VIF(uuids.port2, details=details)
]))
self.compute._waiting_live_migrations = {}
fake_migration = objects.Migration(
Expand Down

0 comments on commit d9c833d

Please sign in to comment.