diff options
| author | Jian Wen <wenjianhn@gmail.com> | 2012-09-12 17:45:03 +0800 |
|---|---|---|
| committer | Jian Wen <wenjianhn@gmail.com> | 2012-09-13 01:03:10 +0800 |
| commit | a3bdc1624fd557e0699acb049b1ca0c1ef894c2f (patch) | |
| tree | 396ca5f8dfb8baf9a4e52a17385f193c383a29f3 | |
| parent | b961bd4c2916559bca856bc8b142d9df7494ef13 (diff) | |
Avoid live migrate overwriting the other task_state
As commit 4082c8375a6ae7e7e67c7ad2e263be2d5fc3dd1f 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
| -rw-r--r-- | nova/compute/api.py | 4 | ||||
| -rw-r--r-- | nova/scheduler/driver.py | 11 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/contrib/test_admin_actions.py | 7 | ||||
| -rw-r--r-- | nova/tests/compute/test_compute.py | 17 | ||||
| -rw-r--r-- | nova/tests/scheduler/test_scheduler.py | 12 |
5 files changed, 29 insertions, 22 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py index a9ab17a13..3ad6a6305 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1941,6 +1941,10 @@ class API(base.Base): 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) diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index 3bc695623..705cb8636 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -203,19 +203,10 @@ class Scheduler(object): 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) diff --git a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py index 6e075e974..fbd81d283 100644 --- a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py +++ b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py @@ -139,6 +139,13 @@ class AdminActionsTest(test.TestCase): } }) 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) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 27fd90146..34cdf70c4 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -80,6 +80,10 @@ class FakeSchedulerAPI(object): filter_properties): pass + def live_migration(self, ctxt, block_migration, disk_over_commit, + instance, dest): + pass + class BaseTestCase(test.TestCase): @@ -4449,6 +4453,19 @@ class ComputeAPITestCase(BaseTestCase): 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 diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index c5276819e..2e732546c 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -311,10 +311,8 @@ class SchedulerTestCase(test.TestCase): 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 @@ -330,11 +328,6 @@ class SchedulerTestCase(test.TestCase): 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={}) @@ -353,7 +346,6 @@ class SchedulerTestCase(test.TestCase): 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') @@ -398,10 +390,6 @@ class SchedulerTestCase(test.TestCase): "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={}) |
