summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorRenuka Apte <renuka.apte@citrix.com>2012-07-12 16:22:26 -0700
committerRenuka Apte <renuka.apte@citrix.com>2012-08-14 16:25:29 -0700
commita7d0934a97ead360ecb378de7e29dbea513a6b30 (patch)
tree93141a17267c124d032fb2ab3b75d7cdf92df9ac /nova/tests
parent0eb53c035ab290c9574c1388bde59f7d05f64efc (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.py3
-rw-r--r--nova/tests/scheduler/test_scheduler.py9
-rw-r--r--nova/tests/test_xenapi.py141
-rw-r--r--nova/tests/xenapi/stubs.py16
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()