From ab16946885e68ccdef7222a71cc0ad6f92b10de7 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 --- 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 b0e4d33997e..29a0fc05e80 100644 --- a/nova/quota.py +++ b/nova/quota.py @@ -1191,8 +1191,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 a66ec168995..8c2b637269e 100644 --- a/nova/tests/functional/db/test_quota.py +++ b/nova/tests/functional/db/test_quota.py @@ -139,7 +139,9 @@ def test_server_group_members_count_by_user(self, uid_qfd_populated, 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 @@ def test_instances_cores_ram_count(self): 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'])