summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajesh Tailor <rajesh.tailor@nttdata.com>2014-09-16 05:50:47 -0700
committersahid <sahid.ferdjaoui@redhat.com>2015-06-10 06:59:24 +0000
commit90793b9d397e2987cfd0e658dd64eaa035c14ed7 (patch)
treee9541b9161cd16968fe707e92126afc21fb4ffeb
parente2ab3296fc85de905b522510ce1079fa4bdbcebb (diff)
downloadnova-90793b9d397e2987cfd0e658dd64eaa035c14ed7.tar.gz
Fix quota-update in deleting when nova-compute startup finish
Quotas are not updated correctly for the instances whose task_state is in deleting status during the nova-compute init_host call. Added code to pass correct quota to the _delete_instance method. (cherry picked from commit 2635ee08266858a564596ca7393e11be4e050606) Change-Id: Ida84d2d49d46540e0581dc3a58844c30bc1d2cff Partial-Bug: 1296414
-rw-r--r--nova/compute/manager.py25
-rw-r--r--nova/tests/compute/test_compute_mgr.py63
2 files changed, 79 insertions, 9 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 0ba48a0096..d76ddac566 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -860,6 +860,18 @@ class ComputeManager(manager.Manager):
self.consoleauth_rpcapi.delete_tokens_for_instance(context,
instance.uuid)
+ def _create_reservations(self, context, instance, project_id, user_id):
+ vcpus = instance.vcpus
+ mem_mb = instance.memory_mb
+
+ quotas = objects.Quotas(context=context)
+ quotas.reserve(project_id=project_id,
+ user_id=user_id,
+ instances=-1,
+ cores=-vcpus,
+ ram=-mem_mb)
+ return quotas
+
def _init_instance(self, context, instance):
'''Initialize this instance during service init.'''
@@ -953,14 +965,11 @@ class ComputeManager(manager.Manager):
instance.obj_load_attr('system_metadata')
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
context, instance.uuid)
- # FIXME(comstud): This needs fixed. We should be creating
- # reservations and updating quotas, because quotas
- # wouldn't have been updated for this instance since it is
- # still in DELETING. See bug 1296414.
- #
- # Create a dummy quota object for now.
- quotas = objects.Quotas.from_reservations(
- context, None, instance=instance)
+ project_id, user_id = objects.quotas.ids_from_instance(
+ context, instance)
+ quotas = self._create_reservations(context, instance,
+ project_id, user_id)
+
self._delete_instance(context, instance, bdms, quotas)
except Exception:
# we don't want that an exception blocks the init_host
diff --git a/nova/tests/compute/test_compute_mgr.py b/nova/tests/compute/test_compute_mgr.py
index 4aca583c72..30b7995501 100644
--- a/nova/tests/compute/test_compute_mgr.py
+++ b/nova/tests/compute/test_compute_mgr.py
@@ -426,7 +426,10 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
def test_init_instance_stuck_in_deleting(self):
instance = fake_instance.fake_instance_obj(
self.context,
+ project_id='fake',
uuid='fake-uuid',
+ vcpus=1,
+ memory_mb=64,
power_state=power_state.RUNNING,
vm_state=vm_states.ACTIVE,
host=self.compute.host,
@@ -436,18 +439,64 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
'get_by_instance_uuid')
self.mox.StubOutWithMock(self.compute, '_delete_instance')
self.mox.StubOutWithMock(instance, 'obj_load_attr')
+ self.mox.StubOutWithMock(self.compute, '_create_reservations')
bdms = []
+ quotas = objects.quotas.Quotas(self.context)
instance.obj_load_attr('metadata')
instance.obj_load_attr('system_metadata')
objects.BlockDeviceMappingList.get_by_instance_uuid(
self.context, instance.uuid).AndReturn(bdms)
+ self.compute._create_reservations(self.context, instance,
+ instance.project_id,
+ instance.user_id).AndReturn(quotas)
self.compute._delete_instance(self.context, instance, bdms,
mox.IgnoreArg())
self.mox.ReplayAll()
self.compute._init_instance(self.context, instance)
+ @mock.patch.object(objects.Instance, 'get_by_uuid')
+ @mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
+ def test_init_instance_stuck_in_deleting_raises_exception(
+ self, mock_get_by_instance_uuid, mock_get_by_uuid):
+
+ instance = fake_instance.fake_instance_obj(
+ self.context,
+ project_id='fake',
+ uuid='fake-uuid',
+ vcpus=1,
+ memory_mb=64,
+ metadata={},
+ system_metadata={},
+ host=self.compute.host,
+ vm_state=vm_states.ACTIVE,
+ task_state=task_states.DELETING,
+ expected_attrs=['metadata', 'system_metadata'])
+
+ bdms = []
+ reservations = ['fake-resv']
+
+ def _create_patch(name, attr):
+ patcher = mock.patch.object(name, attr)
+ mocked_obj = patcher.start()
+ self.addCleanup(patcher.stop)
+ return mocked_obj
+
+ mock_delete_instance = _create_patch(self.compute, '_delete_instance')
+ mock_set_instance_error_state = _create_patch(
+ self.compute, '_set_instance_error_state')
+ mock_create_reservations = _create_patch(self.compute,
+ '_create_reservations')
+
+ mock_create_reservations.return_value = reservations
+ mock_get_by_instance_uuid.return_value = bdms
+ mock_get_by_uuid.return_value = instance
+ mock_delete_instance.side_effect = test.TestingException('test')
+ self.compute._init_instance(self.context, instance)
+ mock_set_instance_error_state.assert_called_once_with(
+ self.context, instance)
+
def _test_init_instance_reverts_crashed_migrations(self,
old_vm_state=None):
power_on = True if (not old_vm_state or
@@ -644,20 +693,32 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
def test_init_instance_deletes_error_deleting_instance(self):
instance = fake_instance.fake_instance_obj(
self.context,
- uuid='fake',
+ project_id='fake',
+ uuid='fake-uuid',
+ vcpus=1,
+ memory_mb=64,
vm_state=vm_states.ERROR,
host=self.compute.host,
task_state=task_states.DELETING)
+
self.mox.StubOutWithMock(objects.BlockDeviceMappingList,
'get_by_instance_uuid')
self.mox.StubOutWithMock(self.compute, '_delete_instance')
self.mox.StubOutWithMock(instance, 'obj_load_attr')
+ self.mox.StubOutWithMock(objects.quotas, 'ids_from_instance')
+ self.mox.StubOutWithMock(self.compute, '_create_reservations')
bdms = []
+ quotas = objects.quotas.Quotas(self.context)
instance.obj_load_attr('metadata')
instance.obj_load_attr('system_metadata')
objects.BlockDeviceMappingList.get_by_instance_uuid(
self.context, instance.uuid).AndReturn(bdms)
+ objects.quotas.ids_from_instance(self.context, instance).AndReturn(
+ (instance.project_id, instance.user_id))
+ self.compute._create_reservations(self.context, instance,
+ instance.project_id,
+ instance.user_id).AndReturn(quotas)
self.compute._delete_instance(self.context, instance, bdms,
mox.IgnoreArg())
self.mox.ReplayAll()