Update port_status to ACTIVE during live-migration

During live-migration nova waits for 'network-vif-plugged' event
in order to proceeed with live-migration [1]. While using OVN
it never happened because the original design assumes usage
of neutron agents.

This patch updates port status from DOWN to ACTIVE during
pre_live_migration state, which in fact for Neutron/ML2
is done by neutron-ovs-agent, just only to emit
'network-vif-plugged' notification and allow nova
to perform live-migration.

[1] https://review.opendev.org/#/c/558001/

Change-Id: Ib9fe6e1bfea1d5f62b2f2b6fdb12d16878108c3f
Related-Bug: 1834045
(cherry picked from commit 229f894ee6aff6b5da8cc399575537feed1c6a49)
This commit is contained in:
Maciej Józefczyk 2019-07-31 12:21:42 +00:00
parent 5b382bbfe7
commit 3166e8206c
3 changed files with 45 additions and 0 deletions
networking_ovn

@ -44,6 +44,7 @@ OVN_PORT_BINDING_PROFILE_PARAMS = [{'parent_name': six.string_types,
'tag': six.integer_types},
{'vtep-physical-switch': six.string_types,
'vtep-logical-switch': six.string_types}]
MIGRATING_ATTR = 'migrating_to'
OVN_ROUTER_PORT_OPTION_KEYS = ['router-port', 'nat-addresses']
OVN_GATEWAY_CHASSIS_KEY = 'redirect-chassis'
OVN_GATEWAY_NAT_ADDRESSES_KEY = 'nat-addresses'

@ -529,6 +529,26 @@ class OVNMechanismDriver(api.MechanismDriver):
port['network'] = context.network.current
original_port = copy.deepcopy(context.original)
original_port['network'] = context.network.current
# NOTE(mjozefcz): Check if port is in migration state. If so update
# the port status from DOWN to UP in order to generate 'fake'
# vif-interface-plugged event. This workaround is needed to
# perform live-migration with live_migration_wait_for_vif_plug=True.
if ((port['status'] == const.PORT_STATUS_DOWN and
ovn_const.MIGRATING_ATTR in port[portbindings.PROFILE].keys() and
port[portbindings.VIF_TYPE] == portbindings.VIF_TYPE_OVS)):
admin_context = n_context.get_admin_context()
LOG.info("Setting port %s status from DOWN to UP in order "
"to emit vif-interface-plugged event.",
port['id'])
self._plugin.update_port_status(admin_context, port['id'],
const.PORT_STATUS_ACTIVE)
# The revision has been changed. In the meantime
# port-update event already updated the OVN configuration,
# So there is no need to update it again here. Anyway it
# will fail that OVN has port with bigger revision.
return
self._ovn_client.update_port(port, port_object=original_port)
self._notify_dhcp_updated(port['id'])

@ -1493,6 +1493,30 @@ class TestOVNMechanismDriver(test_plugin.Ml2PluginV2TestCase):
passed_fake_port, port_object=passed_fake_port_orig)
mock_notify_dhcp.assert_called_once_with(fake_port['id'])
@mock.patch.object(mech_driver.OVNMechanismDriver,
'_is_port_provisioning_required', lambda *_: True)
@mock.patch.object(mech_driver.OVNMechanismDriver, '_notify_dhcp_updated')
@mock.patch.object(ovn_client.OVNClient, 'update_port')
@mock.patch.object(context, 'get_admin_context')
def test_update_port_postcommit_live_migration(
self, mock_admin_context, mock_update_port, mock_notify_dhcp):
self.plugin.update_port_status = mock.Mock()
foo_admin_context = mock.Mock()
mock_admin_context.return_value = foo_admin_context
fake_port = fakes.FakePort.create_one_port(
attrs={
'status': const.PORT_STATUS_DOWN,
portbindings.PROFILE: {ovn_const.MIGRATING_ATTR: 'foo'},
portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS}).info()
fake_ctx = mock.Mock(current=fake_port, original=fake_port)
self.mech_driver.update_port_postcommit(fake_ctx)
mock_update_port.assert_not_called()
mock_notify_dhcp.assert_not_called()
self.plugin.update_port_status.assert_called_once_with(
foo_admin_context, fake_port['id'], const.PORT_STATUS_ACTIVE)
def _test__update_dnat_entry_if_needed(self, up=True):
ovn_config.cfg.CONF.set_override(
'enable_distributed_floating_ip', True, group='ovn')