Fix live-migration when using ovs-vif-driver
When live-migrating a vm the ports are not added to the bridge
at the destination. This patch ensures that ports are added
correctly during live migration.
Closes-Bug: #1551222
(cherry picked from commit ce3e4e9317
)
Change-Id: I70735ef1544622fbad2bf88d105192afe087a5b0
This commit is contained in:
parent
bf7069f72a
commit
f8420ebe57
|
@ -160,6 +160,10 @@ class HyperVDriver(driver.ComputeDriver):
|
|||
self._livemigrationops.post_live_migration(context, instance,
|
||||
block_device_info)
|
||||
|
||||
def post_live_migration_at_source(self, context, instance, network_info):
|
||||
"""Unplug VIFs from networks at source."""
|
||||
self._vmops.unplug_vifs(instance, network_info)
|
||||
|
||||
def post_live_migration_at_destination(self, context, instance,
|
||||
network_info,
|
||||
block_migration=False,
|
||||
|
|
|
@ -112,6 +112,7 @@ class LiveMigrationOps(object):
|
|||
network_info, block_migration):
|
||||
LOG.debug("post_live_migration_at_destination called",
|
||||
instance=instance_ref)
|
||||
self._vmops.post_start_vifs(instance_ref, network_info)
|
||||
|
||||
@check_os_version_requirement
|
||||
def check_can_live_migrate_destination(self, ctxt, instance_ref,
|
||||
|
|
|
@ -501,10 +501,7 @@ class VMOps(object):
|
|||
|
||||
if destroy_disks:
|
||||
self._delete_disk_files(instance_name)
|
||||
if network_info:
|
||||
for vif in network_info:
|
||||
vif_driver = self._get_vif_driver(vif.get('type'))
|
||||
vif_driver.unplug(instance, vif)
|
||||
self.unplug_vifs(instance, network_info)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE('Failed to destroy instance: %s'),
|
||||
|
@ -612,10 +609,7 @@ class VMOps(object):
|
|||
block_device_info)
|
||||
|
||||
self._set_vm_state(instance, constants.HYPERV_VM_STATE_ENABLED)
|
||||
if network_info:
|
||||
for vif in network_info:
|
||||
vif_driver = self._get_vif_driver(vif.get('type'))
|
||||
vif_driver.post_start(instance, vif)
|
||||
self.post_start_vifs(instance, network_info)
|
||||
|
||||
def _set_vm_state(self, instance, req_state):
|
||||
instance_name = instance.name
|
||||
|
@ -788,6 +782,18 @@ class VMOps(object):
|
|||
|
||||
self.power_on(instance)
|
||||
|
||||
def unplug_vifs(self, instance, network_info):
|
||||
if network_info:
|
||||
for vif in network_info:
|
||||
vif_driver = self._get_vif_driver(vif.get('type'))
|
||||
vif_driver.unplug(instance, vif)
|
||||
|
||||
def post_start_vifs(self, instance, network_info):
|
||||
if network_info:
|
||||
for vif in network_info:
|
||||
vif_driver = self._get_vif_driver(vif.get('type'))
|
||||
vif_driver.post_start(instance, vif)
|
||||
|
||||
def _check_hotplug_is_available(self, instance):
|
||||
if (self._get_vm_state(instance.name) ==
|
||||
constants.HYPERV_VM_STATE_DISABLED):
|
||||
|
|
|
@ -121,3 +121,12 @@ class LiveMigrationOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
mock.sentinel.block_device_info)
|
||||
self._livemigrops._pathutils.get_instance_dir.assert_called_once_with(
|
||||
mock.sentinel.instance.name, create_dir=False, remove_dir=True)
|
||||
|
||||
@mock.patch.object(livemigrationops.vmops.VMOps, 'post_start_vifs')
|
||||
def test_post_live_migration_at_destination(self, mock_post_start_vifs):
|
||||
self._livemigrops.post_live_migration_at_destination(
|
||||
mock.sentinel.context, mock.sentinel.instance,
|
||||
mock.sentinel.network_info, mock.sentinel.block_migration)
|
||||
|
||||
mock_post_start_vifs.assert_called_once_with(
|
||||
mock.sentinel.instance, mock.sentinel.network_info)
|
||||
|
|
|
@ -753,13 +753,15 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
@mock.patch('hyperv.nova.volumeops.VolumeOps.disconnect_volumes')
|
||||
@mock.patch('hyperv.nova.vmops.VMOps._delete_disk_files')
|
||||
@mock.patch('hyperv.nova.vmops.VMOps.power_off')
|
||||
def test_destroy(self, mock_power_off, mock_delete_disk_files,
|
||||
mock_disconnect_volumes):
|
||||
@mock.patch('hyperv.nova.vmops.VMOps.unplug_vifs')
|
||||
def test_destroy(self, mock_unplug_vifs, mock_power_off,
|
||||
mock_delete_disk_files, mock_disconnect_volumes):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
self._vmops._vmutils.vm_exists.return_value = True
|
||||
|
||||
self._vmops.destroy(instance=mock_instance,
|
||||
block_device_info=mock.sentinel.FAKE_BD_INFO)
|
||||
block_device_info=mock.sentinel.FAKE_BD_INFO,
|
||||
network_info=mock.sentinel.fake_network_info)
|
||||
|
||||
self._vmops._vmutils.vm_exists.assert_called_with(
|
||||
mock_instance.name)
|
||||
|
@ -770,6 +772,8 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
mock.sentinel.FAKE_BD_INFO)
|
||||
mock_delete_disk_files.assert_called_once_with(
|
||||
mock_instance.name)
|
||||
mock_unplug_vifs.assert_called_once_with(
|
||||
mock_instance, mock.sentinel.fake_network_info)
|
||||
|
||||
def test_destroy_inexistent_instance(self):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
|
@ -961,21 +965,14 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
mock_set_vm_state.assert_called_once_with(
|
||||
mock_instance, constants.HYPERV_VM_STATE_ENABLED)
|
||||
|
||||
@mock.patch.object(vmops.VMOps, '_get_vif_driver')
|
||||
def test_power_on_with_network_info(self, mock_get_vif_driver):
|
||||
@mock.patch.object(vmops.VMOps, 'post_start_vifs')
|
||||
def test_power_on_with_network_info(self, mock_post_start_vifs):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
fake_vif1 = {'id': mock.sentinel.ID1,
|
||||
'type': mock.sentinel.vif_type1}
|
||||
fake_vif2 = {'id': mock.sentinel.ID2,
|
||||
'type': mock.sentinel.vif_type2}
|
||||
mock_network_info = [fake_vif1, fake_vif2]
|
||||
fake_vif_driver = mock.MagicMock()
|
||||
mock_get_vif_driver.return_value = fake_vif_driver
|
||||
calls = [mock.call(mock_instance, fake_vif1),
|
||||
mock.call(mock_instance, fake_vif2)]
|
||||
|
||||
self._vmops.power_on(mock_instance, network_info=mock_network_info)
|
||||
fake_vif_driver.post_start.assert_has_calls(calls)
|
||||
self._vmops.power_on(mock_instance,
|
||||
network_info=mock.sentinel.fake_network_info)
|
||||
mock_post_start_vifs.assert_called_once_with(
|
||||
mock_instance, mock.sentinel.fake_network_info)
|
||||
|
||||
def _test_set_vm_state(self, state):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
|
@ -1252,6 +1249,40 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
def test_configure_remotefx(self):
|
||||
self._test_configure_remotefx()
|
||||
|
||||
@mock.patch.object(vmops.VMOps, '_get_vif_driver')
|
||||
def test_unplug_vifs(self, mock_get_vif_driver):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
fake_vif1 = {'id': mock.sentinel.ID1,
|
||||
'type': mock.sentinel.vif_type1}
|
||||
fake_vif2 = {'id': mock.sentinel.ID2,
|
||||
'type': mock.sentinel.vif_type2}
|
||||
mock_network_info = [fake_vif1, fake_vif2]
|
||||
fake_vif_driver = mock.MagicMock()
|
||||
mock_get_vif_driver.return_value = fake_vif_driver
|
||||
calls = [mock.call(mock_instance, fake_vif1),
|
||||
mock.call(mock_instance, fake_vif2)]
|
||||
|
||||
self._vmops.unplug_vifs(mock_instance,
|
||||
network_info=mock_network_info)
|
||||
fake_vif_driver.unplug.assert_has_calls(calls)
|
||||
|
||||
@mock.patch.object(vmops.VMOps, '_get_vif_driver')
|
||||
def test_post_start_vifs(self, mock_get_vif_driver):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
fake_vif1 = {'id': mock.sentinel.ID1,
|
||||
'type': mock.sentinel.vif_type1}
|
||||
fake_vif2 = {'id': mock.sentinel.ID2,
|
||||
'type': mock.sentinel.vif_type2}
|
||||
mock_network_info = [fake_vif1, fake_vif2]
|
||||
fake_vif_driver = mock.MagicMock()
|
||||
mock_get_vif_driver.return_value = fake_vif_driver
|
||||
calls = [mock.call(mock_instance, fake_vif1),
|
||||
mock.call(mock_instance, fake_vif2)]
|
||||
|
||||
self._vmops.post_start_vifs(mock_instance,
|
||||
network_info=mock_network_info)
|
||||
fake_vif_driver.post_start.assert_has_calls(calls)
|
||||
|
||||
@mock.patch.object(vmops.VMOps, '_get_vm_state')
|
||||
def _test_check_hotplug_is_available(self, mock_get_vm_state, vm_gen,
|
||||
windows_version, vm_state):
|
||||
|
|
Loading…
Reference in New Issue