[PATCH 0 of 4] [TEST][RFC] Added new tc to verify remote live migration.

Verified with KVM. The test case will not pass for KVM since the guest information needs to have emulator information without which the remote migration fails. The support to pass the emulator information via VirtualSystemMigrationSettingData is not yet available. As a workaround for verification of the tc. ------------------------------------------- 1) create a KVM VM which has the emulator information outside the tc on the comman line. 2) comment out the setup_guest() call. 3) specify the name of the guest create in test_dom before calling local_remote_migrate(). Signed-off-by: Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com>

# HG changeset patch # User Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1236853111 25200 # Node ID 873ac33542e0a2cfc49a7f1ca89c0190bafe58cd # Parent 676a8b05baa09b69052d519c7b438b301bea849c [TEST] Adding option to main.py to accept target machine info for Migration Tests. Signed-off-by: Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> diff -r 676a8b05baa0 -r 873ac33542e0 suites/libvirt-cim/main.py --- a/suites/libvirt-cim/main.py Tue Mar 10 22:27:59 2009 -0700 +++ b/suites/libvirt-cim/main.py Thu Mar 12 03:18:31 2009 -0700 @@ -44,6 +44,8 @@ parser = OptionParser() parser.add_option("-i", "--ip", dest="ip", default="localhost", help="IP address of machine to test (default: localhost)") +parser.add_option("-m", "--target_url", dest="t_url", default="localhost:5988", + help="URL of destination host for remote migration ") parser.add_option("-p", "--port", dest="port", type="int", default=5988, help="CIMOM port (default: 5988)") parser.add_option("-g", "--group", dest="group", @@ -199,6 +201,21 @@ # with a different port if options.port: os.environ['CIMOM_PORT'] = str(options.port) + + if ":" in options.ip: + (s_sysname, port) = options.ip.split(":") + else: + s_sysname = options.ip + + if ":" in options.t_url: + (t_sysname, port) = options.t_url.split(":") + else: + t_sysname = options.t_url + + # HACK: To be able to use the src and target host + # comparison for remote migration + os.environ['SRC_IP'] = str(s_sysname) + os.environ['TARGET_IP'] = str(t_sysname) if options.report: to_addr = options.report

# HG changeset patch # User Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1236853346 25200 # Node ID 555e0df8d5ac2d5a42a4f6d839e35194cf98a2d6 # Parent 873ac33542e0a2cfc49a7f1ca89c0190bafe58cd [TEST]Modifying emulator information to be used for KVM. Signed-off-by: Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> diff -r 873ac33542e0 -r 555e0df8d5ac suites/libvirt-cim/lib/XenKvmLib/const.py --- a/suites/libvirt-cim/lib/XenKvmLib/const.py Thu Mar 12 03:18:31 2009 -0700 +++ b/suites/libvirt-cim/lib/XenKvmLib/const.py Thu Mar 12 03:22:26 2009 -0700 @@ -82,10 +82,12 @@ Xen_default_mac = '11:22:33:aa:bb:cc' # vxml.KVMXML -if fv_cap(CIM_IP): - KVM_default_emulator = '/usr/bin/qemu-kvm' -else: - KVM_default_emulator = '/usr/bin/qemu' +KVM_default_emulator = '/usr/local/bin/qemu-system-x86_64' +if not os.path.exists(KVM_default_emulator): + if fv_cap(CIM_IP): + KVM_default_emulator = '/usr/bin/qemu-kvm' + else: + KVM_default_emulator = '/usr/bin/qemu' KVM_disk_path = os.path.join(_image_dir, 'default-kvm-dimage') KVM_secondary_disk_path = os.path.join(_image_dir, 'default-kvm-dimage.2ND') KVM_default_disk_dev = 'hda'

# HG changeset patch # User Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1236853527 25200 # Node ID caae383c83ec70e6cb6de9b6e5ccf6d2fcbecb45 # Parent 555e0df8d5ac2d5a42a4f6d839e35194cf98a2d6 [TEST] Adding support for remote migration in the vsmigrations library. Signed-off-by: Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> diff -r 555e0df8d5ac -r caae383c83ec suites/libvirt-cim/lib/XenKvmLib/vsmigrations.py --- a/suites/libvirt-cim/lib/XenKvmLib/vsmigrations.py Thu Mar 12 03:22:26 2009 -0700 +++ b/suites/libvirt-cim/lib/XenKvmLib/vsmigrations.py Thu Mar 12 03:25:27 2009 -0700 @@ -3,6 +3,7 @@ # # Authors: # Guolian Yun <yunguol@cn.ibm.com> +# Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public @@ -18,34 +19,59 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -import pywbem -import time +# + +from time import sleep +from pywbem import WBEMConnection, CIMInstanceName from CimTest.CimExt import CIMMethodClass, CIMClassMOF -from CimTest.Globals import logger, CIM_USER, CIM_PASS, CIM_NS from CimTest.ReturnCodes import PASS, FAIL -from XenKvmLib.test_doms import destroy_and_undefine_domain -from CimTest.Globals import logger, CIM_ERROR_ENUMERATE from XenKvmLib import enumclass -from XenKvmLib.classes import get_typed_class +from XenKvmLib.classes import get_typed_class, virt_types from XenKvmLib.xm_virt_util import domain_list from XenKvmLib.const import get_provider_version +from CimTest.Globals import logger, CIM_USER, CIM_PASS, CIM_NS, \ + CIM_ERROR_ENUMERATE +# Migration constants +CIM_MIGRATE_OFFLINE=1 +CIM_MIGRATE_LIVE=2 +CIM_MIGRATE_RESUME=3 +CIM_MIGRATE_RESTART=4 + +CIM_JOBSTATE_STARTING=3 +CIM_JOBSTATE_COMPLETE=7 +CIM_JOBSTATE_RUNNING=4 libvirt_mig_changes = 668 +def eval_cls(basename): + def func(f): + def body(virt): + if virt in virt_types: + return eval(get_typed_class(virt, basename)) + return body + return func + + class CIM_VirtualSystemMigrationService(CIMMethodClass): conn = None inst = None - def __init__(self, server, hyp): - self.conn = pywbem.WBEMConnection('http://%s' % server, - (CIM_USER, CIM_PASS), CIM_NS) + def __init__(self, server, virt='Xen'): + self.conn = WBEMConnection('http://%s' % server, + (CIM_USER, CIM_PASS), CIM_NS) - self.inst = hyp + '_VirtualSystemMigrationService' + self.inst = get_typed_class(virt, 'VirtualSystemMigrationService') +@eval_cls('VirtualSystemMigrationService') +def get_vs_mig_setting_class(virt): + pass + class Xen_VirtualSystemMigrationService(CIM_VirtualSystemMigrationService): - def __init__(self, server): - CIM_VirtualSystemMigrationService.__init__(self, server, 'Xen') + pass + +class KVM_VirtualSystemMigrationService(CIM_VirtualSystemMigrationService): + pass # classes to define VirtualSystemMigrationSettingData parameters class CIM_VirtualSystemMigrationSettingData(CIMClassMOF): @@ -56,118 +82,233 @@ self.Priority = priority class Xen_VirtualSystemMigrationSettingData(CIM_VirtualSystemMigrationSettingData): - def __init__(self, type, priority): - CIM_VirtualSystemMigrationSettingData.__init__(self, type, - priority) + pass class KVM_VirtualSystemMigrationSettingData(CIM_VirtualSystemMigrationSettingData): - def __init__(self, type, priority): - CIM_VirtualSystemMigrationSettingData.__init__(self, type, - priority) + pass +def get_msd(virt, mtype='live', mpriority=0): + if mtype == "live": + mtype = CIM_MIGRATE_LIVE + elif mtype == "resume": + mtype = CIM_MIGRATE_RESUME + elif mtype == "restart": + mtype = CIM_MIGRATE_RESTART + elif mtype == "offline": + mtype = CIM_MIGRATE_OFFLINE + else: + logger.error("Invalid migration type '%s' specified", mtype) + return None + try: + vsmsd_cn = get_typed_class(virt, "VirtualSystemMigrationSettingData") + msd = eval(vsmsd_cn)(type=mtype, priority=mpriority) + except Exception, details: + logger.error("In get_msd() Exception details: %s", details) + return None + + return msd.mof() + +def get_guest_ref(guest, virt): + guest_cn = get_typed_class(virt, "ComputerSystem") + keys = { 'Name' : guest, 'CreationClassName' : guest_cn } + cs_ref = None + + try: + cs_ref = CIMInstanceName(guest_cn, keybindings=keys) + + except Exception, details: + logger.error("In fn get_guest_ref() Exception details: %s", details) + return None + + return cs_ref + +#Remove this once vsms.02_host_migrate_type.py uses get_msd() def default_msd_str(mtype=3, mpriority=0): msd = Xen_VirtualSystemMigrationSettingData(type=mtype, priority=mpriority) return msd.mof() -def check_possible_host_migration(service, cs_ref, ip): - rc = None +def check_possible_host_migration(service, cs_ref, ip, msd=None): + res = None try: - rc = service.CheckVirtualSystemIsMigratableToHost(ComputerSystem=cs_ref, - DestinationHost=ip) + checkfn_name = 'service.CheckVirtualSystemIsMigratableToHost' + if msd == None: + res = eval(checkfn_name)(ComputerSystem=cs_ref, DestinationHost=ip) + else: + res = eval(checkfn_name)(ComputerSystem=cs_ref, + DestinationHost=ip, + MigrationSettingData=msd) except Exception, details: - logger.error("Error invoke 'CheckVirtualSystemIsMigratableToHost\'.") + logger.error("Error invoke 'CheckVirtualSystemIsMigratableToHost'.") logger.error("%s", details) return FAIL - if rc == None or rc[1]['IsMigratable'] != True: + if res == None or res[1]['IsMigratable'] != True: + logger.error("Migration check failed") return FAIL return PASS -def migrate_guest_to_host(service, ref, ip, msd=None): + +def migrate_guest_to_host(service, cs_ref, dest_ip, msd=None): ret = [] try: if msd == None: - ret = service.MigrateVirtualSystemToHost(ComputerSystem=ref, - DestinationHost=ip) + ret = service.MigrateVirtualSystemToHost(ComputerSystem=cs_ref, + DestinationHost=dest_ip) else: - ret = service.MigrateVirtualSystemToHost(ComputerSystem=ref, - DestinationHost=ip, + ret = service.MigrateVirtualSystemToHost(ComputerSystem=cs_ref, + DestinationHost=dest_ip, MigrationSettingData=msd) except Exception, details: - logger.error("Error invoke method 'MigrateVirtualSystemToHost\'.") - logger.error("%s", details) + logger.error("Failed to invoke method 'MigrateVirtualSystemToHost'.") + logger.error("Exception in fn migrate_guest_to_host() %s", details) return FAIL, ret if len(ret) == 0: logger.error("MigrateVirtualSystemToHost returns an empty list") return FAIL, ret + return PASS, ret -def get_migration_job_instance(ip, virt, id): +def get_migration_job_instance(src_ip, virt, id): job = [] - key_list = ["instanceid"] - curr_cim_rev, changeset = get_provider_version(virt, ip) + curr_cim_rev, changeset = get_provider_version(virt, src_ip) if curr_cim_rev < libvirt_mig_changes: mig_job_cn = 'Virt_MigrationJob' else: mig_job_cn = get_typed_class(virt, 'MigrationJob') try: - job = enumclass.EnumInstances(ip, mig_job_cn) + job = enumclass.EnumInstances(src_ip, mig_job_cn) + if len(job) < 1: + return FAIL, None + + for i in range(0, len(job)): + if job[i].InstanceID == id: + break + elif i == len(job)-1 and job[i].InstanceID != id: + logger.error("%s err: can't find expected job inst", mig_job_cn) + return FAIL, None except Exception, details: logger.error(CIM_ERROR_ENUMERATE, mig_job_cn) - logger.error(details) + logger.error("Exception in fn get_migration_job_instance() " \ + "details: %s", details) return FAIL, None - if len(job) < 1: - return FAIL, None - - for i in range(0, len(job)): - if job[i].InstanceID == id: - break - elif i == len(job)-1 and job[i].InstanceID != id: - logger.error("%s err: can't find expected job inst", mig_job_cn) - return FAIL, None - return PASS, job[i] -def verify_domain_list(list, local_migrate, test_dom): - status = PASS - if local_migrate == 0 and test_dom not in list: - status = FAIL - if local_migrate == 1 and test_dom in list: +def verify_domain_list(remote_migrate, test_dom, src_ip, target_ip): + status = FAIL + list_src = domain_list(src_ip) + if remote_migrate == 0: + if test_dom in list_src: + status = PASS + elif remote_migrate == 1 : + list_target = domain_list(target_ip) + if test_dom not in list_src and test_dom in list_target: + status = PASS + else: + logger.error("Invalid migration option") + + if status != PASS: + logger.error("Migration verification for '%s' failed", test_dom) + return status + + return status + +def check_migration_job(src_ip, id, target_ip, test_dom, + remote_migrate, virt='Xen', timeout=50): + try: + status, job_inst = get_migration_job_instance(src_ip, virt, id) + if status != PASS: + logger.error("Unable to get mig_job instance for '%s'", test_dom) + return FAIL + status = FAIL - if status != PASS: - logger.error("%s migrate failed", test_dom) + for i in range(0, timeout): + if job_inst.JobState == CIM_JOBSTATE_COMPLETE: + sleep(3) + if job_inst.Status != "Completed": + logger.error("Failed to set the status for the migrated " \ + "dom: '%s'", test_dom) + return FAIL + else: + status = verify_domain_list(remote_migrate, test_dom, + src_ip, target_ip) + if status != FAIL: + logger.info("Migration job status is : %s", + job_inst.Status) + logger.info("Migration for '%s' succeeded.", test_dom) + return status + elif job_inst.JobState == CIM_JOBSTATE_RUNNING and i < (timeout-1): + sleep(3) + status, job_inst = get_migration_job_instance(src_ip, virt, id) + if status != PASS: + logger.error("Could not get mig_job instance for '%s'", + test_dom) + return status + else: + logger.error("Migration timed out.... ") + logger.error("Increase timeout > %s and try again..", timeout) + return FAIL + + except Exception, details: + logger.error("In check_migration_job() Exception details: %s", details) + return FAIL +# +# This fn executes local/remote migration depending on the +# value of remote_migrate. +# Parameters used: +# vsmservice = VSMigrationService Instance +# s_sysname = src host on which migration is initiated +# t_sysname = Target machine for migration +# virt = Xen, KVM +# remote_migrate = 1 [for remote migration, 0 for local] +# mtype = live/resume/offline/restart +# mpriority=0 by default +# guest_name = name of the guest to be migrated +# time_out = time for which migration is tried. +# +def local_remote_migrate(vsmservice, s_sysname, t_sysname, virt='KVM', + remote_migrate=1, mtype='live', mpriority=0, + guest_name=None, time_out=40): + + if guest_name == None: + logger.error("Guest to be migrated not specified.") + return FAIL + + # Get the guest ref + guest_ref = get_guest_ref(guest_name, virt) + if guest_ref == None or guest_ref['Name'] != guest_name: + logger.error("Failed to get the guest refernce to be migrated") + return FAIL + + # Get MigrationSettingData information + msd = get_msd(virt, mtype, mpriority) + if msd == None: return FAIL - return PASS - -def check_migration_job(ip, id, target_ip, test_dom, local_migrate, virt='Xen'): - status, job_inst = get_migration_job_instance(ip, virt, id) + # Verify is destination(t_sysname) can be used for migration + status = check_possible_host_migration(vsmservice, guest_ref, + t_sysname, msd) if status != PASS: return FAIL - for i in range(0, 50): - if job_inst.JobState == 7: - if job_inst.Status != "Completed": - logger.error("%s migrate failed", test_dom) - return FAIL - list_after = domain_list(ip) - status = verify_domain_list(list_after, local_migrate, test_dom) - break - elif job_inst.JobState == 4 and i < 49: - time.sleep(3) - status, job_inst = get_migration_job_instance(ip, virt, id) - if status != PASS: - return FAIL - else: - logger.error("MigrateVirtualSystemToHost took too long") - return FAIL + logger.info("Migrating %s.. this will take some time.", guest_name) + # Migrate the guest to t_sysname + status, ret = migrate_guest_to_host(vsmservice, guest_ref, t_sysname, msd) + if status == FAIL: + logger.error("Failed to Migrate guest '%s' from '%s' to '%s'", + guest_name, s_sysname, t_sysname) + return status + elif len(ret) == 2: + id = ret[1]['Job'].keybindings['InstanceID'] - return PASS + # Verify if migration status + status = check_migration_job(s_sysname, id, t_sysname, guest_name, + remote_migrate, virt, timeout=time_out) + return status

-def get_migration_job_instance(ip, virt, id): +def get_migration_job_instance(src_ip, virt, id): job = [] - key_list = ["instanceid"] - curr_cim_rev, changeset = get_provider_version(virt, ip) + curr_cim_rev, changeset = get_provider_version(virt, src_ip) if curr_cim_rev < libvirt_mig_changes: mig_job_cn = 'Virt_MigrationJob' else: mig_job_cn = get_typed_class(virt, 'MigrationJob')
try: - job = enumclass.EnumInstances(ip, mig_job_cn) + job = enumclass.EnumInstances(src_ip, mig_job_cn) + if len(job) < 1:
Can you print an error here indicating that no job instances were returned?
-def verify_domain_list(list, local_migrate, test_dom): - status = PASS - if local_migrate == 0 and test_dom not in list: - status = FAIL - if local_migrate == 1 and test_dom in list: +def verify_domain_list(remote_migrate, test_dom, src_ip, target_ip): + status = FAIL + list_src = domain_list(src_ip) + if remote_migrate == 0: + if test_dom in list_src: + status = PASS + elif remote_migrate == 1 : + list_target = domain_list(target_ip)
The verification fails for me when migrating a KVM guest. Here's the error message I see: VirtualSystemMigrationService - 06_remote_migration.py: FAIL ERROR - Migration verification for 'f10_test' failed You'll need to specify the virtualization type - otherwise, it calls domain_list() for Xen hyp. Here's what I see when I print the contents of the list_src and list_target: ['Xen', 'Xen', 'failed']
+ if test_dom not in list_src and test_dom in list_target: + status = PASS + else: + logger.error("Invalid migration option") + + if status != PASS: + logger.error("Migration verification for '%s' failed", test_dom) + return status + + return status + +def check_migration_job(src_ip, id, target_ip, test_dom, + remote_migrate, virt='Xen', timeout=50): + try: + status, job_inst = get_migration_job_instance(src_ip, virt, id) + if status != PASS: + logger.error("Unable to get mig_job instance for '%s'", test_dom) + return FAIL + status = FAIL
- if status != PASS: - logger.error("%s migrate failed", test_dom) + for i in range(0, timeout): + if job_inst.JobState == CIM_JOBSTATE_COMPLETE: + sleep(3) + if job_inst.Status != "Completed": + logger.error("Failed to set the status for the migrated " \ + "dom: '%s'", test_dom)
Can you also print the job_inst.Status as well? Right now, libvirt doesn't print much when a migration fails, but it might print more info in the future. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

Kaitlin Rupert wrote:
-def get_migration_job_instance(ip, virt, id): +def get_migration_job_instance(src_ip, virt, id): job = [] - key_list = ["instanceid"] - curr_cim_rev, changeset = get_provider_version(virt, ip) + curr_cim_rev, changeset = get_provider_version(virt, src_ip) if curr_cim_rev < libvirt_mig_changes: mig_job_cn = 'Virt_MigrationJob' else: mig_job_cn = get_typed_class(virt, 'MigrationJob')
try: - job = enumclass.EnumInstances(ip, mig_job_cn) + job = enumclass.EnumInstances(src_ip, mig_job_cn) + if len(job) < 1:
Can you print an error here indicating that no job instances were returned?
-def verify_domain_list(list, local_migrate, test_dom): - status = PASS - if local_migrate == 0 and test_dom not in list: - status = FAIL - if local_migrate == 1 and test_dom in list: +def verify_domain_list(remote_migrate, test_dom, src_ip, target_ip): + status = FAIL + list_src = domain_list(src_ip) + if remote_migrate == 0: + if test_dom in list_src: + status = PASS + elif remote_migrate == 1 : + list_target = domain_list(target_ip)
The verification fails for me when migrating a KVM guest. Here's the error message I see:
VirtualSystemMigrationService - 06_remote_migration.py: FAIL ERROR - Migration verification for 'f10_test' failed
You'll need to specify the virtualization type - otherwise, it calls domain_list() for Xen hyp. Here's what I see when I print the contents of the list_src and list_target:
['Xen', 'Xen', 'failed']
+ if test_dom not in list_src and test_dom in list_target: + status = PASS + else: + logger.error("Invalid migration option") + + if status != PASS: + logger.error("Migration verification for '%s' failed", test_dom) + return status + + return status + +def check_migration_job(src_ip, id, target_ip, test_dom, + remote_migrate, virt='Xen', timeout=50): + try: + status, job_inst = get_migration_job_instance(src_ip, virt, id) + if status != PASS: + logger.error("Unable to get mig_job instance for '%s'", test_dom) + return FAIL + status = FAIL
- if status != PASS: - logger.error("%s migrate failed", test_dom) + for i in range(0, timeout): + if job_inst.JobState == CIM_JOBSTATE_COMPLETE: + sleep(3) + if job_inst.Status != "Completed": + logger.error("Failed to set the status for the migrated " \ + "dom: '%s'", test_dom)
Can you also print the job_inst.Status as well? Right now, libvirt doesn't print much when a migration fails, but it might print more info in the future.
I shall take care of these. -- Thanks and Regards, Deepti B. Kalakeri IBM Linux Technology Center deeptik@linux.vnet.ibm.com

# HG changeset patch # User Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1236853868 25200 # Node ID 89db4ac2378c90fd89845dd09836bfb39cc6e6ed # Parent caae383c83ec70e6cb6de9b6e5ccf6d2fcbecb45 [TEST][RFC] Added new tc to verify remote live migration. Verified with KVM. The test case will not pass for KVM since the guest information needs to have emulator information without which the remote migration fails. The support to pass the emulator information via VirtualSystemMigrationSettingData is not yet available. Signed-off-by: Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> diff -r caae383c83ec -r 89db4ac2378c suites/libvirt-cim/cimtest/VirtualSystemMigrationService/06_remote_migration.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/suites/libvirt-cim/cimtest/VirtualSystemMigrationService/06_remote_migration.py Thu Mar 12 03:31:08 2009 -0700 @@ -0,0 +1,111 @@ +#!/usr/bin/python +# +# Copyright 2008 IBM Corp. +# +# Authors: +# Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> +# +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# This testcase is used to verify the live remote migration. +# +# Date : 12-03-09 +# + +import sys +import os +import time +import socket +from XenKvmLib import vxml +from XenKvmLib.common_util import poll_for_state_change +from CimTest.Globals import logger +from XenKvmLib.const import do_main +from CimTest.ReturnCodes import PASS, FAIL, SKIP +from XenKvmLib.classes import get_typed_class +from XenKvmLib.vsmigrations import local_remote_migrate, \ + get_vs_mig_setting_class + +sup_types = ['KVM', 'Xen'] + +REQUESTED_STATE = 2 + +def setup_guest(test_dom, ip, virt): + virt_xml = vxml.get_class(virt) + cxml = virt_xml(test_dom) + ret = cxml.cim_define(ip) + if not ret: + logger.error("Error define domain %s", test_dom) + return FAIL, cxml + + status = cxml.cim_start(ip) + if status != PASS: + logger.error("Error to start domain %s", test_dom) + return FAIL, cxml + + status, dom_cs = poll_for_state_change(ip, virt, test_dom, + REQUESTED_STATE) + if status != PASS: + raise Exception("%s didn't change state as expected" % test_dom) + return FAIL, cxml + + return PASS, cxml + +@do_main(sup_types) +def main(): + options = main.options + virt = options.virt + s_sysname = os.environ['SRC_IP'] + t_sysname = os.environ['TARGET_IP'] + if options.virt == 'KVM' and t_sysname == s_sysname: + logger.info("Libvirt does not support local migratoin for KVM") + return SKIP + + status = FAIL + test_dom = 'VM_frm_' + socket.gethostname() + + try: + status, cxml = setup_guest(test_dom, s_sysname, virt) + if status != PASS: + logger.error("Error setting up the guest") + return status + + # Migrate the test_dom to t_sysname. + # local_remote_migrate executes live migration by default + # Enable remote migration by setting remote_migrate=1 + vsms_cn = get_vs_mig_setting_class(virt) + vsmservice = vsms_cn(s_sysname, virt) + status = local_remote_migrate(vsmservice, s_sysname, t_sysname, virt, + remote_migrate=1, guest_name=test_dom) + except Exception,details: + logger.error("Exception details :%s", details) + cxml.cim_destroy(s_sysname) + cxml.undefine(s_sysname) + return FAIL + + if status == PASS: + # Remote Migration Successful, clean the domain on target machine + cxml.cim_destroy(t_sysname) + cxml.undefine(t_sysname) + else: + # Remote Migration not Successful, clean the domain on src machine + cxml.cim_destroy(s_sysname) + cxml.undefine(s_sysname) + + return status + +if __name__ == "__main__": + sys.exit(main())

Deepti B. Kalakeri wrote:
# HG changeset patch # User Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1236853868 25200 # Node ID 89db4ac2378c90fd89845dd09836bfb39cc6e6ed # Parent caae383c83ec70e6cb6de9b6e5ccf6d2fcbecb45 [TEST][RFC] Added new tc to verify remote live migration.
Verified with KVM. The test case will not pass for KVM since the guest information needs to have emulator information without which the remote migration fails. The support to pass the emulator information via VirtualSystemMigrationSettingData is not yet available.
I haven't verified this on Xen yet.
+def main(): + options = main.options + virt = options.virt + s_sysname = os.environ['SRC_IP']
You already know the source IP from options.ip - do you need to set an environment variable for it?
+ t_sysname = os.environ['TARGET_IP']
Shouldn't you be able to the target ip from main.options the same way we get the source IP?
+ if options.virt == 'KVM' and t_sysname == s_sysname: + logger.info("Libvirt does not support local migratoin for KVM") + return SKIP + + status = FAIL + test_dom = 'VM_frm_' + socket.gethostname() + + try: + status, cxml = setup_guest(test_dom, s_sysname, virt) + if status != PASS: + logger.error("Error setting up the guest") + return status + + # Migrate the test_dom to t_sysname. + # local_remote_migrate executes live migration by default + # Enable remote migration by setting remote_migrate=1 + vsms_cn = get_vs_mig_setting_class(virt) + vsmservice = vsms_cn(s_sysname, virt) + status = local_remote_migrate(vsmservice, s_sysname, t_sysname, virt, + remote_migrate=1, guest_name=test_dom)
Why not have local_remote_migrate() get its own VirtualSystemMigrationService object? There's no need to pass it in here because it's not used later on.. Or are you planning to have future tests use it for something?
+ except Exception,details: + logger.error("Exception details :%s", details) + cxml.cim_destroy(s_sysname) + cxml.undefine(s_sysname) + return FAIL + + if status == PASS: + # Remote Migration Successful, clean the domain on target machine + cxml.cim_destroy(t_sysname) + cxml.undefine(t_sysname) + else: + # Remote Migration not Successful, clean the domain on src machine + cxml.cim_destroy(s_sysname) + cxml.undefine(s_sysname) +
Technically, if the migration fails partway through migrating a guest, it's possible for the guest to end up on both systems. So it'd be good to check both the source and the target to see if the guest exists (and remove it if it does). -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

Kaitlin Rupert wrote:
Deepti B. Kalakeri wrote:
# HG changeset patch # User Deepti B. Kalakeri <deeptik@linux.vnet.ibm.com> # Date 1236853868 25200 # Node ID 89db4ac2378c90fd89845dd09836bfb39cc6e6ed # Parent caae383c83ec70e6cb6de9b6e5ccf6d2fcbecb45 [TEST][RFC] Added new tc to verify remote live migration.
Verified with KVM. The test case will not pass for KVM since the guest information needs to have emulator information without which the remote migration fails. The support to pass the emulator information via VirtualSystemMigrationSettingData is not yet available.
I haven't verified this on Xen yet. I have not verified it either.
+def main(): + options = main.options + virt = options.virt + s_sysname = os.environ['SRC_IP']
You already know the source IP from options.ip - do you need to set an environment variable for it?
+ t_sysname = os.environ['TARGET_IP']
Shouldn't you be able to the target ip from main.options the same way we get the source IP?
I knew that the test cases were using the const.py options but was not able to track how they inherited the command line args given. Hmmm... I traced it now and its a bit tricky. I will make the changes in the subsequent patch I submit. I have one query, MigrateVirtualSystemToHost() just takes the DestinationHost ip / hostname, but what if the user wanted to connect using a specific port. Will passing the port information as part of the DestinationHost work ? If it does not then passing the Port through command line becomes meaningless.
+ if options.virt == 'KVM' and t_sysname == s_sysname: I was wondering how to make the check for verifying if the user wanted to do local migration, which means I need to validate the src ip and dest ip to be different. The user might give the src and destination information in any form like localhost, ip address, hostname, FQDN. The live.full_hostname() does not come handy. Also, the following function gave me a similar results which could be used for comparison. [ Only some o/p given]
print "Hostname is ", socket.gethostbyaddr('localhost') Hostname is ('elm3b41', ['localhost.localdomain', 'localhost', 'localhost'], ['127.0.0.1']) print "Hostname is ", socket.gethostbyaddr('elm3b41.beaverton.ibm.com') Hostname is ('elm3b41.beaverton.ibm.com', [], ['9.47.67.41']) print "Hostname is ", socket.gethostbyaddr('9.47.67.41') Hostname is ('elm3b41.beaverton.ibm.com', [], ['9.47.67.41'])
print "fqdn is %s", socket.getfqdn('elm3b41') fqdn is %s localhost.localdomain print "fqdn is %s", socket.getfqdn('') fqdn is %s localhost.localdomain print "fqdn is %s", socket.getfqdn('9.47.67.41') fqdn is %s elm3b41.beaverton.ibm.com print "fqdn is %s", socket.getfqdn('elm3b41.beaverton.ibm.com') fqdn is %s elm3b41.beaverton.ibm.com print "fqdn is %s", socket.getfqdn('localhost.localdomain') fqdn is %s localhost.localdomain
print "FQDN is ", socket.gethostbyaddr(socket.gethostname())[0] FQDN is elm3b41 socket.getfqdn('127.0.0.1') 'localhost.localdomain'
Can you suggest something here ?
+ logger.info("Libvirt does not support local migratoin for KVM") + return SKIP + + status = FAIL + test_dom = 'VM_frm_' + socket.gethostname() + + try: + status, cxml = setup_guest(test_dom, s_sysname, virt) + if status != PASS: + logger.error("Error setting up the guest") + return status + + # Migrate the test_dom to t_sysname. + # local_remote_migrate executes live migration by default + # Enable remote migration by setting remote_migrate=1 + vsms_cn = get_vs_mig_setting_class(virt) + vsmservice = vsms_cn(s_sysname, virt) + status = local_remote_migrate(vsmservice, s_sysname, t_sysname, virt, + remote_migrate=1, guest_name=test_dom)
Why not have local_remote_migrate() get its own VirtualSystemMigrationService object? There's no need to pass it in here because it's not used later on..
Or are you planning to have future tests use it for something?
Oh! yeah we do not use it for anything else in the current test case changes. I had created the VirtualSystemMigrationService object thinking that I shall execute one by one migration types. I will shift this to vsmigrations.py. But I guess writing separate scenarios for each of them makes it more cleaner or else it will become lengthier , wat say ??
+ except Exception,details: + logger.error("Exception details :%s", details) + cxml.cim_destroy(s_sysname) + cxml.undefine(s_sysname) + return FAIL + + if status == PASS: + # Remote Migration Successful, clean the domain on target machine + cxml.cim_destroy(t_sysname) + cxml.undefine(t_sysname) + else: + # Remote Migration not Successful, clean the domain on src machine + cxml.cim_destroy(s_sysname) + cxml.undefine(s_sysname) +
Technically, if the migration fails partway through migrating a guest, it's possible for the guest to end up on both systems. So it'd be good to check both the source and the target to see if the guest exists (and remove it if it does).
Ok I shall take care of this as well. -- Thanks and Regards, Deepti B. Kalakeri IBM Linux Technology Center deeptik@linux.vnet.ibm.com

Shouldn't you be able to the target ip from main.options the same way we get the source IP?
I knew that the test cases were using the const.py options but was not able to track how they inherited the command line args given. Hmmm... I traced it now and its a bit tricky. I will make the changes in the subsequent patch I submit.
I have one query, MigrateVirtualSystemToHost() just takes the DestinationHost ip / hostname, but what if the user wanted to connect using a specific port. Will passing the port information as part of the DestinationHost work ?
No, this won't work.
If it does not then passing the Port through command line becomes meaningless.
There's no need to specify a CIMOM port because MigrateVirtualSystemToHost() uses libvirt to migrate the guest - it doesn't use the CIMOM for this communication. It is possible to specify other libvirt transport types - this can be done using the MigrationSettingData instance. It's some what involved to use some of these transport types (more information at: http://libvirt.org/remote.html). I would recommend using the default transport type for these tests. Testing additional transport methods is something that can be added later (once all the basic migration scenarios are covered).
+ if options.virt == 'KVM' and t_sysname == s_sysname: I was wondering how to make the check for verifying if the user wanted to do local migration, which means I need to validate the src ip and dest ip to be different. The user might give the src and destination information in any form like localhost, ip address, hostname, FQDN. The live.full_hostname() does not come handy. Also, the following function gave me a similar results which could be used for comparison. [ Only some o/p given]
print "Hostname is ", socket.gethostbyaddr('localhost') Hostname is ('elm3b41', ['localhost.localdomain', 'localhost', 'localhost'], ['127.0.0.1']) print "Hostname is ", socket.gethostbyaddr('elm3b41.beaverton.ibm.com') Hostname is ('elm3b41.beaverton.ibm.com', [], ['9.47.67.41']) print "Hostname is ", socket.gethostbyaddr('9.47.67.41') Hostname is ('elm3b41.beaverton.ibm.com', [], ['9.47.67.41'])
print "fqdn is %s", socket.getfqdn('elm3b41') fqdn is %s localhost.localdomain print "fqdn is %s", socket.getfqdn('') fqdn is %s localhost.localdomain print "fqdn is %s", socket.getfqdn('9.47.67.41') fqdn is %s elm3b41.beaverton.ibm.com print "fqdn is %s", socket.getfqdn('elm3b41.beaverton.ibm.com') fqdn is %s elm3b41.beaverton.ibm.com print "fqdn is %s", socket.getfqdn('localhost.localdomain') fqdn is %s localhost.localdomain
print "FQDN is ", socket.gethostbyaddr(socket.gethostname())[0] FQDN is elm3b41 socket.getfqdn('127.0.0.1') 'localhost.localdomain'
Can you suggest something here ?
This is pretty tricky. The problem is that the /etc/hosts file can be formatted in numerous ways, and there isn't really a standard across distros / systems. So the gethostbyaddr(), getfqdn(), etc can return different values. Like you've pointed out, it's tough to get a full list of possible aliases for the system. I would say, for now, if the source and the target differ, assume it's a remote migration.
+ logger.info("Libvirt does not support local migratoin for KVM") + return SKIP + + status = FAIL + test_dom = 'VM_frm_' + socket.gethostname() + + try: + status, cxml = setup_guest(test_dom, s_sysname, virt) + if status != PASS: + logger.error("Error setting up the guest") + return status + + # Migrate the test_dom to t_sysname. + # local_remote_migrate executes live migration by default + # Enable remote migration by setting remote_migrate=1 + vsms_cn = get_vs_mig_setting_class(virt) + vsmservice = vsms_cn(s_sysname, virt) + status = local_remote_migrate(vsmservice, s_sysname, t_sysname, virt, + remote_migrate=1, guest_name=test_dom)
Why not have local_remote_migrate() get its own VirtualSystemMigrationService object? There's no need to pass it in here because it's not used later on..
Or are you planning to have future tests use it for something?
Oh! yeah we do not use it for anything else in the current test case changes. I had created the VirtualSystemMigrationService object thinking that I shall execute one by one migration types. I will shift this to vsmigrations.py. But I guess writing separate scenarios for each of them makes it more cleaner or else it will become lengthier , wat say ??
I'm not sure what you mean here.. for each of the migration types, you can still call local_remote_migrate(). The only difference here is that the function will set up the VirtualSystemMigrationService object each time. But I don't think that's a problem - it doesn't take too much execution time. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

Kaitlin Rupert wrote:
Shouldn't you be able to the target ip from main.options the same way we get the source IP?
I knew that the test cases were using the const.py options but was not able to track how they inherited the command line args given. Hmmm... I traced it now and its a bit tricky. I will make the changes in the subsequent patch I submit.
I have one query, MigrateVirtualSystemToHost() just takes the DestinationHost ip / hostname, but what if the user wanted to connect using a specific port. Will passing the port information as part of the DestinationHost work ?
No, this won't work.
If it does not then passing the Port through command line becomes meaningless.
There's no need to specify a CIMOM port because MigrateVirtualSystemToHost() uses libvirt to migrate the guest - it doesn't use the CIMOM for this communication.
It is possible to specify other libvirt transport types - this can be done using the MigrationSettingData instance. It's some what involved to use some of these transport types (more information at: http://libvirt.org/remote.html).
I would recommend using the default transport type for these tests. Testing additional transport methods is something that can be added later (once all the basic migration scenarios are covered).
+ if options.virt == 'KVM' and t_sysname == s_sysname: I was wondering how to make the check for verifying if the user wanted to do local migration, which means I need to validate the src ip and dest ip to be different. The user might give the src and destination information in any form like localhost, ip address, hostname, FQDN. The live.full_hostname() does not come handy. Also, the following function gave me a similar results which could be used for comparison. [ Only some o/p given]
print "Hostname is ", socket.gethostbyaddr('localhost') Hostname is ('elm3b41', ['localhost.localdomain', 'localhost', 'localhost'], ['127.0.0.1']) print "Hostname is ", socket.gethostbyaddr('elm3b41.beaverton.ibm.com') Hostname is ('elm3b41.beaverton.ibm.com', [], ['9.47.67.41']) print "Hostname is ", socket.gethostbyaddr('9.47.67.41') Hostname is ('elm3b41.beaverton.ibm.com', [], ['9.47.67.41'])
print "fqdn is %s", socket.getfqdn('elm3b41') fqdn is %s localhost.localdomain print "fqdn is %s", socket.getfqdn('') fqdn is %s localhost.localdomain print "fqdn is %s", socket.getfqdn('9.47.67.41') fqdn is %s elm3b41.beaverton.ibm.com print "fqdn is %s", socket.getfqdn('elm3b41.beaverton.ibm.com') fqdn is %s elm3b41.beaverton.ibm.com print "fqdn is %s", socket.getfqdn('localhost.localdomain') fqdn is %s localhost.localdomain
print "FQDN is ", socket.gethostbyaddr(socket.gethostname())[0] FQDN is elm3b41 socket.getfqdn('127.0.0.1') 'localhost.localdomain'
Can you suggest something here ?
This is pretty tricky. The problem is that the /etc/hosts file can be formatted in numerous ways, and there isn't really a standard across distros / systems. So the gethostbyaddr(), getfqdn(), etc can return different values.
Like you've pointed out, it's tough to get a full list of possible aliases for the system.
I would say, for now, if the source and the target differ, assume it's a remote migration.
+ logger.info("Libvirt does not support local migratoin for KVM") + return SKIP + + status = FAIL + test_dom = 'VM_frm_' + socket.gethostname() + + try: + status, cxml = setup_guest(test_dom, s_sysname, virt) + if status != PASS: + logger.error("Error setting up the guest") + return status + + # Migrate the test_dom to t_sysname. + # local_remote_migrate executes live migration by default + # Enable remote migration by setting remote_migrate=1 + vsms_cn = get_vs_mig_setting_class(virt) + vsmservice = vsms_cn(s_sysname, virt) + status = local_remote_migrate(vsmservice, s_sysname, t_sysname, virt, + remote_migrate=1, guest_name=test_dom)
Why not have local_remote_migrate() get its own VirtualSystemMigrationService object? There's no need to pass it in here because it's not used later on..
Or are you planning to have future tests use it for something?
Oh! yeah we do not use it for anything else in the current test case changes. I had created the VirtualSystemMigrationService object thinking that I shall execute one by one migration types. I will shift this to vsmigrations.py. But I guess writing separate scenarios for each of them makes it more cleaner or else it will become lengthier , wat say ??
I'm not sure what you mean here.. for each of the migration types, you can still call local_remote_migrate(). The only difference here is that the function will set up the VirtualSystemMigrationService object each time. Oops! I mixed two different things. Yes I had included the VirtualSystemMigrationService object creation to be able to use it for different migration types. Also, I was en quiring with you that if it is a good idea to include scenarios for all the migration types in one tc. Sorry for not being clear. But I don't think that's a problem - it doesn't take too much execution time.
-- Thanks and Regards, Deepti B. Kalakeri IBM Linux Technology Center deeptik@linux.vnet.ibm.com

I'm not sure what you mean here.. for each of the migration types, you can still call local_remote_migrate(). The only difference here is that the function will set up the VirtualSystemMigrationService object each time. Oops! I mixed two different things. Yes I had included the VirtualSystemMigrationService object creation to be able to use it for different migration types. Also, I was en quiring with you that if it is a good idea to include scenarios for all the migration types in one tc. Sorry for not being clear.
No problem! I think it's possible to include all the migration types in to one test. If it looks like the test will become too complex, then you can break it up. But I think it should be easy to add the others in without too much complexity. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com
participants (3)
-
Deepti B Kalakeri
-
Deepti B. Kalakeri
-
Kaitlin Rupert