summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathew Odden <mrodden@us.ibm.com>2012-08-31 23:51:12 -0500
committerMathew Odden <mrodden@us.ibm.com>2012-09-01 14:25:30 -0500
commita692e7750f9aa6394c1ab9df5e22ecb908e7eb29 (patch)
treeb96f8cf90ffca81d170dd6a948481ec6519a772e
parent0318efe625682ee8703b91f363a966200503782f (diff)
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
-rw-r--r--nova/compute/api.py11
-rw-r--r--nova/tests/compute/test_compute.py36
2 files changed, 45 insertions, 2 deletions
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')