summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJian Wen <wenjianhn@gmail.com>2012-09-12 17:45:03 +0800
committerJian Wen <wenjianhn@gmail.com>2012-09-13 01:03:10 +0800
commita3bdc1624fd557e0699acb049b1ca0c1ef894c2f (patch)
tree396ca5f8dfb8baf9a4e52a17385f193c383a29f3
parentb961bd4c2916559bca856bc8b142d9df7494ef13 (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.py4
-rw-r--r--nova/scheduler/driver.py11
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_admin_actions.py7
-rw-r--r--nova/tests/compute/test_compute.py17
-rw-r--r--nova/tests/scheduler/test_scheduler.py12
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={})