diff options
author | Rajesh Tailor <rajesh.tailor@nttdata.com> | 2014-09-16 05:50:47 -0700 |
---|---|---|
committer | sahid <sahid.ferdjaoui@redhat.com> | 2015-06-10 06:59:24 +0000 |
commit | 90793b9d397e2987cfd0e658dd64eaa035c14ed7 (patch) | |
tree | e9541b9161cd16968fe707e92126afc21fb4ffeb | |
parent | e2ab3296fc85de905b522510ce1079fa4bdbcebb (diff) | |
download | nova-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.py | 25 | ||||
-rw-r--r-- | nova/tests/compute/test_compute_mgr.py | 63 |
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() |