This patch improves the virsh_migrate test to support more tests. Signed-off-by: Tang Chen <tangc...@cn.fujitsu.com> --- client/tests/libvirt/tests/virsh_migrate.py | 286 +++++++++++++++++++++++---- 1 files changed, 243 insertions(+), 43 deletions(-)
diff --git a/client/tests/libvirt/tests/virsh_migrate.py b/client/tests/libvirt/tests/virsh_migrate.py index 7e74505..403d4db 100644 --- a/client/tests/libvirt/tests/virsh_migrate.py +++ b/client/tests/libvirt/tests/virsh_migrate.py @@ -1,13 +1,40 @@ -import logging, time +import logging, os, re, time, shutil, codecs, tempfile from autotest_lib.client.common_lib import error +from autotest_lib.client.bin import utils +from autotest_lib.client.virt import libvirt_vm, virt_utils def run_virsh_migrate(test, params, env): - """ + """ Test virsh migrate command. """ + # vm.migrate() did some error checking, so when we want to test + # some incorrect options, we have to construct our own command. + def do_error_migration(vm_ref, dest_uri, options = "", extra = "", uri = ""): + cmd = "" + if uri == "": + cmd += "virsh migrate " + else: + cmd += "virsh -c %s migrate " % uri + cmd += options + if vm_ref != "": + cmd += " --domain %s " % vm_ref + if dest_uri != "": + cmd += " --desturi %s " % dest_uri + cmd += extra + + cmd_result = utils.run(cmd, ignore_status = True) + logging.info("Output: %s", cmd_result.stdout.strip()) + logging.error("Error: %s", cmd_result.stderr.strip()) + logging.info("Status: %d", cmd_result.exit_status) + # Here we should keep the return value type the same as do_migration(). + if cmd_result.exit_status == 0: + return True + else: + return False + def check_vm_state(vm, state): - """ + """ Return True if vm is in the correct state. """ actual_state = vm.state() @@ -21,46 +48,59 @@ def run_virsh_migrate(test, params, env): Clean up the destination host environment when doing the uni-direction migration. """ - vm_state = vm.state() - if vm_state == "running": - vm.destroy() - elif vm_state == "paused": - vm.resume() - vm.destroy() + try: + if libvirt_vm.virsh_domain_exists(vm.name, vm.connect_uri): + vm_state = vm.state() + if vm_state == "paused": + vm.resume() + elif vm_state == "shut off": + vm.start() + vm.destroy() + + if vm.is_persistent(): + vm.undefine() - if vm.is_persistent(): - vm.undefine() + except Exception, detail: + logging.error("Cleaning up destination failed.\n%s" % detail) - vm.connect_uri = src_uri + finally: + if src_uri != "": + vm.connect_uri = src_uri - def do_migration(dly, vm, dest_uri, options, extra): - logging.info("Sleeping %d seconds before migration" % dly) - time.sleep(dly) + def do_migration(delay, vm, dest_uri, options, extra): + logging.info("Sleeping %d seconds before migration" % delay) + time.sleep(delay) # Migrate the guest. successful = vm.migrate(dest_uri, options, extra) if not successful: - raise error.TestFail("Migration failed for %s." % vm_name) + logging.error("Migration failed for %s." % vm_name) + return False if vm.is_alive(): # vm.connect_uri was updated logging.info("Alive guest found on destination %s." % dest_uri) else: - raise error.TestFail("VM not running on destination %s" % dest_uri) - - # Migration may fail, but VM is alive on destination. - dest_state = params.get("virsh_migrate_dest_state") - ret = check_vm_state(vm, dest_state) - logging.info("Supposed state: %s" % dest_state) - logging.info("Actual state: %s" % vm.state()) - if not ret: - raise error.TestFail("VM is not in the supposed state.") + logging.error("VM not alive on destination %s" % dest_uri) + return False # FIXME: This needs to be tested, but won't work currently # vm.verify_kernel_crash() + logging.info("vm.verify_kernel_crash() needs to be tested, \ + but won't work currently.") + return True vm_name = params.get("main_vm") vm = env.get_vm(params["main_vm"]) vm.verify_alive() + # For safety reasons, we'd better back up xmlfile. + vm_xmlfile = "/etc/libvirt/qemu/%s.xml" % vm_name + vm_xmlfile_bak = tempfile.mktemp(dir = "/tmp") + if os.path.exists(vm_xmlfile_bak): + os.remove(vm_xmlfile_bak) + shutil.copyfile(vm_xmlfile, vm_xmlfile_bak) + if not os.path.exists(vm_xmlfile_bak): + logging.warning(warning_text % "Backing up xmlfile failed.") + src_uri = vm.connect_uri dest_uri = params.get("virsh_migrate_desturi") # Identify easy config. mistakes early @@ -77,22 +117,182 @@ def run_virsh_migrate(test, params, env): options = params.get("virsh_migrate_options") extra = params.get("virsh_migrate_extra") - dly = int(params.get("virsh_migrate_delay", 10)) - - - do_migration(dly, vm, dest_uri, options, extra) - # Repeat the migration with a recursive call and guaranteed exit - if params.get("virsh_migrate_back", "no") == 'yes': - back_dest_uri = params.get("virsh_migrate_back_desturi", 'default') - back_options = params.get("virsh_migrate_back_options", 'default') - back_extra = params.get("virsh_migrate_back_extra", 'default') - if back_dest_uri == 'default': - back_dest_uri = src_uri - if back_options == 'default': - back_options = options - if back_extra == 'default': - back_extra = extra - do_migration(dly, vm, back_dest_uri, back_options, back_extra) - # Do the uni-direction migration here. - else: + delay = int(params.get("virsh_migrate_delay", 10)) + status_error = params.get("status_error", 'no') + libvirtd_state = params.get("virsh_migrate_libvirtd_state", 'on') + src_state = params.get("virsh_migrate_src_state", "running") + + # Wait till VM is up. + time.sleep(delay) + + exception = False + try: + # Confirm VM can be accessed through network. + vm_ip = vm.get_address(index = 0) + logging.info("VM IP: %s" % vm_ip) + # Ping VM for 100 sec and return if no responding. + i =1 + while (i <= 10): + ping_result = utils.run("ping -c 2 %s" % vm_ip, ignore_status = True) + if ping_result.exit_status != 0: + logging.info("Pinging VM %s has no responding after %d sec." % (vm_name, i*10)) + i = i + 1 + time.sleep(10) + else: + logging.info("VM has responded.") + break + if i > 10: + exception = True + raise error.TestError("Pinging VM %s has no responding after 100 sec." % vm_name) + + # Prepare for --xml. + new_nic_mac = "" + dest_xmlfile = "" + if options.count("xml") or extra.count("xml"): + new_nic_mac = virt_utils.generate_mac_address(vm, 1) + logging.info("New mac address: %s" % new_nic_mac) + dest_xmlfile = params.get("virsh_migrate_xml", "") + if dest_xmlfile != "": + ret_attach = vm.attach_interface("bridge", "--source virbr0 --mac %s" % new_nic_mac) + if not ret_attach: + exception = True + raise error.TestError("Attaching nic to %s failed." % vm.name) + vm_xml_new = vm.get_xml() + logging.info("Xml file on source: %s" % vm_xml_new) + f = codecs.open(dest_xmlfile, 'wb', encoding='utf-8') + f.write(vm_xml_new) + f.close() + if not os.path.exists(dest_xmlfile): + exception = True + raise erro.TestError("Creating %s failed." % dest_xmlfile) + + # Turn VM into certain state. + if src_state == "paused": + if vm.is_alive(): + vm.pause() + elif src_state == "shut off": + if vm.is_alive(): + if not vm.shutdown(): + vm.destroy() + + # Turn libvirtd into certain state. + if libvirtd_state == "off": + libvirt_vm.libvirtd_stop() + + # Test uni-direction migration. + if status_error == 'no': + ret_migrate = do_migration(delay, vm, dest_uri, options, extra) + else: + vm_ref = params.get("vm_ref", vm.name) + dest_uri_ref = params.get("dest_uri_ref", dest_uri) + ret_migrate = do_error_migration(vm_ref, dest_uri_ref, options, extra) + + # Recover libvirtd state. + if libvirtd_state == "off": + libvirt_vm.libvirtd_start() + + # Recover VM state. + if src_state == "paused": + vm.resume() + elif src_state == "shut off": + vm.start() + + # Check vm state on destination. + check_dest_state = True + dest_state = params.get("virsh_migrate_dest_state", "running") + check_dest_state = check_vm_state(vm, dest_state) + logging.info("Supposed state: %s\nActual state: %s" % (dest_state, vm.state())) + + # Checking for --persistent. + check_dest_persistent = True + if options.count("persistent") or extra.count("persistent"): + if not vm.is_persistent(): + check_dest_persistent = False + + # Checking for --undefinesource. + check_src_undefine = True + if options.count("undefinesource") or extra.count("undefinesource"): + if libvirt_vm.virsh_domain_exists(vm_name, src_uri): + check_src_undefine = False + + # Checking for --dname. + check_dest_dname = True + if options.count("dname") or extra.count("dname"): + dname = params.get("virsh_migrate_dname") + if not libvirt_vm.virsh_domain_exists(dname, dest_uri): + check_dest_dname = False + + # Checking for --xml. + check_dest_xml = True + if options.count("xml") or extra.count("xml"): + if dest_xmlfile != "": + vm_dest_xml = vm.get_xml() + logging.info("Xml file on destination: %s" % vm_dest_xml) + if not re.search(new_nic_mac, vm_dest_xml): + check_dest_xml = False + + # Repeat the migration with a recursive call and guaranteed exit + if params.get("virsh_migrate_back", "no") == 'yes': + back_dest_uri = params.get("virsh_migrate_back_desturi", 'default') + back_options = params.get("virsh_migrate_back_options", 'default') + back_extra = params.get("virsh_migrate_back_extra", 'default') + if back_dest_uri == 'default': + back_dest_uri = src_uri + if back_options == 'default': + back_options = options + if back_extra == 'default': + back_extra = extra + do_migration(delay, vm, back_dest_uri, back_options, back_extra) + + except Exception, detail: + # Whatever error occurs, we have to clean up all environment. + exception = True + logging.error("Error occurred.\n%s" % detail) + + finally: + # Cleanup destination. + # Make sure vm.connect_uri is the destination uri. + vm.connect_uri = dest_uri + if options.count("dname") or extra.count("dname"): + # Use the VM object to remove + vm.name = params.get("virsh_migrate_dname") + cleanup_dest(vm, "") + vm.name = vm_name cleanup_dest(vm, src_uri) + + # Recover source (just in case). + # vm.connect_uri has been set back to src_uri in cleanup_dest(). + if not libvirt_vm.virsh_domain_exists(vm_name, src_uri): + vm.define(vm_xmlfile_bak) + else: + if not vm.shutdown(): + vm.destroy() + + # Cleanup source. + if os.path.exists(vm_xmlfile_bak): + os.remove(vm_xmlfile_bak) + if os.path.exists(dest_xmlfile): + os.remove(dest_xmlfile) + + if exception: + raise error.TestError("Error occurred.") + + # Check test result. + if status_error == 'yes': + if ret_migrate: + raise error.TestFail("Migration finished with unexpected status.") + else: + if not ret_migrate: + raise error.TestFail("Migration finished with unexpected status.") + if not check_dest_state: + raise error.TestFail("Wrong VM state on destination.") + if not check_dest_persistent: + raise error.TestFail("VM is not persistent on destination.") + if not check_src_undefine: + raise error.TestFail("VM is not undefined on source.") + if not check_dest_dname: + raise error.TestFail("Wrong VM name %s on destination." % dname) + if not check_dest_xml: + raise error.TestFail("Wrong xml configuration on destination.") + + -- 1.7.3.1 -- Best Regards, Tang chen _______________________________________________ Autotest mailing list Autotest@test.kernel.org http://test.kernel.org/cgi-bin/mailman/listinfo/autotest