On 03/19/2012 12:51 AM, tangchen wrote:
>
> This patch improves the virsh_migrate test to support more tests.

Hi Tang, thanks for the new tests. I found some problems on the code, 
see below:

> Signed-off-by: Tang Chen<tangc...@cn.fujitsu.com>
> ---
>   client/tests/libvirt/tests/virsh_migrate.py |  268 
> +++++++++++++++++++++++----
>   1 files changed, 227 insertions(+), 41 deletions(-)
>
> diff --git a/client/tests/libvirt/tests/virsh_migrate.py 
> b/client/tests/libvirt/tests/virsh_migrate.py
> index 7e74505..3e756bb 100644
> --- a/client/tests/libvirt/tests/virsh_migrate.py
> +++ b/client/tests/libvirt/tests/virsh_migrate.py
> @@ -1,5 +1,7 @@
> -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, virt_test_utils
>
>   def run_virsh_migrate(test, params, env):
>       """
> @@ -21,46 +23,84 @@ 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 != "":

^ You can express the above as:

if src_uri:

Since an empty string evaluates to false. It's cleaner and clearer IMO.

> +                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)
> +    # 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 = 
> ""):

^ Here you're not following PEP 08, it should be like:

def do_error_migration(vm_ref, dest_uri, options="", extra="", uri=""):

> +        cmd = ""
> +        if uri == "":

^ The above is better expressed as

if uri:

> +            cmd += "virsh migrate "
> +        else:
> +            cmd += "virsh -c %s migrate " % uri
> +        cmd += options


^ I'd say it's better to avoid a noop in case options is empty with:

if options:
     cmd += options

> +        if vm_ref != "":

if vm_ref:

> +            cmd += " --domain %s " % vm_ref
> +        if dest_uri != "":

if dest_uri

> +            cmd += " --desturi %s " % dest_uri
> +        cmd += extra
> +
> +        cmd_result = utils.run(cmd, ignore_status = True)

^ Fix spacing of the arguments

> +        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 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.")

^ The \ at the end of the line can be replaced by implicit line 
continuation:

         # vm.verify_kernel_crash()
         logging.info("vm.verify_kernel_crash() needs to be tested, "
                      "but won't work currently.")

And the message should be a debug message.

> +        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")

^ Again, fix spacing.

> +    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.")


^ Here warning_text is being used before specified.

> +
>       src_uri = vm.connect_uri
>       dest_uri = params.get("virsh_migrate_desturi")
>       # Identify easy config. mistakes early
> @@ -77,22 +117,168 @@ 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")
> +    new_nic_mac = ""
> +    dest_xmlfile = ""
> +
> +    exception = False
> +    try:
> +        # Confirm VM can be accessed through network.
> +        virt_utils.wait_for(None, delay, first=delay, step=1.0, text=None)

^ I'm not sure using wait_for with None as a function would work since 
it's not a callable. In this specific case, it's better to just 
time.sleep(delay).

> +        vm_ip = vm.get_address()
> +        s_ping, o_ping = virt_test_utils.ping(vm_ip, count = 2, timeout = 
> delay)

^ Again, fix passing arguments.

> +        logging.info(o_ping)
> +        if s_ping != 0:
> +            raise error.TestError("%s did not respond after %d sec." % 
> (vm.name, delay))
> +
> +        # Prepare for --xml.
> +        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)

^ I believe putting this as an INFO level message is excessive. DEBUG is 
better.

> +                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)

^ Typo here, error.TestError.

> +
> +        # 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. \n%s" % detail)
> +
> +        # 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.")
> +

_______________________________________________
Autotest mailing list
Autotest@test.kernel.org
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to