From 9249785be48079bbacc162f2e627a5aee1aa5871 Mon Sep 17 00:00:00 2001 From: Brian Elliott Date: Wed, 27 Feb 2013 05:06:12 +0000 Subject: Suppress retries on UnexpectedTaskStateErrors Don't try to re-schedule if an UnexpectedTaskStateError occurs during a build. If the instance was deleted mid-build, just catch the exception and log a message. Change-Id: I5e577f252ee71f310a749186060808723b676854 --- nova/compute/manager.py | 7 +++++++ nova/tests/compute/test_compute.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 99b97e921..9ca00bd9b 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -780,6 +780,13 @@ class ComputeManager(manager.SchedulerDependentManager): msg = _('Failed to dealloc network for deleted instance') LOG.exception(msg, instance=instance) raise + except exception.UnexpectedTaskStateError as e: + actual_task_state = e.kwargs.get('actual', None) + if actual_task_state == 'deleting': + msg = _('Instance was deleted during spawn.') + LOG.debug(msg, instance=instance) + else: + raise except Exception: exc_info = sys.exc_info() # try to re-schedule instance: diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 5ad333c9e..98eba5570 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -7225,6 +7225,41 @@ class ComputeRescheduleOrReraiseTestCase(BaseTestCase): self.compute._reschedule_or_reraise(self.context, self.instance, exc_info, None, None, None, False, None, {}) + def test_no_reschedule_on_delete_during_spawn(self): + # instance should not be rescheduled if instance is deleted + # during the build + self.mox.StubOutWithMock(self.compute, '_spawn') + self.mox.StubOutWithMock(self.compute, '_reschedule_or_reraise') + + exc = exception.UnexpectedTaskStateError(expected=task_states.SPAWNING, + actual=task_states.DELETING) + self.compute._spawn(mox.IgnoreArg(), self.instance, mox.IgnoreArg(), + mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), + mox.IgnoreArg()).AndRaise(exc) + + self.mox.ReplayAll() + # test succeeds if mocked method '_reschedule_or_reraise' is not + # called. + self.compute._run_instance(self.context, None, {}, None, None, None, + False, None, self.instance) + + def test_no_reschedule_on_unexpected_task_state(self): + # instance shouldn't be rescheduled if unexpected task state arises. + # the exception should get reraised. + self.mox.StubOutWithMock(self.compute, '_spawn') + self.mox.StubOutWithMock(self.compute, '_reschedule_or_reraise') + + exc = exception.UnexpectedTaskStateError(expected=task_states.SPAWNING, + actual=task_states.SCHEDULING) + self.compute._spawn(mox.IgnoreArg(), self.instance, mox.IgnoreArg(), + mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), + mox.IgnoreArg()).AndRaise(exc) + + self.mox.ReplayAll() + self.assertRaises(exception.UnexpectedTaskStateError, + self.compute._run_instance, self.context, None, {}, None, None, + None, False, None, self.instance) + class ComputeRescheduleResizeOrReraiseTestCase(BaseTestCase): """Test logic and exception handling around rescheduling prep resize -- cgit