Skip to content

Commit

Permalink
Avoid live migrate overwriting the other task_state
Browse files Browse the repository at this point in the history
As commit 4082c83 says,
one ordinary task is running, so that task_state is set. The
live_migrate task is accepted at API, and will change task_state to
MIGRATING. However the first task may continue to update task_state or
set it to None as it finishes.

This patch avoids it by updating task_state in compute.api.live_migrate
level with expected_task_state=None.

Add test case for compute.api.live_migrate.

Fixes bug 1049533

Change-Id: Ida8cef4797de421a7e356c9f5e882fe926535639
  • Loading branch information
wenjianhn committed Sep 12, 2012
1 parent b961bd4 commit a3bdc16
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 22 deletions.
4 changes: 4 additions & 0 deletions nova/compute/api.py
Expand Up @@ -1941,6 +1941,10 @@ def live_migrate(self, context, instance, block_migration,
LOG.debug(_("Going to try to live migrate instance to %s"),
host, instance=instance)

instance = self.update(context, instance,
task_state=task_states.MIGRATING,
expected_task_state=None)

self.scheduler_rpcapi.live_migration(context, block_migration,
disk_over_commit, instance, host)

Expand Down
11 changes: 1 addition & 10 deletions nova/scheduler/driver.py
Expand Up @@ -203,19 +203,10 @@ def schedule_live_migration(self, context, instance, dest,
migrate_data = self.compute_rpcapi.check_can_live_migrate_destination(
context, instance, dest, block_migration, disk_over_commit)

# Change instance_state
values = {"task_state": task_states.MIGRATING}

# update instance state and notify
(old_ref, new_instance_ref) = db.instance_update_and_get_original(
context, instance['uuid'], values)
notifications.send_update(context, old_ref, new_instance_ref,
service="scheduler")

# Perform migration
src = instance['host']
self.compute_rpcapi.live_migration(context, host=src,
instance=new_instance_ref, dest=dest,
instance=instance, dest=dest,
block_migration=block_migration,
migrate_data=migrate_data)

Expand Down
Expand Up @@ -139,6 +139,13 @@ def test_migrate_live_enabled(self):
}
})
req.content_type = 'application/json'

def fake_update(inst, context, instance,
task_state, expected_task_state):
return None

self.stubs.Set(compute.API, 'update', fake_update)

res = req.get_response(app)
self.assertEqual(res.status_int, 202)

Expand Down
17 changes: 17 additions & 0 deletions nova/tests/compute/test_compute.py
Expand Up @@ -80,6 +80,10 @@ def run_instance(self, ctxt, request_spec, admin_password,
filter_properties):
pass

def live_migration(self, ctxt, block_migration, disk_over_commit,
instance, dest):
pass


class BaseTestCase(test.TestCase):

Expand Down Expand Up @@ -4449,6 +4453,19 @@ def group_get(*args, **kwargs):

self.security_group_api.trigger_rules_refresh(self.context, [1, 2])

def test_live_migrate(self):
instance, instance_uuid = self._run_instance()

self.compute_api.live_migrate(self.context, instance,
block_migration=True,
disk_over_commit=True,
host='fake_dest_host')

instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertEqual(instance['task_state'], task_states.MIGRATING)

db.instance_destroy(self.context, instance['uuid'])


def fake_rpc_method(context, topic, msg, do_cast=True):
pass
Expand Down
12 changes: 0 additions & 12 deletions nova/tests/scheduler/test_scheduler.py
Expand Up @@ -311,10 +311,8 @@ def test_live_migration_basic(self):
self.mox.StubOutWithMock(self.driver, '_live_migration_common_check')
self.mox.StubOutWithMock(self.driver.compute_rpcapi,
'check_can_live_migrate_destination')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
self.mox.StubOutWithMock(self.driver.compute_rpcapi,
'live_migration')
self.mox.StubOutWithMock(notifications, 'send_update')

dest = 'fake_host2'
block_migration = False
Expand All @@ -330,11 +328,6 @@ def test_live_migration_basic(self):
self.driver.compute_rpcapi.check_can_live_migrate_destination(
self.context, instance, dest, block_migration,
disk_over_commit).AndReturn({})
db.instance_update_and_get_original(self.context, instance_uuid,
{"task_state": task_states.MIGRATING}).AndReturn(
(instance, instance))
notifications.send_update(self.context, instance, instance,
service="scheduler")
self.driver.compute_rpcapi.live_migration(self.context,
host=instance['host'], instance=instance, dest=dest,
block_migration=block_migration, migrate_data={})
Expand All @@ -353,7 +346,6 @@ def test_live_migration_all_checks_pass(self):
self.mox.StubOutWithMock(db, 'instance_get_all_by_host')
self.mox.StubOutWithMock(rpc, 'call')
self.mox.StubOutWithMock(rpc, 'cast')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
self.mox.StubOutWithMock(self.driver.compute_rpcapi,
'live_migration')

Expand Down Expand Up @@ -398,10 +390,6 @@ def test_live_migration_all_checks_pass(self):
"version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
None).AndReturn({})

db.instance_update_and_get_original(self.context, instance_uuid,
{"task_state": task_states.MIGRATING}).AndReturn(
(instance, instance))

self.driver.compute_rpcapi.live_migration(self.context,
host=instance['host'], instance=instance, dest=dest,
block_migration=block_migration, migrate_data={})
Expand Down

0 comments on commit a3bdc16

Please sign in to comment.