diff options
| author | Renuka Apte <renuka.apte@citrix.com> | 2012-07-12 16:22:26 -0700 |
|---|---|---|
| committer | Renuka Apte <renuka.apte@citrix.com> | 2012-08-14 16:25:29 -0700 |
| commit | a7d0934a97ead360ecb378de7e29dbea513a6b30 (patch) | |
| tree | 93141a17267c124d032fb2ab3b75d7cdf92df9ac /nova/tests | |
| parent | 0eb53c035ab290c9574c1388bde59f7d05f64efc (diff) | |
xenapi: Support live migration without pools
Implement blueprint xenapi-live-block-migration.
Add ability to live migrate VMs to hosts that are not
a part of a host aggregate (block migration).
This requires XenServer 6.1/later, or XCP 1.6/later. As
of this change, we still do not support instances with
(nova/cinder) volumes attached. External kernels are also
not supported.
Change-Id: I5feb6756d78804aa37780a7d0cda1600f7060afe
Diffstat (limited to 'nova/tests')
| -rw-r--r-- | nova/tests/compute/test_rpcapi.py | 3 | ||||
| -rw-r--r-- | nova/tests/scheduler/test_scheduler.py | 9 | ||||
| -rw-r--r-- | nova/tests/test_xenapi.py | 141 | ||||
| -rw-r--r-- | nova/tests/xenapi/stubs.py | 16 |
4 files changed, 158 insertions, 11 deletions
diff --git a/nova/tests/compute/test_rpcapi.py b/nova/tests/compute/test_rpcapi.py index 619ec016d..e88cb2096 100644 --- a/nova/tests/compute/test_rpcapi.py +++ b/nova/tests/compute/test_rpcapi.py @@ -191,7 +191,8 @@ class ComputeRpcAPITestCase(test.TestCase): def test_live_migration(self): self._test_compute_api('live_migration', 'cast', instance=self.fake_instance, dest='dest', - block_migration='blockity_block', host='tsoh', version='1.40') + block_migration='blockity_block', host='tsoh', version='1.43', + migrate_data={}) def test_post_live_migration_at_destination(self): self._test_compute_api('post_live_migration_at_destination', 'call', diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index d21e206c0..c242bb62b 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -427,7 +427,8 @@ class SchedulerTestCase(test.TestCase): self.driver._live_migration_common_check(self.context, instance, dest) self.driver.compute_rpcapi.check_can_live_migrate_destination( - self.context, instance, dest, block_migration, disk_over_commit) + 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)) @@ -436,7 +437,7 @@ class SchedulerTestCase(test.TestCase): compute_rpcapi.ComputeAPI.live_migration(self.context, host=instance['host'], instance=instance, dest=dest, - block_migration=block_migration) + block_migration=block_migration, migrate_data={}) self.mox.ReplayAll() self.driver.schedule_live_migration(self.context, @@ -494,7 +495,7 @@ class SchedulerTestCase(test.TestCase): 'block_migration': block_migration, 'disk_over_commit': disk_over_commit}, "version": "1.10"}, - None) + None).AndReturn({}) db.instance_update_and_get_original(self.context, instance_uuid, {"task_state": task_states.MIGRATING}).AndReturn( @@ -502,7 +503,7 @@ class SchedulerTestCase(test.TestCase): compute_rpcapi.ComputeAPI.live_migration(self.context, host=instance['host'], instance=instance, dest=dest, - block_migration=block_migration) + block_migration=block_migration, migrate_data={}) self.mox.ReplayAll() result = self.driver.schedule_live_migration(self.context, diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 321065657..92d3000b3 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -2116,14 +2116,17 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase): 'Dom0IptablesFirewallDriver', host='host') db_fakes.stub_out_db_instance_api(self.stubs) - stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) self.context = context.get_admin_context() - self.conn = xenapi_conn.XenAPIDriver(False) + xenapi_fake.create_local_pifs() def test_live_migration_calls_vmops(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + def fake_live_migrate(context, instance_ref, dest, post_method, - recover_method, block_migration): + recover_method, block_migration, migrate_data): fake_live_migrate.called = True + self.stubs.Set(self.conn._vmops, "live_migrate", fake_live_migrate) self.conn.live_migration(None, None, None, None, None) @@ -2131,18 +2134,78 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase): def test_pre_live_migration(self): # ensure method is present + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) self.conn.pre_live_migration(None, None, None, None) def test_post_live_migration_at_destination(self): # ensure method is present + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) self.conn.post_live_migration_at_destination(None, None, None, None) - def test_check_can_live_migrate_raises_on_block_migrate(self): - self.assertRaises(NotImplementedError, + def test_check_can_live_migrate_destination_with_block_migration(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + expected = {'block_migration': True, + 'migrate_data': {'xenops': '', + 'host': '', + 'master': '', + 'session_id': '', + 'SM': ''} + } + fake_data = self.conn.check_can_live_migrate_destination(self.context, + {'host': 'host'}, True, False) + self.assertEqual(expected.keys(), fake_data.keys()) + self.assertEqual(expected['migrate_data'].keys(), + fake_data['migrate_data'].keys()) + + def test_check_can_live_migrate_destination_block_migration_fails(self): + stubs.stubout_session(self.stubs, + stubs.FakeSessionForFailedMigrateTests) + self.conn = xenapi_conn.XenAPIDriver(False) + self.assertRaises(exception.MigrationError, self.conn.check_can_live_migrate_destination, - None, None, True, None) + self.context, {'host': 'host'}, True, False) + + def test_check_can_live_migrate_source_with_block_migrate(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + + def fake_get_vm_opaque_ref(instance): + return "fake_vm" + + self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", + fake_get_vm_opaque_ref) + dest_check_data = {'block_migration': True, + 'migrate_data': {}} + self.assertNotRaises(None, + self.conn.check_can_live_migrate_source, + self.context, + {'host': 'host'}, + dest_check_data) + + def test_check_can_live_migrate_source_with_block_migrate_fails(self): + def fake_get_vm_opaque_ref(instance): + return "fake_vm" + stubs.stubout_session(self.stubs, + stubs.FakeSessionForFailedMigrateTests) + self.conn = xenapi_conn.XenAPIDriver(False) + self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", + fake_get_vm_opaque_ref) + + dest_check_data = {'block_migration': True, + 'migrate_data': {}} + self.assertRaises(exception.MigrationError, + self.conn.check_can_live_migrate_source, + self.context, + {'host': 'host'}, + dest_check_data) def test_check_can_live_migrate_works(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + class fake_aggregate: def __init__(self): self.metadetails = {"host": "test_host_uuid"} @@ -2157,6 +2220,9 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase): {'host': 'host'}, False, False) def test_check_can_live_migrate_fails(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + class fake_aggregate: def __init__(self): self.metadetails = {"dest_other": "test_host_uuid"} @@ -2172,6 +2238,9 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase): self.context, {'host': 'host'}, None, None) def test_live_migration(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + def fake_get_vm_opaque_ref(instance): return "fake_vm" self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", @@ -2191,6 +2260,9 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase): self.assertTrue(post_method.called, "post_method.called") def test_live_migration_on_failure(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + def fake_get_vm_opaque_ref(instance): return "fake_vm" self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", @@ -2214,6 +2286,63 @@ class XenAPILiveMigrateTestCase(stubs.XenAPITestBase): self.conn, None, None, None, recover_method) self.assertTrue(recover_method.called, "recover_method.called") + def test_live_migration_with_block_migration(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + + def fake_get_vm_opaque_ref(instance): + return "fake_vm" + self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", + fake_get_vm_opaque_ref) + + def post_method(context, instance, destination_hostname, + block_migration): + post_method.called = True + + # pass block_migration = True and migrate data + migrate_data = {"test": "data"} + self.conn.live_migration(self.conn, None, None, post_method, None, + True, migrate_data) + self.assertTrue(post_method.called, "post_method.called") + + def test_live_migration_with_block_migration_raises_invalid_param(self): + stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) + self.conn = xenapi_conn.XenAPIDriver(False) + + def fake_get_vm_opaque_ref(instance): + return "fake_vm" + self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", + fake_get_vm_opaque_ref) + + def recover_method(context, instance, destination_hostname, + block_migration): + recover_method.called = True + # pass block_migration = True and no migrate data + self.assertRaises(exception.InvalidParameterValue, + self.conn.live_migration, self.conn, + None, None, None, recover_method, True, None) + self.assertTrue(recover_method.called, "recover_method.called") + + def test_live_migration_with_block_migration_fails_migrate_send(self): + stubs.stubout_session(self.stubs, + stubs.FakeSessionForFailedMigrateTests) + self.conn = xenapi_conn.XenAPIDriver(False) + + def fake_get_vm_opaque_ref(instance): + return "fake_vm" + self.stubs.Set(self.conn._vmops, "_get_vm_opaque_ref", + fake_get_vm_opaque_ref) + + def recover_method(context, instance, destination_hostname, + block_migration): + recover_method.called = True + # pass block_migration = True and migrate data + migrate_data = {"test": "data"} + self.assertRaises(exception.MigrationError, + self.conn.live_migration, self.conn, + None, None, None, recover_method, True, migrate_data) + self.assertTrue(recover_method.called, "recover_method.called") + class XenAPIInjectMetadataTestCase(stubs.XenAPITestBase): def setUp(self): diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 4813bfa57..d9c1d510d 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -356,6 +356,22 @@ def stub_out_migration_methods(stubs): stubs.Set(vm_utils, 'generate_ephemeral', fake_generate_ephemeral) +class FakeSessionForFailedMigrateTests(FakeSessionForVMTests): + def __init__(self, uri): + super(FakeSessionForFailedMigrateTests, self).__init__(uri) + + def VM_assert_can_migrate(self, session, vmref, migrate_data, + live, vdi_map, vif_map, options): + raise fake.Failure("XenAPI VM.assert_can_migrate failed") + + def host_migrate_receive(self, session, hostref, networkref, options): + raise fake.Failure("XenAPI host.migrate_receive failed") + + def VM_migrate_send(self, session, vmref, migrate_data, islive, vdi_map, + vif_map, options): + raise fake.Failure("XenAPI VM.migrate_send failed") + + class XenAPITestBase(test.TestCase): def setUp(self): super(XenAPITestBase, self).setUp() |
