From a692e7750f9aa6394c1ab9df5e22ecb908e7eb29 Mon Sep 17 00:00:00 2001 From: Mathew Odden Date: Fri, 31 Aug 2012 23:51:12 -0500 Subject: Allow hard reboot of a soft rebooting instance Allow hard reboot API calls to succeed if the task status is soft reboot, but not hard reboot. This was discussed in the previous change for this bug in Iae95b121c5c623e1eaa6fba52b13170413722d2d Fixes bug #944015 Change-Id: I0f78faad524774dbbcad0bf2adafed3802dfeb75 --- nova/compute/api.py | 11 +++++++++-- nova/tests/compute/test_compute.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'nova') diff --git a/nova/compute/api.py b/nova/compute/api.py index fa413fdb1..ffc034063 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1238,14 +1238,21 @@ class API(base.Base): @check_instance_lock @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED, vm_states.RESCUED], - task_state=[None]) + task_state=[None, task_states.REBOOTING]) def reboot(self, context, instance, reboot_type): """Reboot the given instance.""" + if (reboot_type == 'SOFT' and + instance['task_state'] == task_states.REBOOTING): + raise exception.InstanceInvalidState( + attr='task_state', + instance_uuid=instance['uuid'], + state=instance['task_state']) state = {'SOFT': task_states.REBOOTING, 'HARD': task_states.REBOOTING_HARD}[reboot_type] instance = self.update(context, instance, vm_state=vm_states.ACTIVE, task_state=state, - expected_task_state=None) + expected_task_state=[None, + task_states.REBOOTING]) self.compute_rpcapi.reboot_instance(context, instance=instance, reboot_type=reboot_type) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 13fa4b644..7142f92a9 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -3074,6 +3074,42 @@ class ComputeAPITestCase(BaseTestCase): db.instance_destroy(self.context, inst_ref['uuid']) + def test_hard_reboot_of_soft_rebooting_instance(self): + """Ensure instance can be hard rebooted while soft rebooting""" + instance = jsonutils.to_primitive(self._create_fake_instance()) + self.compute.run_instance(self.context, instance=instance) + + inst_ref = db.instance_get_by_uuid(self.context, instance['uuid']) + + db.instance_update(self.context, instance['uuid'], + {"task_state": task_states.REBOOTING}) + + reboot_type = "HARD" + self.compute_api.reboot(self.context, inst_ref, reboot_type) + + inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid']) + self.assertEqual(inst_ref['task_state'], task_states.REBOOTING_HARD) + + db.instance_destroy(self.context, inst_ref['uuid']) + + def test_soft_reboot_of_rebooting_instance(self): + """Ensure instance can't be soft rebooted while rebooting""" + instance = jsonutils.to_primitive(self._create_fake_instance()) + self.compute.run_instance(self.context, instance=instance) + + inst_ref = db.instance_get_by_uuid(self.context, instance['uuid']) + + db.instance_update(self.context, instance['uuid'], + {"task_state": task_states.REBOOTING}) + + inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid']) + reboot_type = "SOFT" + self.assertRaises(exception.InstanceInvalidState, + self.compute_api.reboot, + self.context, + inst_ref, + reboot_type) + def test_hostname_create(self): """Ensure instance hostname is set during creation.""" inst_type = instance_types.get_instance_type_by_name('m1.tiny') -- cgit