From 5c6c816d8c83e892c6dba4b5edb318d6c288ec7a Mon Sep 17 00:00:00 2001 From: Surya Seetharaman Date: Wed, 6 Feb 2019 10:30:49 +0100 Subject: [PATCH] Modify InstanceMappingList.get_not_deleted_by_cell_and_project() 1) Change it to accommodate querying it for 'None' project_ids in the "--all-tenats" case. 2) If the online data migration for populating queued_for_delete has not been run for some reason, the the values could be NULL in the database for instance_mapping.queued_for_delete. Under such circumstances, we assume that such mappings with NULL queued_for_delete have *not* being queued_for_deletion. Related to blueprint handling-down-cell Change-Id: I80a65bc026e26a272a9dc041b27f9839511db765 --- nova/objects/instance_mapping.py | 17 +++++++++--- .../functional/db/test_instance_mapping.py | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/nova/objects/instance_mapping.py b/nova/objects/instance_mapping.py index b9740cc4f4db..4bc232f37cee 100644 --- a/nova/objects/instance_mapping.py +++ b/nova/objects/instance_mapping.py @@ -13,6 +13,7 @@ from oslo_utils import versionutils from sqlalchemy.orm import joinedload from sqlalchemy.sql import false +from sqlalchemy.sql import or_ from nova import context as nova_context from nova.db.sqlalchemy import api as db_api @@ -260,10 +261,18 @@ class InstanceMappingList(base.ObjectListBase, base.NovaObject): @db_api.api_context_manager.reader 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()) + query = context.session.query(api_models.InstanceMapping) + if project_id is not None: + # Note that the project_id can be None in case + # instances are being listed for the all-tenants case. + query = query.filter_by(project_id=project_id) + # Both the values NULL (for cases when the online data migration for + # queued_for_delete was not run) and False (cases when the online + # data migration for queued_for_delete was run) are assumed to mean + # that the instance is not queued for deletion. + query = (query.filter(or_( + api_models.InstanceMapping.queued_for_delete == false(), + api_models.InstanceMapping.queued_for_delete.is_(None))) .join('cell_mapping') .options(joinedload('cell_mapping')) .filter(api_models.CellMapping.uuid == cell_uuid)) diff --git a/nova/tests/functional/db/test_instance_mapping.py b/nova/tests/functional/db/test_instance_mapping.py index 51415c3d1d18..b96cfaae56ec 100644 --- a/nova/tests/functional/db/test_instance_mapping.py +++ b/nova/tests/functional/db/test_instance_mapping.py @@ -349,3 +349,29 @@ class InstanceMappingListTestCase(test.NoDBTestCase): pid, limit=1)) self.assertEqual(1, len(ims)) + + def test_get_not_deleted_by_cell_and_project_None(self): + cm = cell_mapping.CellMapping(context=self.context, + uuid=uuidsentinel.cell, + database_connection='fake:///', + transport_url='fake://') + cm.create() + im1 = instance_mapping.InstanceMapping(context=self.context, + project_id='fake-project-1', + cell_mapping=cm, + instance_uuid=uuidsentinel.uid1, + queued_for_delete=False) + im1.create() + im2 = instance_mapping.InstanceMapping(context=self.context, + project_id='fake-project-2', + cell_mapping=cm, + instance_uuid=uuidsentinel.uid2, + queued_for_delete=None) + im2.create() + # testing if it accepts None project_id in the query and + # catches None queued for delete records. + ims = (instance_mapping.InstanceMappingList. + get_not_deleted_by_cell_and_project(self.context, + cm.uuid, + None)) + self.assertEqual(2, len(ims))