diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 883865988e69..6ef7dd9a9963 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -807,6 +807,15 @@ class ComputeTaskManager(base.Base): with compute_utils.EventReporter(context, 'rebuild_server', instance.uuid): node = limits = None + + try: + migration = objects.Migration.get_by_instance_and_status( + context, instance.uuid, 'accepted') + except exception.MigrationNotFoundByStatus: + LOG.debug("No migration record for the rebuild/evacuate " + "request.", instance=instance) + migration = None + # The host variable is passed in two cases: # 1. rebuild - the instance.host is passed to rebuild on the # same host and bypass the scheduler. @@ -857,6 +866,9 @@ class ComputeTaskManager(base.Base): host_dict['nodename'], host_dict['limits']) except exception.NoValidHost as ex: + if migration: + migration.status = 'error' + migration.save() request_spec = request_spec.to_legacy_request_spec_dict() with excutils.save_and_reraise_exception(): self._set_vm_state_and_notify(context, instance.uuid, @@ -866,6 +878,9 @@ class ComputeTaskManager(base.Base): LOG.warning("No valid host found for rebuild", instance=instance) except exception.UnsupportedPolicyException as ex: + if migration: + migration.status = 'error' + migration.save() request_spec = request_spec.to_legacy_request_spec_dict() with excutils.save_and_reraise_exception(): self._set_vm_state_and_notify(context, instance.uuid, @@ -875,14 +890,6 @@ class ComputeTaskManager(base.Base): LOG.warning("Server with unsupported policy " "cannot be rebuilt", instance=instance) - try: - migration = objects.Migration.get_by_instance_and_status( - context, instance.uuid, 'accepted') - except exception.MigrationNotFoundByStatus: - LOG.debug("No migration record for the rebuild/evacuate " - "request.", instance=instance) - migration = None - compute_utils.notify_about_instance_usage( self.notifier, context, instance, "rebuild.scheduled") diff --git a/nova/tests/functional/regressions/test_bug_1713783.py b/nova/tests/functional/regressions/test_bug_1713783.py index 4da5c6086497..4233511aaf67 100644 --- a/nova/tests/functional/regressions/test_bug_1713783.py +++ b/nova/tests/functional/regressions/test_bug_1713783.py @@ -118,7 +118,4 @@ class FailedEvacuateStateTests(test.TestCase, self.assertEqual('evacuation', migrations[0]['migration_type']) self.assertEqual(server['id'], migrations[0]['instance_uuid']) self.assertEqual(self.hostname, migrations[0]['source_compute']) - self.assertEqual('accepted', migrations[0]['status']) - # NOTE(elod.illes): Migration status should be 'error' and not - # 'accepted'. Needs to be replaced when bug #1713783 is fixed. - # self.assertEqual('error', migrations[0]['status']) + self.assertEqual('error', migrations[0]['status']) diff --git a/nova/tests/unit/conductor/test_conductor.py b/nova/tests/unit/conductor/test_conductor.py index 484be3daac61..3cba5342a899 100644 --- a/nova/tests/unit/conductor/test_conductor.py +++ b/nova/tests/unit/conductor/test_conductor.py @@ -1282,6 +1282,15 @@ class _BaseTaskTestCase(object): # build_instances() is a cast, we need to wait for it to complete self.useFixture(cast_as_call.CastAsCall(self)) + # Create the migration record (normally created by the compute API). + migration = objects.Migration(self.context, + source_compute=inst_obj.host, + source_node=inst_obj.node, + instance_uuid=inst_obj.uuid, + status='accepted', + migration_type='evacuation') + migration.create() + self.assertRaises(exc.UnsupportedPolicyException, self.conductor.rebuild_instance, self.context, @@ -1294,6 +1303,10 @@ class _BaseTaskTestCase(object): self.assertFalse(select_dest_mock.called) self.assertFalse(rebuild_mock.called) + # Assert the migration status was updated. + migration = objects.Migration.get_by_id(self.context, migration.id) + self.assertEqual('error', migration.status) + def test_rebuild_instance_evacuate_migration_record(self): inst_obj = self._create_fake_instance_obj() migration = objects.Migration(context=self.context,