diff options
author | Matthew Sherborne <msherborne@gmail.com> | 2013-04-20 19:08:07 +1000 |
---|---|---|
committer | Matthew Sherborne <msherborne@gmail.com> | 2013-04-23 22:22:05 +1000 |
commit | 40692574bbdefbdfa4a6f3366bec524fd4612400 (patch) | |
tree | 80e666e59702888e79422e7c7477089c83e63842 /nova | |
parent | bfc3a3ccb2811cc8a96a15987528e6639ec029bf (diff) | |
download | nova-40692574bbdefbdfa4a6f3366bec524fd4612400.tar.gz nova-40692574bbdefbdfa4a6f3366bec524fd4612400.tar.xz nova-40692574bbdefbdfa4a6f3366bec524fd4612400.zip |
If rescue fails don't error the instance
If a rescue attempt fails, the VM's state should return to what it was
before the rescue attempt started, and the user should be notified of
the failure.
Fixes bug: 1170328
Change-Id: If5e97d06a3617adad83a4bba2ac6320616bbe83b
Diffstat (limited to 'nova')
-rwxr-xr-x | nova/compute/manager.py | 9 | ||||
-rw-r--r-- | nova/tests/compute/test_compute.py | 28 |
2 files changed, 35 insertions, 2 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 5da050f60..f1ab1629e 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -2007,7 +2007,6 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @reverts_task_state @wrap_instance_event - @wrap_instance_fault def rescue_instance(self, context, instance, rescue_password=None): """ Rescue an instance on this host. @@ -2028,10 +2027,16 @@ class ComputeManager(manager.SchedulerDependentManager): else: rescue_image_meta = {} - with self._error_out_instance_on_exception(context, instance['uuid']): + try: self.driver.rescue(context, instance, self._legacy_nw_info(network_info), rescue_image_meta, admin_password) + except Exception as e: + LOG.exception(_("Error trying to Rescue Instance"), + instance=instance) + raise exception.InstanceNotRescuable( + instance_id=instance['uuid'], + reason=_("Driver Error: %s") % unicode(e)) current_power_state = self._get_power_state(context, instance) self._instance_update(context, diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 6bf612eee..e3db2cdba 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -22,6 +22,7 @@ import base64 import copy import datetime import sys +import testtools import time import traceback import uuid @@ -1265,6 +1266,33 @@ class ComputeTestCase(BaseTestCase): self.compute.terminate_instance(self.context, instance=instance) + def test_rescue_handle_err(self): + # If the driver fails to rescue, instance state should remain the same + # and the exception should be converted to InstanceNotRescuable + instance = jsonutils.to_primitive(self._create_fake_instance()) + self.mox.StubOutWithMock(self.compute, '_get_rescue_image_ref') + self.mox.StubOutWithMock(nova.virt.fake.FakeDriver, 'rescue') + + self.compute._get_rescue_image_ref( + mox.IgnoreArg(), instance).AndReturn('resc_image_ref') + nova.virt.fake.FakeDriver.rescue( + mox.IgnoreArg(), instance, [], mox.IgnoreArg(), 'password' + ).AndRaise(RuntimeError("Try again later")) + + self.mox.ReplayAll() + + expected_message = ('Instance %s cannot be rescued: ' + 'Driver Error: Try again later' % instance['uuid']) + instance['vm_state'] = 'some_random_state' + + with testtools.ExpectedException( + exception.InstanceNotRescuable, expected_message): + self.compute.rescue_instance( + self.context, instance=instance, + rescue_password='password') + + self.assertEqual('some_random_state', instance['vm_state']) + def test_power_on(self): # Ensure instance can be powered on. |