From 91160c423839fc8a385dd28c96f94c2b2cdb02cd Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Fri, 15 May 2020 16:49:12 -0400 Subject: [PATCH] Make quotas respect instance_list_per_project_cells This option was introduced in order to limit queries to cells which only belong to the project we're interacting with. However, The nova quota code was not respecting it and therefore it was always trying to get the cells assigned to a project even with that option disabled. This patch makes the quota code respect that option and adds testing to ensure that enabling the option does make sure it doesn't search all cells but only the ones for this project. Closes-Bug: #1878979 Change-Id: I2e0d48e799e70d550f912ad8a424c86df3ade3a2 (cherry picked from commit ab16946885e68ccdef7222a71cc0ad6f92b10de7) (cherry picked from commit fa2bfac862e9e1db5a98c64a56a933987f857903) --- nova/quota.py | 8 ++++++-- nova/tests/functional/db/test_quota.py | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/nova/quota.py b/nova/quota.py index 241d7ecc0810..314eabd9365a 100644 --- a/nova/quota.py +++ b/nova/quota.py @@ -1236,8 +1236,12 @@ def _instances_cores_ram_count_legacy(context, project_id, user_id=None): # this filtering if there is more than one non-cell0 cell. # TODO(tssurya): Consider adding a scatter_gather_cells_for_project # variant that makes this native to nova.context. - cell_mappings = objects.CellMappingList.get_by_project_id( - context, project_id) + if CONF.api.instance_list_per_project_cells: + cell_mappings = objects.CellMappingList.get_by_project_id( + context, project_id) + else: + nova_context.load_cells() + cell_mappings = nova_context.CELLS results = nova_context.scatter_gather_cells( context, cell_mappings, nova_context.CELL_TIMEOUT, objects.InstanceList.get_counts, project_id, user_id=user_id) diff --git a/nova/tests/functional/db/test_quota.py b/nova/tests/functional/db/test_quota.py index a66ec1689959..8c2b637269e1 100644 --- a/nova/tests/functional/db/test_quota.py +++ b/nova/tests/functional/db/test_quota.py @@ -139,7 +139,9 @@ class QuotaTestCase(test.NoDBTestCase): ctxt, group, instance.user_id) self.assertEqual(2, count['user']['server_group_members']) - def test_instances_cores_ram_count(self): + @mock.patch('nova.objects.CellMappingList.get_by_project_id', + wraps=objects.CellMappingList.get_by_project_id) + def test_instances_cores_ram_count(self, mock_get_project_cell_mappings): ctxt = context.RequestContext('fake-user', 'fake-project') mapping1 = objects.CellMapping(context=ctxt, uuid=uuidutils.generate_uuid(), @@ -197,10 +199,22 @@ class QuotaTestCase(test.NoDBTestCase): project_id='fake-project') im.create() - # Count instances, cores, and ram across cells + # Count instances, cores, and ram across cells (all cells) count = quota._instances_cores_ram_count(ctxt, 'fake-project', user_id='fake-user') + mock_get_project_cell_mappings.assert_not_called() + self.assertEqual(3, count['project']['instances']) + self.assertEqual(10, count['project']['cores']) + self.assertEqual(2560, count['project']['ram']) + self.assertEqual(2, count['user']['instances']) + self.assertEqual(6, count['user']['cores']) + self.assertEqual(1536, count['user']['ram']) + # Count instances, cores, and ram across cells (query cell subset) + self.flags(instance_list_per_project_cells=True, group='api') + count = quota._instances_cores_ram_count(ctxt, 'fake-project', + user_id='fake-user') + mock_get_project_cell_mappings.assert_called_with(ctxt, 'fake-project') self.assertEqual(3, count['project']['instances']) self.assertEqual(10, count['project']['cores']) self.assertEqual(2560, count['project']['ram'])