Add @targets_cell for live_migrate_instance method in conductor

With microversion < 2.34, the API casts to the migrate_server
method in super conductor which targets the context using the
@targets_cell decorator.

With microversion >= 2.34, the API casts to the live_migrate_instance
method in super conductor which does not use the @targets_cell
decorator, which results in a failure to lookup the instance action
record when recording the start of the action event with the
@wrap_instance_event decorator.

This change simply adds the decorator and provides a test which
was missing for this before. Note that the live migration CI job
didn't catch this regression since it only tests up to microversion
2.26.

Co-Authored-By: Matt Riedemann <mriedem.os@gmail.com>

Closes-bug: #1716903
Change-Id: I21d3f3b7589221b7e0a46c332510afc876ca5a79
This commit is contained in:
Yikun Jiang 2017-09-13 19:35:49 +08:00 committed by Matt Riedemann
parent f91817aaf4
commit 062f5b2e87
2 changed files with 35 additions and 0 deletions

View File

@ -375,6 +375,7 @@ class ComputeTaskManager(base.Base):
# exception will be raised by instance.save()
pass
@targets_cell
@wrap_instance_event(prefix='conductor')
def live_migrate_instance(self, context, instance, scheduler_hint,
block_migration, disk_over_commit, request_spec):

View File

@ -2613,6 +2613,40 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
{'vm_state': instance.vm_state, 'task_state': None}, ex,
reqspec.to_legacy_request_spec_dict())
@mock.patch('nova.conductor.tasks.live_migrate.LiveMigrationTask.execute')
def test_live_migrate_instance(self, mock_execute):
"""Tests that asynchronous live migration targets the cell that the
instance lives in.
"""
instance = self.params['build_requests'][0].instance
scheduler_hint = {'host': None}
reqspec = self.params['request_specs'][0]
# setUp created the instance mapping but didn't target it to a cell,
# to mock out the API doing that, but let's just update it to point
# at cell1.
im = objects.InstanceMapping.get_by_instance_uuid(
self.ctxt, instance.uuid)
im.cell_mapping = self.cell_mappings[test.CELL1_NAME]
im.save()
# Make sure the InstanceActionEvent is created in the cell.
original_event_start = objects.InstanceActionEvent.event_start
def fake_event_start(_cls, ctxt, *args, **kwargs):
# Make sure the context is targeted to the cell that the instance
# was created in.
self.assertIsNotNone(ctxt.db_connection, 'Context is not targeted')
original_event_start(ctxt, *args, **kwargs)
self.stub_out(
'nova.objects.InstanceActionEvent.event_start', fake_event_start)
self.conductor.live_migrate_instance(
self.ctxt, instance, scheduler_hint, block_migration=None,
disk_over_commit=None, request_spec=reqspec)
mock_execute.assert_called_once_with()
class ConductorTaskRPCAPITestCase(_BaseTaskTestCase,
test_compute.BaseTestCase):