diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 5c1bbb49dc15..4ad2d0442f50 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -874,6 +874,25 @@ class ComputeManager(manager.Manager): {'cpus': list(pinned_cpus)}, instance=instance) + def _reset_live_migration(self, context, instance): + migration = None + try: + migration = objects.Migration.get_by_instance_and_status( + context, instance.uuid, 'running') + if migration: + self.live_migration_abort(context, instance, migration.id) + except Exception: + LOG.exception('Failed to abort live-migration', + instance=instance) + finally: + if migration: + self._set_migration_status(migration, 'error') + LOG.info('Instance found in migrating state during ' + 'startup. Resetting task_state', + instance=instance) + instance.task_state = None + instance.save(expected_task_state=[task_states.MIGRATING]) + def _init_instance(self, context, instance): """Initialize this instance during service init.""" @@ -1106,9 +1125,8 @@ class ComputeManager(manager.Manager): instance.save() if instance.task_state == task_states.MIGRATING: # Live migration did not complete, but instance is on this - # host, so reset the state. - instance.task_state = None - instance.save(expected_task_state=[task_states.MIGRATING]) + # host. Abort ongoing migration if still running and reset state. + self._reset_live_migration(context, instance) db_state = instance.power_state drv_state = self._get_power_state(context, instance) diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 9f470e1b718a..2bcdb49d61d0 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -1508,14 +1508,25 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, vm_state=vm_states.ACTIVE, host=self.compute.host, task_state=task_states.MIGRATING) + migration = objects.Migration(source_compute='fake-host1', id=39, + dest_compute='fake-host2') with test.nested( mock.patch.object(instance, 'save'), mock.patch('nova.objects.Instance.get_network_info', - return_value=network_model.NetworkInfo()) - ) as (save, get_nw_info): + return_value=network_model.NetworkInfo()), + mock.patch.object(objects.Migration, 'get_by_instance_and_status', + return_value=migration), + mock.patch.object(self.compute, 'live_migration_abort'), + mock.patch.object(self.compute, '_set_migration_status') + ) as (save, get_nw_info, mock_get_status, mock_abort, mock_set_migr): self.compute._init_instance(self.context, instance) save.assert_called_once_with(expected_task_state=['migrating']) get_nw_info.assert_called_once_with() + mock_get_status.assert_called_with(self.context, instance.uuid, + 'running') + mock_abort.assert_called_with(self.context, instance, + migration.id) + mock_set_migr.assert_called_with(migration, 'error') self.assertIsNone(instance.task_state) self.assertEqual(vm_states.ACTIVE, instance.vm_state)