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
This commit is contained in:
Artom Lifshitz 2019-09-24 13:22:23 -04:00
parent 9b2e00e015
commit 6ec686c26b
2 changed files with 6 additions and 7 deletions

View File

@ -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()

View File

@ -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):