From 6c7c6a379b6e916d9237d2f2d9a38a144abc1a26 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Sun, 11 Dec 2016 15:21:56 +0800 Subject: [PATCH] Fix migrate data object error in live migrate Nova conductor live-migrate task utilize nova.objects.migrate_data objects to maintain parameters through the whole live migration process. The lagacy dict type of migrate data is no longer supported. Fix the un-supported migrate data error in this change. Change-Id: If04287726aec4be11432db7410b71b13c6291783 --- nova/tests/unit/virt/zvm/test_zvm.py | 93 ++------------------------ nova/virt/zvm/driver.py | 97 +++++++--------------------- test-requirements.txt | 1 + 3 files changed, 29 insertions(+), 162 deletions(-) diff --git a/nova/tests/unit/virt/zvm/test_zvm.py b/nova/tests/unit/virt/zvm/test_zvm.py index 70858d9..7af9d45 100644 --- a/nova/tests/unit/virt/zvm/test_zvm.py +++ b/nova/tests/unit/virt/zvm/test_zvm.py @@ -986,107 +986,22 @@ class ZVMDriverTestCases(ZVMTestCase): def test_live_migration_same_mn(self): dest = 'fhost2' - migrate_data = {'dest_host': dest, - 'pre_live_migration_result': - {'same_xcat_mn': True, - 'dest_diff_mn_key': None}} info = ["os000001: VMRELOCATE action=move against OS000001... Done\n"] - self._set_fake_xcat_responses([self._generate_xcat_resp(info)]) + self._set_fake_xcat_responses([self._generate_xcat_resp(info), + self._generate_xcat_resp(info)]) self.driver.live_migration(self.context, self.instance, dest, self._fake_fun(), self._fake_fun(), None, - migrate_data) - self.mox.VerifyAll() - - def test_live_migration_diff_mn(self): - dest = 'fhost2' - migrate_data = {'dest_host': dest, - 'pre_live_migration_result': - {'same_xcat_mn': False, - 'dest_diff_mn_key': 'sshkey'}} - info = ["os000001: VMRELOCATE action=move against OS000001... Done\n"] - self.stubs.Set(zvmutils, "xdsh", self._fake_fun()) - self.stubs.Set(self.driver._networkop, 'clean_mac_switch_host', - self._fake_fun()) - self.stubs.Set(instance.ZVMInstance, 'delete_xcat_node', - self._fake_fun()) - self._set_fake_xcat_resp([("PUT", None, None, - self._gen_resp(info=info))]) - self.driver.live_migration(self.context, self.instance, dest, - self._fake_fun(), self._fake_fun(), None, - migrate_data) + None) self.mox.VerifyAll() def test_live_migration_failed(self): dest = 'fhost2' - migrate_data = {'dest_host': dest, - 'pre_live_migration_result': - {'same_xcat_mn': True, - 'dest_diff_mn_key': None}} info = ["os000001: VMRELOCATE MOVE error\n"] self._set_fake_xcat_responses([self._gen_resp(info=info, error=['error'])]) - self.stubs.Set(zvmutils, "xdsh", self._fake_fun()) self.assertRaises(nova_exception.MigrationError, self.driver.live_migration, self.context, self.instance, dest, - self._fake_fun(), self._fake_fun(), None, migrate_data) - self.mox.VerifyAll() - - def test_check_can_live_migrate_destination(self): - dest = 'fhost2' - dest_info = {'hypervisor_hostname': dest} - res_dict = self.driver.check_can_live_migrate_destination(self.context, - self.instance, {}, dest_info, {}, {}) - exp_dict = {'dest_host': dest, - 'is_shared_storage': True} - self.assertEqual(res_dict.get('migrate_data', None), exp_dict) - - def test_check_can_live_migrate_source(self): - dest = 'fhost2' - migrate_data = {'dest_host': dest, - 'is_shared_storage': True} - dest_check_data = {'migrate_data': migrate_data} - info = ["os000001: VMRELOCATE action=test against OS000001... Done\n"] - self._set_fake_xcat_resp([ - ("GET", None, None, self._gen_resp(info=["userid=os000001"])), - ("PUT", None, None, self._gen_resp(info=info))]) - res_dict = self.driver.check_can_live_migrate_source( - self.context, self.instance, dest_check_data) - self.assertNotEqual(res_dict.get('dest_host', None), None) - self.mox.ReplayAll() - - def test_check_can_live_migrate_source_failed(self): - dest = 'fhost2' - migrate_data = {'dest_host': dest} - dest_check_data = {'migrate_data': migrate_data} - error = ["VMRELOCATE move failed"] - - self.mox.StubOutWithMock(zvmutils, "get_userid") - self.mox.StubOutWithMock(self.driver, "_vmrelocate") - zvmutils.get_userid('os000001').AndReturn("os000001") - self.driver._vmrelocate('fhost2', 'os000001', 'test').AndRaise( - nova_exception.MigrationError(reason=error)) - self.mox.ReplayAll() - - self.assertRaises(nova_exception.MigrationError, - self.driver.check_can_live_migrate_source, self.context, - self.instance, dest_check_data) - self.mox.VerifyAll() - - def test_check_can_live_migrate_source_force(self): - self.flags(zvm_vmrelocate_force='domain') - dest = 'fhost2' - migrate_data = {'dest_host': dest} - dest_check_data = {'migrate_data': migrate_data} - - self.mox.StubOutWithMock(zvmutils, "get_userid") - self.mox.StubOutWithMock(self.driver, "_vmrelocate") - zvmutils.get_userid('os000001').AndReturn("os000001") - self.driver._vmrelocate('fhost2', 'os000001', 'test').AndRaise( - nova_exception.MigrationError(reason="1944")) - self.mox.ReplayAll() - - self.driver.check_can_live_migrate_source(self.context, self.instance, - dest_check_data) + self._fake_fun(), self._fake_fun(), None, None) self.mox.VerifyAll() def test_migrate_disk_and_power_off(self): diff --git a/nova/virt/zvm/driver.py b/nova/virt/zvm/driver.py index 8bd2612..211a8af 100644 --- a/nova/virt/zvm/driver.py +++ b/nova/virt/zvm/driver.py @@ -39,6 +39,7 @@ from nova import exception as nova_exception from nova.i18n import _, _LI, _LW from nova.image import api as image_api from nova.image import glance +from nova.objects import migrate_data as migrate_data_obj from nova import utils from nova.virt import configdrive from nova.virt import driver @@ -992,14 +993,7 @@ class ZVMDriver(driver.ComputeDriver): :param block_migration: if true, prepare for block migration :param disk_over_commit: if true, allow disk over commit """ - # For z/VM, all live migration check will be done in - # check_can_live_migration_source, so just return a dst_compute_info. - # And we only support shared storage live migration. - migrate_data = {'dest_host': dst_compute_info['hypervisor_hostname'], - 'is_shared_storage': True} - dest_check_data = {'migrate_data': migrate_data} - - return dest_check_data + return migrate_data_obj.LibvirtLiveMigrateData() def check_can_live_migrate_source(self, ctxt, instance_ref, dest_check_data, block_device_info=None): @@ -1013,43 +1007,10 @@ class ZVMDriver(driver.ComputeDriver): :param dest_check_data: result of check_can_live_migrate_destination """ - LOG.info(_LI("Checking source host for live-migration for %s") % - instance_ref['name'], instance=instance_ref) + return migrate_data_obj.LibvirtLiveMigrateData() - migrate_data = dest_check_data.get('migrate_data', {}) - dest_host = migrate_data.get('dest_host', None) - userid = zvmutils.get_userid(instance_ref['name']) - migrate_data.update({'source_xcat_mn': CONF.zvm_xcat_server, - 'zvm_userid': userid}) - - if dest_host is not None: - try: - self._vmrelocate(dest_host, instance_ref['name'], 'test') - except nova_exception.MigrationError as err: - emsg = err.format_message() - if isinstance(CONF.zvm_vmrelocate_force, str): - force = CONF.zvm_vmrelocate_force.lower() - if ('domain' in force) or ('architecture' in force): - if '1944' in emsg: - # force domain/architecture in effect, ignore - return migrate_data - LOG.error(_("Live-migrating check failed: %s") % emsg, - instance=instance_ref) - raise nova_exception.MigrationPreCheckError(reason=emsg) - - return migrate_data - else: - reason = _("Invalid migration data") - raise nova_exception.MigrationPreCheckError(reason=reason) - - def check_can_live_migrate_destination_cleanup(self, ctxt, + def cleanup_live_migration_destination_check(self, ctxt, dest_check_data): - """Do required cleanup on dest host after check_can_live_migrate calls - - :param ctxt: security context - :param dest_check_data: result of check_can_live_migrate_destination - - """ # For z/VM, nothing needed to be cleanup return @@ -1070,16 +1031,6 @@ class ZVMDriver(driver.ComputeDriver): raise nova_exception.MigrationError(reason=msg) zvm_inst = ZVMInstance(self, instance_ref) - source_xcat_mn = migrate_data.get('source_xcat_mn', '') - userid = migrate_data.get('zvm_userid') - hcp = self._get_hcp_info()['hostname'] - same_xcat_mn = source_xcat_mn == CONF.zvm_xcat_server - dest_diff_mn_key = None - - if not same_xcat_mn: - # The two z/VM system managed by two different xCAT MN - zvm_inst.create_xcat_node(hcp, userid) - dest_diff_mn_key = zvmutils.get_mn_pub_key() if network_info is not None: network = network_info[0]['network'] ip_addr = network['subnets'][0]['ips'][0]['address'] @@ -1087,8 +1038,7 @@ class ZVMDriver(driver.ComputeDriver): zvm_inst._name) self._networkop.makehosts() - return {'same_xcat_mn': same_xcat_mn, - 'dest_diff_mn_key': dest_diff_mn_key} + return def pre_block_migration(self, ctxt, instance_ref, disk_info): """Prepare a block device for migration @@ -1122,21 +1072,28 @@ class ZVMDriver(driver.ComputeDriver): """ inst_name = instance_ref['name'] - dest_host = migrate_data['dest_host'] + + # Test can live migrate or not + force = CONF.zvm_vmrelocate_force + try: + self._vmrelocate(dest, inst_name, 'test') + except nova_exception.MigrationError as err: + emsg = err.format_message() + if (force and ('domain' in force.lower() or + 'architecture' in force.lower()) and ('1944' in emsg)): + LOG.debug("Ignore VMRELOCATE 1944 error") + else: + LOG.error(_("Live-migrating check failed: %s") % emsg, + instance=instance_ref) + with excutils.save_and_reraise_exception(): + recover_method(ctxt, instance_ref, dest, + block_migration, migrate_data) + LOG.info(_LI("Live-migrating %(inst)s to %(dest)s") % - {'inst': inst_name, 'dest': dest_host}, instance=instance_ref) - - same_mn = migrate_data['pre_live_migration_result']['same_xcat_mn'] - dest_diff_mn_key = migrate_data['pre_live_migration_result'].get( - 'dest_diff_mn_key', None) - - if not same_mn and dest_diff_mn_key: - auth_command = ('echo "%s" >> /root/.ssh/authorized_keys' % - dest_diff_mn_key) - zvmutils.xdsh(inst_name, auth_command) + {'inst': inst_name, 'dest': dest}, instance=instance_ref) try: - self._vmrelocate(dest_host, inst_name, 'move') + self._vmrelocate(dest, inst_name, 'move') except nova_exception.MigrationError as err: LOG.error(_("Live-migration failed: %s") % err.format_message(), instance=instance_ref) @@ -1144,12 +1101,6 @@ class ZVMDriver(driver.ComputeDriver): recover_method(ctxt, instance_ref, dest, block_migration, migrate_data) - if not same_mn: - # Delete node definition at source xCAT MN - zvm_inst = ZVMInstance(self, instance_ref) - self._networkop.clean_mac_switch_host(zvm_inst._name) - zvm_inst.delete_xcat_node() - post_method(ctxt, instance_ref, dest, block_migration, migrate_data) diff --git a/test-requirements.txt b/test-requirements.txt index 21fdf43..88d195d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -14,3 +14,4 @@ testscenarios>=0.4 testtools>=1.4.0 mock>=1.2 mox>=0.5.3 +vine