Merge "Remove dest node allocations during live migration rollback"
This commit is contained in:
commit
ef76319541
|
@ -5963,6 +5963,19 @@ class ComputeManager(manager.Manager):
|
|||
Contains the status we want to set for the migration object
|
||||
|
||||
"""
|
||||
# Remove allocations created in Placement for the dest node.
|
||||
# NOTE(mriedem): The migrate_data.migration object does not have the
|
||||
# dest_node (or dest UUID) set, so we have to lookup the destination
|
||||
# ComputeNode with only the hostname.
|
||||
dest_node = objects.ComputeNode.get_first_node_by_host_for_old_compat(
|
||||
context, dest, use_slave=True)
|
||||
reportclient = self.scheduler_client.reportclient
|
||||
resources = scheduler_utils.resources_from_flavor(
|
||||
instance, instance.flavor)
|
||||
reportclient.remove_provider_from_instance_allocation(
|
||||
instance.uuid, dest_node.uuid, instance.user_id,
|
||||
instance.project_id, resources)
|
||||
|
||||
instance.task_state = None
|
||||
instance.progress = 0
|
||||
instance.save(expected_task_state=[task_states.MIGRATING])
|
||||
|
|
|
@ -2269,23 +2269,12 @@ class ServerMovingTests(ProviderUsageBaseTestCase):
|
|||
dest_usages = self._get_provider_usages(dest_rp_uuid)
|
||||
# Assert the allocations, created by the scheduler, are cleaned up
|
||||
# after the rollback happens.
|
||||
# FIXME: This is bug 1715182 where rollback doesn't remove the
|
||||
# allocations against the dest node. Uncomment once fixed.
|
||||
self.assertFlavorMatchesAllocation(self.flavor1, dest_usages)
|
||||
# self.assertFlavorMatchesAllocation(
|
||||
# {'vcpus': 0, 'ram': 0, 'disk': 0}, dest_usages)
|
||||
self.assertFlavorMatchesAllocation(
|
||||
{'vcpus': 0, 'ram': 0, 'disk': 0}, dest_usages)
|
||||
|
||||
allocations = self._get_allocations_by_server_uuid(server['id'])
|
||||
# There should only be 1 allocation for the instance on the source node
|
||||
# FIXME: This is bug 1715182 where rollback doesn't remove the
|
||||
# allocations against the dest node. Uncomment once fixed.
|
||||
# self.assertEqual(1, len(allocations))
|
||||
self.assertEqual(2, len(allocations))
|
||||
|
||||
self.assertIn(dest_rp_uuid, allocations)
|
||||
self.assertFlavorMatchesAllocation(
|
||||
self.flavor1, allocations[dest_rp_uuid]['resources'])
|
||||
|
||||
self.assertEqual(1, len(allocations))
|
||||
self.assertIn(source_rp_uuid, allocations)
|
||||
self.assertFlavorMatchesAllocation(
|
||||
self.flavor1, allocations[source_rp_uuid]['resources'])
|
||||
|
@ -2477,14 +2466,8 @@ class ServerMovingTests(ProviderUsageBaseTestCase):
|
|||
self._run_periodics()
|
||||
|
||||
allocations = self._get_allocations_by_server_uuid(server['id'])
|
||||
# Note(lajos katona): After solving bug #1714237 there should be
|
||||
# only 1 allocation:
|
||||
# self.assertEqual(1, len(allocations))
|
||||
self.assertEqual(2, len(allocations))
|
||||
|
||||
# Note(lajos katona): After solving bug #1714237 the destination
|
||||
# resource provider should not be among the allocations:
|
||||
# self.assertNotIn(dest_rp_uuid, allocations)
|
||||
self.assertEqual(1, len(allocations))
|
||||
self.assertNotIn(dest_rp_uuid, allocations)
|
||||
|
||||
source_usages = self._get_provider_usages(source_rp_uuid)
|
||||
self.assertFlavorMatchesAllocation(self.flavor1, source_usages)
|
||||
|
@ -2493,18 +2476,8 @@ class ServerMovingTests(ProviderUsageBaseTestCase):
|
|||
self.assertFlavorMatchesAllocation(self.flavor1, source_allocation)
|
||||
|
||||
dest_usages = self._get_provider_usages(dest_rp_uuid)
|
||||
# Note(lajos katona): After solving bug #1714237 on the destination
|
||||
# there should be zero usage:
|
||||
# self.assertFlavorMatchesAllocation(
|
||||
# {'ram': 0, 'disk': 0, 'vcpus': 0}, dest_usages)
|
||||
self.assertFlavorMatchesAllocation(self.flavor1, dest_usages)
|
||||
|
||||
dest_allocation = allocations[dest_rp_uuid]['resources']
|
||||
# Note(lajos katona): After solving bug #1714237 on the destination
|
||||
# there should be zero allocation:
|
||||
# self.assertFlavorMatchesAllocation(
|
||||
# {'ram': 0, 'disk': 0, 'vcpus': 0}, dest_allocation)
|
||||
self.assertFlavorMatchesAllocation(self.flavor1, dest_allocation)
|
||||
self.assertFlavorMatchesAllocation(
|
||||
{'ram': 0, 'disk': 0, 'vcpus': 0}, dest_usages)
|
||||
|
||||
self._delete_and_check_allocations(
|
||||
server, source_rp_uuid, dest_rp_uuid)
|
||||
|
|
|
@ -5867,6 +5867,10 @@ class ComputeTestCase(BaseTestCase,
|
|||
|
||||
@mock.patch.object(fake.FakeDriver, 'get_instance_disk_info')
|
||||
@mock.patch.object(compute_rpcapi.ComputeAPI, 'pre_live_migration')
|
||||
@mock.patch.object(objects.ComputeNode,
|
||||
'get_first_node_by_host_for_old_compat')
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'remove_provider_from_instance_allocation')
|
||||
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
|
||||
@mock.patch.object(compute_rpcapi.ComputeAPI, 'remove_volume_connection')
|
||||
@mock.patch.object(compute_rpcapi.ComputeAPI,
|
||||
|
@ -5874,7 +5878,8 @@ class ComputeTestCase(BaseTestCase,
|
|||
@mock.patch('nova.objects.Migration.save')
|
||||
def test_live_migration_exception_rolls_back(self, mock_save,
|
||||
mock_rollback, mock_remove,
|
||||
mock_get_uuid, mock_pre, mock_get_disk):
|
||||
mock_get_uuid, mock_remove_allocs,
|
||||
mock_get_node, mock_pre, mock_get_disk):
|
||||
# Confirm exception when pre_live_migration fails.
|
||||
c = context.get_admin_context()
|
||||
|
||||
|
@ -5884,7 +5889,9 @@ class ComputeTestCase(BaseTestCase,
|
|||
updated_instance = self._create_fake_instance_obj(
|
||||
{'host': 'fake-dest-host'})
|
||||
dest_host = updated_instance['host']
|
||||
fake_bdms = [
|
||||
dest_node = objects.ComputeNode(host=dest_host, uuid=uuids.dest_node)
|
||||
mock_get_node.return_value = dest_node
|
||||
fake_bdms = objects.BlockDeviceMappingList(objects=[
|
||||
objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'volume_id': uuids.volume_id_1,
|
||||
|
@ -5895,7 +5902,7 @@ class ComputeTestCase(BaseTestCase,
|
|||
{'volume_id': uuids.volume_id_2,
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume'}))
|
||||
]
|
||||
])
|
||||
migrate_data = migrate_data_obj.XenapiLiveMigrateData(
|
||||
block_migration=True)
|
||||
|
||||
|
@ -5925,6 +5932,9 @@ class ComputeTestCase(BaseTestCase,
|
|||
block_device_info=block_device_info)
|
||||
mock_pre.assert_called_once_with(c,
|
||||
instance, True, 'fake_disk', dest_host, migrate_data)
|
||||
mock_remove_allocs.assert_called_once_with(
|
||||
instance.uuid, dest_node.uuid, instance.user_id,
|
||||
instance.project_id, test.MatchType(dict))
|
||||
mock_setup.assert_called_once_with(c, instance, self.compute.host)
|
||||
mock_get_uuid.assert_called_with(c, instance.uuid)
|
||||
mock_remove.assert_has_calls([
|
||||
|
@ -6259,14 +6269,21 @@ class ComputeTestCase(BaseTestCase,
|
|||
terminate_connection.assert_called_once_with(
|
||||
c, uuids.volume_id, 'fake-connector')
|
||||
|
||||
@mock.patch.object(objects.ComputeNode,
|
||||
'get_first_node_by_host_for_old_compat')
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'remove_provider_from_instance_allocation')
|
||||
@mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid')
|
||||
def test_rollback_live_migration(self, mock_bdms):
|
||||
def test_rollback_live_migration(self, mock_bdms, mock_remove_allocs,
|
||||
mock_get_node):
|
||||
c = context.get_admin_context()
|
||||
instance = mock.MagicMock()
|
||||
migration = mock.MagicMock()
|
||||
migrate_data = {'migration': migration}
|
||||
|
||||
mock_bdms.return_value = []
|
||||
dest_node = objects.ComputeNode(host='foo', uuid=uuids.dest_node)
|
||||
mock_get_node.return_value = dest_node
|
||||
mock_bdms.return_value = objects.BlockDeviceMappingList()
|
||||
|
||||
@mock.patch('nova.compute.utils.notify_about_instance_action')
|
||||
@mock.patch.object(self.compute, '_live_migration_cleanup_flags')
|
||||
|
@ -6275,6 +6292,9 @@ class ComputeTestCase(BaseTestCase,
|
|||
mock_lmcf.return_value = False, False
|
||||
self.compute._rollback_live_migration(c, instance, 'foo',
|
||||
migrate_data=migrate_data)
|
||||
mock_remove_allocs.assert_called_once_with(
|
||||
instance.uuid, dest_node.uuid, instance.user_id,
|
||||
instance.project_id, test.MatchType(dict))
|
||||
mock_notify.assert_has_calls([
|
||||
mock.call(c, instance, self.compute.host,
|
||||
action='live_migration_rollback', phase='start'),
|
||||
|
@ -6288,14 +6308,22 @@ class ComputeTestCase(BaseTestCase,
|
|||
self.assertEqual(0, instance.progress)
|
||||
migration.save.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(objects.ComputeNode,
|
||||
'get_first_node_by_host_for_old_compat')
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'remove_provider_from_instance_allocation')
|
||||
@mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid')
|
||||
def test_rollback_live_migration_set_migration_status(self, mock_bdms):
|
||||
def test_rollback_live_migration_set_migration_status(self, mock_bdms,
|
||||
mock_remove_allocs,
|
||||
mock_get_node):
|
||||
c = context.get_admin_context()
|
||||
instance = mock.MagicMock()
|
||||
migration = mock.MagicMock()
|
||||
migrate_data = {'migration': migration}
|
||||
|
||||
mock_bdms.return_value = []
|
||||
dest_node = objects.ComputeNode(host='foo', uuid=uuids.dest_node)
|
||||
mock_get_node.return_value = dest_node
|
||||
mock_bdms.return_value = objects.BlockDeviceMappingList()
|
||||
|
||||
@mock.patch('nova.compute.utils.notify_about_instance_action')
|
||||
@mock.patch.object(self.compute, '_live_migration_cleanup_flags')
|
||||
|
@ -6305,6 +6333,9 @@ class ComputeTestCase(BaseTestCase,
|
|||
self.compute._rollback_live_migration(c, instance, 'foo',
|
||||
migrate_data=migrate_data,
|
||||
migration_status='fake')
|
||||
mock_remove_allocs.assert_called_once_with(
|
||||
instance.uuid, dest_node.uuid, instance.user_id,
|
||||
instance.project_id, test.MatchType(dict))
|
||||
mock_notify.assert_has_calls([
|
||||
mock.call(c, instance, self.compute.host,
|
||||
action='live_migration_rollback', phase='start'),
|
||||
|
|
|
@ -6071,8 +6071,15 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase):
|
|||
|
||||
_test()
|
||||
|
||||
def test_rollback_live_migration_handles_dict(self):
|
||||
@mock.patch.object(objects.ComputeNode,
|
||||
'get_first_node_by_host_for_old_compat')
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'remove_provider_from_instance_allocation')
|
||||
def test_rollback_live_migration_handles_dict(self, mock_remove_allocs,
|
||||
mock_get_node):
|
||||
compute = manager.ComputeManager()
|
||||
dest_node = objects.ComputeNode(host='foo', uuid=uuids.dest_node)
|
||||
mock_get_node.return_value = dest_node
|
||||
|
||||
@mock.patch('nova.compute.utils.notify_about_instance_action')
|
||||
@mock.patch.object(compute.network_api, 'setup_networks_on_host')
|
||||
|
@ -6081,12 +6088,15 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase):
|
|||
@mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid')
|
||||
def _test(mock_bdm, mock_lmcf, mock_notify, mock_nwapi,
|
||||
mock_notify_about_instance_action):
|
||||
mock_bdm.return_value = []
|
||||
mock_bdm.return_value = objects.BlockDeviceMappingList()
|
||||
mock_lmcf.return_value = False, False
|
||||
mock_instance = mock.MagicMock()
|
||||
compute._rollback_live_migration(self.context,
|
||||
mock_instance,
|
||||
'foo', {})
|
||||
mock_remove_allocs.assert_called_once_with(
|
||||
mock_instance.uuid, dest_node.uuid, mock_instance.user_id,
|
||||
mock_instance.project_id, test.MatchType(dict))
|
||||
mock_notify_about_instance_action.assert_has_calls([
|
||||
mock.call(self.context, mock_instance, compute.host,
|
||||
action='live_migration_rollback', phase='start'),
|
||||
|
|
Loading…
Reference in New Issue