Unbreak start instance and fixes bug 905270
This patch fixes the bug 905270 https://bugs.launchpad.net/nova/+bug/905270 According to EC2 documentation, EBS-instances that initiated shutdown result in stopped state. And then it can be started again. (On the other hand non-EBS instance result in terminted when instance initiated shutdown) However, the current nova case, the shutdowned instance always results in terminated status. As related issues are - describe-instance-attribute instance_initiated_shutdown_behavior doesn't work correctly - instance attribute disable_api_termination isn't supported - stop instance was broken by the change set of the following. It needs unbreak. > commit eb03d47fecd3bfc24243da29ee01679b334a08fe > Author: Vishvananda Ishaya <vishvananda@gmail.com> > Date: Fri Sep 23 09:22:32 2011 -0700 > > Remove AoE, Clean up volume code > > * Removes Ata Over Ethernet > * Adds drivers to libvirt for volumes > * Adds initialize_connection and terminate_connection to volume api > * Passes connection info back through volume api > > Change-Id: I1b1626f40bebe8466ab410fb174683293c7c474f This patch - unbreak start instance - implement instance_initiated_shutdown_behavior and make it EC2 compatible - implement disable_api_termination --- Changes 5 -> 6: - fixes to catch up 26b7b9457a5899ecca93fd67d3879efcad4e4968 Changes 4 -> 5: - HACKING compilance Changes 3 -> 4: - rebased to 4c5586a28fd7a085369c49f6039876ffdc86b526 sqlalchemy migrate version Changes 2 -> 3: - rename long name to shorter one s/instance_initiated_shutdown_behavior/shutdown_terminate/g s/disable_api_termination/disable_terminate/g as suggested Kevin L. Mitchell - improved nova.api.ec2.cloud._state_description - pep8 - broken out patches are available for easy review at git://github.com/yamahata/nova.git lp905270-2 Changes 1 -> 2: - fixed an unit test failure pointed out by Mark. (I think ebtabls failure strongly suggests installation problem) - introduce vm_states.SHUTOFF and put instance state which is in power_state.{NOSTATE, SHUTOFF} into vm_states.SHUTOFF. - simplified logic a bit by vm_states.SHUTOFF as suggested by Vish. - instance_initiated_shutdown_behavior:String(255) => instance_initiated_shutdown_terminate:Boolean() as suggested by Vish. - Added Johannes Erdfelt to reviews as they written the vm_states state machine checker. I'd have liked to add David Subiros either, but he doesn't seem to be a registered user of the gerrit. Change-Id: Ibeb94f65137feadad2c343913b39195e3f96a35e
This commit is contained in:
@@ -1358,6 +1358,15 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
'properties': {'kernel_id': 1, 'ramdisk_id': 1},
|
'properties': {'kernel_id': 1, 'ramdisk_id': 1},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _run_instance(self):
|
||||||
|
instance = self._create_fake_instance()
|
||||||
|
instance_uuid = instance['uuid']
|
||||||
|
self.compute.run_instance(self.context, instance_uuid)
|
||||||
|
|
||||||
|
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||||
|
self.assertEqual(instance['task_state'], None)
|
||||||
|
return instance, instance_uuid
|
||||||
|
|
||||||
def test_create_with_too_little_ram(self):
|
def test_create_with_too_little_ram(self):
|
||||||
"""Test an instance type with too little memory"""
|
"""Test an instance type with too little memory"""
|
||||||
|
|
||||||
@@ -1554,13 +1563,45 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
|
|
||||||
db.instance_destroy(self.context, instance['id'])
|
db.instance_destroy(self.context, instance['id'])
|
||||||
|
|
||||||
def test_delete(self):
|
def test_start_shutdown(self):
|
||||||
|
def check_state(instance_uuid, power_state_, vm_state_, task_state_):
|
||||||
|
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||||
|
self.assertEqual(instance['power_state'], power_state_)
|
||||||
|
self.assertEqual(instance['vm_state'], vm_state_)
|
||||||
|
self.assertEqual(instance['task_state'], task_state_)
|
||||||
|
|
||||||
|
def start_check_state(instance_uuid,
|
||||||
|
power_state_, vm_state_, task_state_):
|
||||||
|
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||||
|
self.compute_api.start(self.context, instance)
|
||||||
|
check_state(instance_uuid, power_state_, vm_state_, task_state_)
|
||||||
|
|
||||||
instance = self._create_fake_instance()
|
instance = self._create_fake_instance()
|
||||||
instance_uuid = instance['uuid']
|
instance_uuid = instance['uuid']
|
||||||
self.compute.run_instance(self.context, instance_uuid)
|
self.compute.run_instance(self.context, instance_uuid)
|
||||||
|
|
||||||
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
check_state(instance_uuid, power_state.RUNNING, vm_states.ACTIVE, None)
|
||||||
self.assertEqual(instance['task_state'], None)
|
|
||||||
|
# NOTE(yamahata): emulate compute.manager._sync_power_state() that
|
||||||
|
# the instance is shutdown by itself
|
||||||
|
db.instance_update(self.context, instance_uuid,
|
||||||
|
{'power_state': power_state.NOSTATE,
|
||||||
|
'vm_state': vm_states.SHUTOFF})
|
||||||
|
check_state(instance_uuid, power_state.NOSTATE, vm_states.SHUTOFF,
|
||||||
|
None)
|
||||||
|
|
||||||
|
start_check_state(instance_uuid,
|
||||||
|
power_state.NOSTATE, vm_states.SHUTOFF, None)
|
||||||
|
|
||||||
|
db.instance_update(self.context, instance_uuid,
|
||||||
|
{'shutdown_terminate': False})
|
||||||
|
start_check_state(instance_uuid, power_state.NOSTATE,
|
||||||
|
vm_states.STOPPED, task_states.STARTING)
|
||||||
|
|
||||||
|
db.instance_destroy(self.context, instance['id'])
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
instance, instance_uuid = self._run_instance()
|
||||||
|
|
||||||
self.compute_api.delete(self.context, instance)
|
self.compute_api.delete(self.context, instance)
|
||||||
|
|
||||||
@@ -1569,14 +1610,21 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
|
|
||||||
db.instance_destroy(self.context, instance['id'])
|
db.instance_destroy(self.context, instance['id'])
|
||||||
|
|
||||||
def test_delete_soft(self):
|
def test_delete_fail(self):
|
||||||
instance = self._create_fake_instance()
|
instance, instance_uuid = self._run_instance()
|
||||||
instance_uuid = instance['uuid']
|
|
||||||
self.compute.run_instance(self.context, instance['uuid'])
|
instance = db.instance_update(self.context, instance_uuid,
|
||||||
|
{'disable_terminate': True})
|
||||||
|
self.compute_api.delete(self.context, instance)
|
||||||
|
|
||||||
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||||
self.assertEqual(instance['task_state'], None)
|
self.assertEqual(instance['task_state'], None)
|
||||||
|
|
||||||
|
db.instance_destroy(self.context, instance['id'])
|
||||||
|
|
||||||
|
def test_delete_soft(self):
|
||||||
|
instance, instance_uuid = self._run_instance()
|
||||||
|
|
||||||
self.compute_api.soft_delete(self.context, instance)
|
self.compute_api.soft_delete(self.context, instance)
|
||||||
|
|
||||||
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||||
@@ -1584,6 +1632,18 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
|
|
||||||
db.instance_destroy(self.context, instance['id'])
|
db.instance_destroy(self.context, instance['id'])
|
||||||
|
|
||||||
|
def test_delete_soft_fail(self):
|
||||||
|
instance, instance_uuid = self._run_instance()
|
||||||
|
|
||||||
|
instance = db.instance_update(self.context, instance_uuid,
|
||||||
|
{'disable_terminate': True})
|
||||||
|
self.compute_api.soft_delete(self.context, instance)
|
||||||
|
|
||||||
|
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||||
|
self.assertEqual(instance['task_state'], None)
|
||||||
|
|
||||||
|
db.instance_destroy(self.context, instance['id'])
|
||||||
|
|
||||||
def test_force_delete(self):
|
def test_force_delete(self):
|
||||||
"""Ensure instance can be deleted after a soft delete"""
|
"""Ensure instance can be deleted after a soft delete"""
|
||||||
instance = self._create_fake_instance()
|
instance = self._create_fake_instance()
|
||||||
@@ -1621,7 +1681,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
instance = self._create_fake_instance()
|
instance = self._create_fake_instance()
|
||||||
instance_uuid = instance['uuid']
|
instance_uuid = instance['uuid']
|
||||||
instance_id = instance['id']
|
instance_id = instance['id']
|
||||||
self.compute.run_instance(self.context, instance_uuid )
|
self.compute.run_instance(self.context, instance_uuid)
|
||||||
db.instance_update(self.context, instance_id,
|
db.instance_update(self.context, instance_id,
|
||||||
{'vm_state': vm_states.SUSPENDED})
|
{'vm_state': vm_states.SUSPENDED})
|
||||||
instance = db.instance_get(self.context, instance_id)
|
instance = db.instance_get(self.context, instance_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user