Skip to content

Commit

Permalink
Converting delete to use instance objects
Browse files Browse the repository at this point in the history
Related to blueprint internal-uuids

Change-Id: I8875d9785dd0d8f55120673c758edb4c011a4657
  • Loading branch information
ameade committed Nov 10, 2011
1 parent 871e680 commit 1a5418b
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 23 deletions.
5 changes: 4 additions & 1 deletion nova/api/ec2/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -1452,7 +1452,10 @@ def terminate_instances(self, context, instance_id, **kwargs):
"""Terminate each instance in instance_id, which is a list of ec2 ids.
instance_id is a kwarg so its name cannot be modified."""
LOG.debug(_("Going to start terminating instances"))
self._do_instances(self.compute_api.delete, context, instance_id)
for ec2_id in instance_id:
_instance_id = ec2utils.ec2_id_to_id(ec2_id)
instance = self.compute_api.get(context, _instance_id)
self.compute_api.delete(context, instance)
return True

def reboot_instances(self, context, instance_id, **kwargs):
Expand Down
3 changes: 2 additions & 1 deletion nova/api/openstack/contrib/deferred_delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def _force_delete(self, input_dict, req, instance_id):
"""Force delete of instance before deferred cleanup."""

context = req.environ["nova.context"]
self.compute_api.force_delete(context, instance_id)
instance = self.compute_api.get(context, instance_id)
self.compute_api.force_delete(context, instance)
return webob.Response(status_int=202)

def get_actions(self):
Expand Down
5 changes: 3 additions & 2 deletions nova/api/openstack/servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,10 +453,11 @@ def create(self, req, body):
return server

def _delete(self, context, id):
instance = self._get_server(context, id)
if FLAGS.reclaim_instance_interval:
self.compute_api.soft_delete(context, id)
self.compute_api.soft_delete(context, instance)
else:
self.compute_api.delete(context, id)
self.compute_api.delete(context, instance)

@scheduler_api.redirect_handler
def update(self, req, id, body):
Expand Down
37 changes: 18 additions & 19 deletions nova/compute/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ def generate_default_display_name(instance):
return 'Server %s' % instance['id']


def _is_able_to_shutdown(instance, instance_id):
def _is_able_to_shutdown(instance):
vm_state = instance["vm_state"]
instance_id = instance["id"]

valid_shutdown_states = [
vm_states.ACTIVE,
Expand All @@ -97,9 +98,10 @@ def _is_able_to_shutdown(instance, instance_id):
return True


def _is_queued_delete(instance, instance_id):
def _is_queued_delete(instance):
vm_state = instance["vm_state"]
task_state = instance["task_state"]
instance_id = instance["id"]

if vm_state != vm_states.SOFT_DELETE:
LOG.warn(_("Instance %(instance_id)s is not in a 'soft delete' "
Expand Down Expand Up @@ -793,12 +795,11 @@ def _get_instance(self, context, instance_id, action_str):
raise

@scheduler_api.reroute_compute("soft_delete")
def soft_delete(self, context, instance_id):
def soft_delete(self, context, instance):
"""Terminate an instance."""
LOG.debug(_("Going to try to soft delete %s"), instance_id)
instance = self._get_instance(context, instance_id, 'soft delete')
LOG.debug(_("Going to try to soft delete %s"), instance["id"])

if not _is_able_to_shutdown(instance, instance_id):
if not _is_able_to_shutdown(instance):
return

# NOTE(jerdfelt): The compute daemon handles reclaiming instances
Expand All @@ -807,17 +808,17 @@ def soft_delete(self, context, instance_id):
host = instance['host']
if host:
self.update(context,
instance_id,
instance["id"],
vm_state=vm_states.SOFT_DELETE,
task_state=task_states.POWERING_OFF,
deleted_at=utils.utcnow())

self._cast_compute_message('power_off_instance', context,
instance_id, host)
instance['id'], host)
else:
LOG.warning(_("No host for instance %s, deleting immediately"),
instance_id)
self.db.instance_destroy(context, instance_id)
instance["id"])
self.db.instance_destroy(context, instance["id"])

def _delete(self, context, instance):
host = instance['host']
Expand All @@ -833,12 +834,11 @@ def _delete(self, context, instance):
self.db.instance_destroy(context, instance['id'])

@scheduler_api.reroute_compute("delete")
def delete(self, context, instance_id):
def delete(self, context, instance):
"""Terminate an instance."""
LOG.debug(_("Going to try to terminate %s"), instance_id)
instance = self._get_instance(context, instance_id, 'delete')
LOG.debug(_("Going to try to terminate %s"), instance["id"])

if not _is_able_to_shutdown(instance, instance_id):
if not _is_able_to_shutdown(instance):
return

self._delete(context, instance)
Expand All @@ -848,7 +848,7 @@ def restore(self, context, instance_id):
"""Restore a previously deleted (but not reclaimed) instance."""
instance = self._get_instance(context, instance_id, 'restore')

if not _is_queued_delete(instance, instance_id):
if not _is_queued_delete(instance):
return

self.update(context,
Expand All @@ -866,11 +866,10 @@ def restore(self, context, instance_id):
instance_id, host)

@scheduler_api.reroute_compute("force_delete")
def force_delete(self, context, instance_id):
def force_delete(self, context, instance):
"""Force delete a previously deleted (but not reclaimed) instance."""
instance = self._get_instance(context, instance_id, 'force delete')

if not _is_queued_delete(instance, instance_id):
if not _is_queued_delete(instance):
return

self._delete(context, instance)
Expand All @@ -881,7 +880,7 @@ def stop(self, context, instance_id):
LOG.debug(_("Going to try to stop %s"), instance_id)

instance = self._get_instance(context, instance_id, 'stopping')
if not _is_able_to_shutdown(instance, instance_id):
if not _is_able_to_shutdown(instance):
return

self.update(context,
Expand Down
12 changes: 12 additions & 0 deletions nova/tests/api/ec2/test_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,18 @@ def test_stop_start_instance(self):
result = self.cloud.terminate_instances(self.context, [instance_id])
self.assertTrue(result)

def test_terminate_instances(self):
kwargs = {'image_id': 'ami-1',
'instance_type': FLAGS.default_instance_type,
'max_count': 1, }
instance_id = self._run_instance(**kwargs)

# a running instance can't be started. It is just ignored.
result = self.cloud.start_instances(self.context, [instance_id])
self.assertTrue(result)

result = self.cloud.terminate_instances(self.context, [instance_id])
self.assertTrue(result)
self._restart_compute_service()

def test_reboot_instances(self):
Expand Down
46 changes: 46 additions & 0 deletions nova/tests/test_compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,52 @@ def test_destroy_security_group_disassociates_instances(self):
finally:
db.instance_destroy(self.context, ref[0]['id'])

def test_delete(self):
instance_id = self._create_instance()
self.compute.run_instance(self.context, instance_id)

instance = db.instance_get(self.context, instance_id)
self.assertEqual(instance['task_state'], None)

self.compute_api.delete(self.context, instance)

instance = db.instance_get(self.context, instance_id)
self.assertEqual(instance['task_state'], task_states.DELETING)

db.instance_destroy(self.context, instance_id)

def test_delete_soft(self):
instance_id = self._create_instance()
self.compute.run_instance(self.context, instance_id)

instance = db.instance_get(self.context, instance_id)
self.assertEqual(instance['task_state'], None)

self.compute_api.soft_delete(self.context, instance)

instance = db.instance_get(self.context, instance_id)
self.assertEqual(instance['task_state'], task_states.POWERING_OFF)

db.instance_destroy(self.context, instance_id)

def test_force_delete(self):
"""Ensure instance can be soft rebooted"""
instance_id = self._create_instance()
self.compute.run_instance(self.context, instance_id)

instance = db.instance_get(self.context, instance_id)
self.compute_api.soft_delete(self.context, instance)

instance = db.instance_get(self.context, instance_id)
self.assertEqual(instance['task_state'], task_states.POWERING_OFF)

self.compute_api.force_delete(self.context, instance)

instance = db.instance_get(self.context, instance_id)
self.assertEqual(instance['task_state'], task_states.DELETING)

db.instance_destroy(self.context, instance_id)

def test_rebuild(self):
instance_id = self._create_instance()
self.compute.run_instance(self.context, instance_id)
Expand Down

0 comments on commit 1a5418b

Please sign in to comment.