Modify get_by_cell_and_project() to get_not_deleted_by_cell_and_project()

InstanceMappingList.get_by_cell_and_project() is being changed to
get_not_deleted_by_cell_and_project() by which we change the method to
filter out not queued_for_delete instance_mappings and also for
the method to accept cell_uuid as the input instead of the cell_id.
This also adds an optional limit parameter. This is more useful than
the ealier approach since it would increase the performance slightly
by not having to query for the cell_mappings explicitly to get the
cell ids from the cell uuids obtained from scatter gather utility.

Note that this method was added relatively recently and hence is not
used anywhere which is why it should be fine to change this, keeping
in mind the intention of having added it in the first place.

Change-Id: I5df9851cce0b6e635c74fd34f5be9c4906dd7406
Related to blueprint handling-down-cell
This commit is contained in:
Surya Seetharaman 2018-10-03 15:53:41 +02:00 committed by Matt Riedemann
parent 272fbb1993
commit d4f8040117
2 changed files with 104 additions and 31 deletions

View File

@ -12,6 +12,7 @@
from oslo_utils import versionutils
from sqlalchemy.orm import joinedload
from sqlalchemy.sql import false
from nova import context as nova_context
from nova.db.sqlalchemy import api as db_api
@ -252,16 +253,31 @@ class InstanceMappingList(base.ObjectListBase, base.NovaObject):
@staticmethod
@db_api.api_context_manager.reader
def _get_by_cell_and_project_from_db(context, cell_id, project_id):
return (context.session.query(api_models.InstanceMapping)
.options(joinedload('cell_mapping'))
.filter_by(cell_id=cell_id)
.filter_by(project_id=project_id)
.all())
def _get_not_deleted_by_cell_and_project_from_db(context, cell_uuid,
project_id, limit):
query = (
context.session.query(api_models.InstanceMapping)
.filter_by(project_id=project_id)
.filter_by(queued_for_delete=false())
.join('cell_mapping')
.options(joinedload('cell_mapping'))
.filter(api_models.CellMapping.uuid == cell_uuid))
if limit is not None:
query = query.limit(limit)
return query.all()
@classmethod
def get_by_cell_and_project(cls, context, cell_id, project_id):
db_mappings = cls._get_by_cell_and_project_from_db(context, cell_id,
project_id)
def get_not_deleted_by_cell_and_project(cls, context, cell_uuid,
project_id, limit=None):
"""Return a limit restricted list of InstanceMapping objects which are
mapped to the specified cell_uuid, belong to the specified
project_id and are not queued for deletion (note that unlike the other
InstanceMappingList query methods which return all mappings
irrespective of whether they are queued for deletion this method
explicitly queries only for those mappings that are *not* queued for
deletion as is evident from the naming of the method).
"""
db_mappings = cls._get_not_deleted_by_cell_and_project_from_db(
context, cell_uuid, project_id, limit)
return base.obj_make_list(context, cls(), objects.InstanceMapping,
db_mappings)

View File

@ -256,7 +256,7 @@ class InstanceMappingListTestCase(test.NoDBTestCase):
self.assertEqual(sorted(uuids),
sorted([m.instance_uuid for m in mappings]))
def test_get_by_cell_and_project(self):
def test_get_not_deleted_by_cell_and_project(self):
cells = []
# Create two cells
for uuid in (uuidsentinel.cell1, uuidsentinel.cell2):
@ -265,30 +265,87 @@ class InstanceMappingListTestCase(test.NoDBTestCase):
transport_url='fake://')
cm.create()
cells.append(cm)
# With each cell having two instance_mappings of two project_ids.
uuids = {cells[0].id: [uuidsentinel.c1i1, uuidsentinel.c1i2],
cells[1].id: [uuidsentinel.c2i1, uuidsentinel.c2i2]}
project_ids = ['fake-project-1', 'fake-project-2']
for cell_id, uuid in uuids.items():
instance_mapping.InstanceMapping._create_in_db(
self.context,
{'project_id': project_ids[0],
'cell_id': cell_id,
'instance_uuid': uuid[0]})
instance_mapping.InstanceMapping._create_in_db(
self.context,
{'project_id': project_ids[1],
'cell_id': cell_id,
'instance_uuid': uuid[1]})
ims = instance_mapping.InstanceMappingList.get_by_cell_and_project(
self.context, cells[0].id, 'fake-project-2')
uuids = {cells[0]: [uuidsentinel.c1i1, uuidsentinel.c1i2],
cells[1]: [uuidsentinel.c2i1, uuidsentinel.c2i2]}
project_ids = ['fake-project-1', 'fake-project-2']
# Create five instance_mappings such that:
for cell, uuid in uuids.items():
# Both the cells contain a mapping belonging to fake-project-1
im1 = instance_mapping.InstanceMapping(context=self.context,
project_id=project_ids[0], cell_mapping=cell,
instance_uuid=uuid[0], queued_for_delete=False)
im1.create()
# Both the cells contain a mapping belonging to fake-project-2
im2 = instance_mapping.InstanceMapping(context=self.context,
project_id=project_ids[1], cell_mapping=cell,
instance_uuid=uuid[1], queued_for_delete=False)
im2.create()
# The second cell has a third mapping that is queued for deletion
# which belongs to fake-project-1.
if cell.uuid == uuidsentinel.cell2:
im3 = instance_mapping.InstanceMapping(context=self.context,
project_id=project_ids[0], cell_mapping=cell,
instance_uuid=uuidsentinel.qfd, queued_for_delete=True)
im3.create()
# Get not queued for deletion mappings from cell1 belonging to
# fake-project-2.
ims = (instance_mapping.InstanceMappingList.
get_not_deleted_by_cell_and_project(
self.context, cells[0].uuid, 'fake-project-2'))
# This will give us one mapping from cell1
self.assertEqual([uuidsentinel.c1i2],
sorted([m.instance_uuid for m in ims]))
ims = instance_mapping.InstanceMappingList.get_by_cell_and_project(
self.context, cells[1].id, 'fake-project-1')
self.assertIn('cell_mapping', ims[0])
# Get not queued for deletion mappings from cell2 belonging to
# fake-project-1.
ims = (instance_mapping.InstanceMappingList.
get_not_deleted_by_cell_and_project(
self.context, cells[1].uuid, 'fake-project-1'))
# This will give us one mapping from cell2. Note that even if
# there are two mappings belonging to fake-project-1 inside cell2,
# only the one not queued for deletion is returned.
self.assertEqual([uuidsentinel.c2i1],
sorted([m.instance_uuid for m in ims]))
ims = instance_mapping.InstanceMappingList.get_by_cell_and_project(
self.context, cells[0].id, 'fake-project-3')
# Try getting a mapping belonging to a non-existing project_id.
ims = (instance_mapping.InstanceMappingList.
get_not_deleted_by_cell_and_project(
self.context, cells[0].uuid, 'fake-project-3'))
# Since no mappings belong to fake-project-3, nothing is returned.
self.assertEqual([], sorted([m.instance_uuid for m in ims]))
def test_get_not_deleted_by_cell_and_project_limit(self):
cm = cell_mapping.CellMapping(context=self.context,
uuid=uuidsentinel.cell,
database_connection='fake:///',
transport_url='fake://')
cm.create()
pid = self.context.project_id
for uuid in (uuidsentinel.uuid2, uuidsentinel.inst2):
im = instance_mapping.InstanceMapping(context=self.context,
project_id=pid,
cell_mapping=cm,
instance_uuid=uuid,
queued_for_delete=False)
im.create()
ims = (instance_mapping.InstanceMappingList.
get_not_deleted_by_cell_and_project(self.context,
cm.uuid,
pid))
self.assertEqual(2, len(ims))
ims = (instance_mapping.InstanceMappingList.
get_not_deleted_by_cell_and_project(self.context,
cm.uuid,
pid,
limit=10))
self.assertEqual(2, len(ims))
ims = (instance_mapping.InstanceMappingList.
get_not_deleted_by_cell_and_project(self.context,
cm.uuid,
pid,
limit=1))
self.assertEqual(1, len(ims))