summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Gordon <jogo@cloudscaling.com>2012-08-31 00:04:33 +0000
committerJoe Gordon <jogo@cloudscaling.com>2012-08-31 02:06:45 +0000
commit77dd6a0b37652bc163d4ad3083e29af55f2b9a5d (patch)
treed315ddb9f5f641cd9931ba66f29d569de011ceca
parent0749ffc3bedc66df7c82af2887c9839d240d0526 (diff)
Allow for deleting VMs from down compute nodes.
Fix bug 872899 If compute node service_is_up returns false, just delete the VM from the database. If compute node recovers, setting running_deleted_instance_action=reap will clean up the node. Change-Id: Ibb5f1e22c2e482d304c59a485a04b882ead0c67d
-rw-r--r--nova/compute/api.py17
-rw-r--r--nova/tests/compute/test_compute.py25
2 files changed, 31 insertions, 11 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index dcc6a7f06..3292d9080 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -855,7 +855,7 @@ class API(base.Base):
cores=-instance['vcpus'],
ram=-instance['memory_mb'])
- if not instance['host']:
+ if not host:
# Just update database, nothing else we can do
constraint = self.db.constraint(host=self.db.equal_any(host))
try:
@@ -894,7 +894,20 @@ class API(base.Base):
host=src_host, cast=False,
reservations=downsize_reservations)
- self.compute_rpcapi.terminate_instance(context, instance)
+ services = self.db.service_get_all_compute_by_host(
+ context.elevated(), instance['host'])
+ is_up = False
+ #Note(jogo): db allows for multiple compute services per host
+ for service in services:
+ if utils.service_is_up(service):
+ is_up = True
+ self.compute_rpcapi.terminate_instance(context, instance)
+ break
+ if is_up == False:
+ # If compute node isn't up, just delete from DB
+ LOG.warning(_('host for instance is down, deleting from '
+ 'database'), instance=instance)
+ self.db.instance_destroy(context, instance['uuid'])
if reservations:
QUOTAS.commit(context, reservations)
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 822c23e03..ffedff1b5 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -148,6 +148,8 @@ class BaseTestCase(test.TestCase):
inst['architecture'] = 'x86_64'
inst['os_type'] = 'Linux'
inst.update(params)
+ _create_service_entries(self.context.elevated(),
+ {'fake_zone': [inst['host']]})
return db.instance_create(self.context, inst)
def _create_instance(self, params=None, type_name='m1.tiny'):
@@ -2403,8 +2405,8 @@ class ComputeAPITestCase(BaseTestCase):
'ramdisk_id': 'fake_ramdisk_id'},
}
- def _run_instance(self):
- instance = jsonutils.to_primitive(self._create_fake_instance())
+ def _run_instance(self, params=None):
+ instance = jsonutils.to_primitive(self._create_fake_instance(params))
instance_uuid = instance['uuid']
self.compute.run_instance(self.context, instance=instance)
@@ -2719,7 +2721,8 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, instance['uuid'])
def test_delete(self):
- instance, instance_uuid = self._run_instance()
+ instance, instance_uuid = self._run_instance(params={
+ 'host': FLAGS.host})
self.compute_api.delete(self.context, instance)
@@ -2742,7 +2745,8 @@ class ComputeAPITestCase(BaseTestCase):
self.stubs.Set(QUOTAS, 'commit', fake_commit)
- instance, instance_uuid = self._run_instance()
+ instance, instance_uuid = self._run_instance(params={
+ 'host': FLAGS.host})
self.compute_api.delete(self.context, instance)
self.compute_api.delete(self.context, instance)
@@ -2761,7 +2765,8 @@ class ComputeAPITestCase(BaseTestCase):
self.context, instance['uuid'])
def test_delete_handles_host_setting_race_condition(self):
- instance, instance_uuid = self._run_instance()
+ instance, instance_uuid = self._run_instance(params={
+ 'host': FLAGS.host})
instance['host'] = None # make it think host was never set
self.compute_api.delete(self.context, instance)
@@ -2771,7 +2776,8 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, instance['uuid'])
def test_delete_fail(self):
- instance, instance_uuid = self._run_instance()
+ instance, instance_uuid = self._run_instance(params={
+ 'host': FLAGS.host})
instance = db.instance_update(self.context, instance_uuid,
{'disable_terminate': True})
@@ -2806,7 +2812,8 @@ class ComputeAPITestCase(BaseTestCase):
def test_force_delete(self):
"""Ensure instance can be deleted after a soft delete"""
- instance = jsonutils.to_primitive(self._create_fake_instance())
+ instance = jsonutils.to_primitive(self._create_fake_instance(params={
+ 'host': FLAGS.host}))
instance_uuid = instance['uuid']
self.compute.run_instance(self.context, instance=instance)
@@ -3999,7 +4006,7 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, i_ref['uuid'])
def test_add_remove_fixed_ip(self):
- instance = self._create_fake_instance()
+ instance = self._create_fake_instance(params={'host': FLAGS.host})
self.compute_api.add_fixed_ip(self.context, instance, '1')
self.compute_api.remove_fixed_ip(self.context, instance, '192.168.1.1')
self.compute_api.delete(self.context, instance)
@@ -4097,7 +4104,7 @@ class ComputeAPITestCase(BaseTestCase):
self.compute_api.attach_volume(self.context, instance, 1, '/dev/vdb')
def test_inject_network_info(self):
- instance = self._create_fake_instance()
+ instance = self._create_fake_instance(params={'host': FLAGS.host})
self.compute.run_instance(self.context,
instance=jsonutils.to_primitive(instance))
instance = self.compute_api.get(self.context, instance['uuid'])