From 6ec686c26b2c8b18bcff522633bfe9715e0feec3 Mon Sep 17 00:00:00 2001 From: Artom Lifshitz Date: Tue, 24 Sep 2019 13:22:23 -0400 Subject: [PATCH] Stop filtering out 'accepted' for in-progress migrations Live migrations are created with an 'accepted' status. Resource claims on the destination are done with the migration in 'accepted' status. The status is set to 'preparing' a bit later, right before running pre_live_migration(). Migrations with status 'accepted' are filtered out by the database layer when getting in-progress migrations. Thus, there's a time window after resource claims but before 'preparing' during which resources have been claimed but the migration is not considered in-progress by the database layer. During that window, the instance's host is the source - that's only updated once the live migration finishes. If the update available resources periodic task runs during that window, it'll free the instance's resource from the destination because neither the instance nor any of its in-progress migrations are associated with the destination. This means that other incoming instances are able to consume resources that should not be available. This patch stops filtering out the 'accepted' status in the database layer when retrieving in-progress migrations. Change-Id: I4c56925ed35bc3275ca1ac6c30d7fd641ad84260 Closes-bug: 1845146 --- nova/db/sqlalchemy/api.py | 8 ++++---- nova/tests/unit/db/test_db_api.py | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 265138e961d0..25efebe9fdea 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -4419,10 +4419,10 @@ def migration_get_in_progress_by_host_and_node(context, host, node): models.Migration.source_node == node), and_(models.Migration.dest_compute == host, models.Migration.dest_node == node))).\ - filter(~models.Migration.status.in_(['accepted', 'confirmed', - 'reverted', 'error', - 'failed', 'completed', - 'cancelled', 'done'])).\ + filter(~models.Migration.status.in_(['confirmed', 'reverted', + 'error', 'failed', + 'completed', 'cancelled', + 'done'])).\ options(_joinedload_all('instance.system_metadata')).\ all() diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py index 18944f2ff6a1..46c9de4c1db1 100644 --- a/nova/tests/unit/db/test_db_api.py +++ b/nova/tests/unit/db/test_db_api.py @@ -1153,7 +1153,6 @@ class MigrationTestCase(test.TestCase): self.assertNotEqual('reverted', migration['status']) self.assertNotEqual('error', migration['status']) self.assertNotEqual('failed', migration['status']) - self.assertNotEqual('accepted', migration['status']) self.assertNotEqual('done', migration['status']) self.assertNotEqual('cancelled', migration['status']) @@ -1169,7 +1168,7 @@ class MigrationTestCase(test.TestCase): migrations = db.migration_get_in_progress_by_host_and_node(self.ctxt, 'host1', 'a') # 2 as source + 1 as dest - self.assertEqual(3, len(migrations)) + self.assertEqual(4, len(migrations)) self._assert_in_progress(migrations) def test_in_progress_host1_nodeb(self): @@ -1182,7 +1181,7 @@ class MigrationTestCase(test.TestCase): migrations = db.migration_get_in_progress_by_host_and_node(self.ctxt, 'host2', 'b') # 2 as dest, 1 as source - self.assertEqual(3, len(migrations)) + self.assertEqual(4, len(migrations)) self._assert_in_progress(migrations) def test_instance_join(self):