Make _instances_cores_ram_count() be smart about cells

This makes the _instances_cores_ram_count() method only query for instances
in cells that the tenant actually has instances landed in. We do this by
getting a list of cell mappings that have instance mappings owned by the
project and limiting the scatter/gather operation to just those cells.

Change-Id: I0e2a9b2460145d3aee92f7fddc4f4da16af63ff8
Closes-Bug: #1771810
This commit is contained in:
Surya Seetharaman 2018-05-17 10:16:56 +02:00 committed by Matt Riedemann
parent e27905f482
commit 7788165925
3 changed files with 52 additions and 14 deletions

View File

@ -1168,8 +1168,17 @@ def _instances_cores_ram_count(context, project_id, user_id=None):
# counting resources if a cell is down. In the future, we should query
# placement for cores/ram and InstanceMappings for instances (once we are
# deleting InstanceMappings when we delete instances).
results = nova_context.scatter_gather_all_cells(
context, objects.InstanceList.get_counts, project_id, user_id=user_id)
# NOTE(tssurya): We only go into those cells in which the tenant has
# instances. We could optimize this to avoid the CellMappingList query
# for single-cell deployments by checking the cell cache and only doing
# 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)
results = nova_context.scatter_gather_cells(
context, cell_mappings, nova_context.CELL_TIMEOUT,
objects.InstanceList.get_counts, project_id, user_id=user_id)
total_counts = {'project': {'instances': 0, 'cores': 0, 'ram': 0}}
if user_id:
total_counts['user'] = {'instances': 0, 'cores': 0, 'ram': 0}

View File

@ -98,6 +98,13 @@ class QuotaTestCase(test.NoDBTestCase):
user_id='fake-user',
vcpus=2, memory_mb=512)
instance.create()
# create mapping for the instance since we query only those cells
# in which the project has instances based on the instance_mappings
im = objects.InstanceMapping(context=ctxt,
instance_uuid=instance.uuid,
cell_mapping=mapping1,
project_id='fake-project')
im.create()
# Create an instance in cell2
with context.target_cell(ctxt, mapping2) as cctxt:
@ -106,6 +113,13 @@ class QuotaTestCase(test.NoDBTestCase):
user_id='fake-user',
vcpus=4, memory_mb=1024)
instance.create()
# create mapping for the instance since we query only those cells
# in which the project has instances based on the instance_mappings
im = objects.InstanceMapping(context=ctxt,
instance_uuid=instance.uuid,
cell_mapping=mapping2,
project_id='fake-project')
im.create()
# Create an instance in cell2 for a different user
with context.target_cell(ctxt, mapping2) as cctxt:
@ -114,6 +128,13 @@ class QuotaTestCase(test.NoDBTestCase):
user_id='other-fake-user',
vcpus=4, memory_mb=1024)
instance.create()
# create mapping for the instance since we query only those cells
# in which the project has instances based on the instance_mappings
im = objects.InstanceMapping(context=ctxt,
instance_uuid=instance.uuid,
cell_mapping=mapping2,
project_id='fake-project')
im.create()
# Count instances, cores, and ram across cells
count = quota._instances_cores_ram_count(ctxt, 'fake-project',

View File

@ -86,18 +86,26 @@ class QuotaIntegrationTestCase(test.TestCase):
nova.tests.unit.image.fake.FakeImageService_reset()
def _create_instance(self, flavor_name='m1.large'):
"""Create a test instance."""
inst = objects.Instance(context=self.context)
inst.image_id = 'cedef40a-ed67-4d10-800e-17455edce175'
inst.reservation_id = 'r-fakeres'
inst.user_id = self.user_id
inst.project_id = self.project_id
inst.flavor = flavors.get_flavor_by_name(flavor_name)
# This is needed for instance quota counting until we have the
# ability to count allocations in placement.
inst.vcpus = inst.flavor.vcpus
inst.memory_mb = inst.flavor.memory_mb
inst.create()
"""Create a test instance in cell1 with an instance mapping."""
cell1 = self.cell_mappings[test.CELL1_NAME]
with context.target_cell(self.context, cell1) as cctxt:
inst = objects.Instance(context=cctxt)
inst.image_id = 'cedef40a-ed67-4d10-800e-17455edce175'
inst.reservation_id = 'r-fakeres'
inst.user_id = self.user_id
inst.project_id = self.project_id
inst.flavor = flavors.get_flavor_by_name(flavor_name)
# This is needed for instance quota counting until we have the
# ability to count allocations in placement.
inst.vcpus = inst.flavor.vcpus
inst.memory_mb = inst.flavor.memory_mb
inst.create()
# Create the related instance mapping which will be used in
# _instances_cores_ram_count().
inst_map = objects.InstanceMapping(
self.context, instance_uuid=inst.uuid, project_id=inst.project_id,
cell_mapping=cell1)
inst_map.create()
return inst
def test_too_many_instances(self):