Signed-off-by: Yanbing Du <[email protected]>
---
 libvirt/tests/virsh_blockcopy.py |  346 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 346 insertions(+), 0 deletions(-)
 create mode 100644 libvirt/tests/virsh_blockcopy.py

diff --git a/libvirt/tests/virsh_blockcopy.py b/libvirt/tests/virsh_blockcopy.py
new file mode 100644
index 0000000..86f802e
--- /dev/null
+++ b/libvirt/tests/virsh_blockcopy.py
@@ -0,0 +1,346 @@
+import logging, os, commands, re, time
+from autotest.client.shared import error
+from virttest import libvirt_vm, virsh, libvirt_xml
+
+def xml_check(xml, dest_path, level):
+    """
+    Check the domain XML for blockcopy job
+
+    @param copy_xml: XML file of the domain
+    @param: level: domain XML check level
+            level = 1, XMl has <mirror> , dest_path, and ready='yes'
+            level = 2, XML don't have <mirror> but can find dest_path
+            level = 3, XMl don't have <mirror> and can't find dest_path
+    """
+    xml_content = open(xml, "r").read()
+    logging.debug("Domain XML:\n %s", xml_content)
+    if re.search("<mirror", xml_content):
+        re1 = 1
+        logging.debug("Find <mirror> elemnt in domain xml.")
+    else:
+        re1 = 0
+        logging.debug("Can't find <mirror> elemnt in domain xml.")
+    if re.search(dest_path, xml_content):
+        re2 = 1
+        logging.debug("Find %s in domain xml.", dest_path)
+    else:
+        re2 = 0
+        logging.debug("Can' find %s in domain xml.", dest_path)
+    if re.search("ready=\'yes\'", xml_content):
+        re3 = 1
+        logging.debug("Find ready='yes' in domain xml.")
+    else:
+        re3 = 0
+        logging.debug("Can't find ready='yes' in domain xml.")
+
+    if level == 1:
+        if re1 + re2 + re3 == 3:
+            return True
+    elif level == 2:
+        if re1 + re3 == 0  and re2 == 1:
+            return True
+    elif level == 3:
+        if re1 + re2 + re3 == 0:
+            return True
+    else:
+        logging.error("level must in [1, 2, 3]")
+
+    return False
+
+def format_check(dest_path, expect):
+    """
+    Check the image format
+
+    @param dest_path: path of the copy to create
+    @param expect: expect format
+    """
+    logging.debug("Run qemu-img info comamnd on %s", dest_path)
+    cmd = "qemu-img info %s | awk '/file format/'" % dest_path
+    if os.path.exists(dest_path):
+        (status, output) = commands.getstatusoutput(cmd)
+        if status == 0:
+            logging.debug(dest_path + " " + output)
+            if re.search(expect, output):
+                return True
+        else:
+            logging.error("Fail to get format for %s", dest_path)
+    else:
+        logging.error("Image file %s not found", dest_path)
+    return False
+
+def blockjob_check(vm_name, target, check_point, value):
+    """
+    Run blookjob command to check block copy progress, bandwidth
+
+    @param vm_name: domain name
+    @param target: domian disk target dev
+    @param check_point: check progrss, bandwidth or timeout
+    @param value: value of progress, bandwidth or timeout
+    """
+    if check_point not in ["progress", "bandwidth", "timeout"]:
+        logging.error("check_point must be: progress, bandwidth or timeout")
+
+    if not len(value) and not value.isdigit():
+        raise error.TestFail("Invalid value")
+
+    try:
+        options = "--info"
+        cmd_result = virsh.blockjob(vm_name, target, options,
+                                    ignore_status=True, debug=True)
+        output = cmd_result.stdout.strip()
+        err = cmd_result.stderr.strip()
+        status = cmd_result.exit_status
+
+    except Exception, detail:
+        exception = True
+        logging.error("%s: %s", detail.__class__, detail)
+
+    if status == 0:
+        if len(err):
+            if check_point == "progress":
+                progress = value+" %"
+                if re.search(progress, err):
+                    return True
+            if check_point == "bandwidth":
+                bandwidth = value + " MiB/s"
+                if bandwidth == output.split(':')[1].strip():
+                    logging.debug("Pass, bandwidth = %s", bandwidth)
+                    return True
+                else:
+                    logging.error("Fail, bandwidth != %s", bandwidth)
+            if check_point == "timeout":
+                logging.error("Block copy job desen't timeout in %s sec, but "
+                              "expect timeout", value)
+        elif check_point == "timeout":
+            logging.debug("Block copy job timeout in %s sec", value)
+            return True
+        else:
+            logging.error("Doesn't find block copy job for %s on %s", vm_name,
+                           target)
+    else:
+        logging.error("Run blockjob %s %s fail", vm_name, target,)
+    return False
+
+def run_virsh_blockcopy(test, params, env):
+    """
+    Test command: virsh blockcopy.
+
+    This command can copy a disk backing image chain to dest.
+    1. Positive testing
+        1.1 Copy a disk to a new image file.
+        1.2 Reuse existing destination copy.
+        1.3 Valid timeout and bandwidth test.
+    2. Negative testing
+        2.1 Copy a disk to a non-exist directory.
+        2.2 Copy a disk with invalid options.
+        2.3 Do blcok copy for a persistent domain.
+    """
+
+    vm_name = params.get("main_vm", "vm1")
+    vm = env.get_vm(params["main_vm"])
+
+    dest_path = params.get("dest_path")
+    if len(dest_path) == 0:
+        tmp_file = time.strftime("%Y-%m-%d-%H.%M.%S.img")
+        dest_path = os.path.join("/tmp", tmp_file)
+    options = params.get("blockcopy_options", "")
+    dest_format = params.get("dest_format", "")
+    bandwidth = params.get("bandwidth", "")
+    timeout = params.get("timeout", "no")
+    reuse_external = params.get("reuse_external", "no")
+    persistent_vm = params.get("persistent_vm", "no")
+    status_error = params.get("status_error", "no")
+    rerun_flag = 0
+
+    # Prepare transient/persistent vm
+    original_xml = vm.backup_xml()
+    if persistent_vm == "no" and vm.is_persistent():
+        vm.undefine()
+    elif persistent_vm == "yes" and not vm.is_persistent():
+        vm.define(original_xml)
+
+    # Get a source disk
+    try:
+        blklist = libvirt_xml.VMXML.get_disk_blk(vm_name)
+        if blklist == None:
+            raise error.TestFail("Cannot find disk in domain %s" % vm_name)
+        # Select the first block device from disks
+        target = blklist[0]
+    except Exception, detail:
+        logging.error("Fail to get first block device.\n%s", detail)
+
+    # Prepare for --reuse-external option
+    rename_dest = 0
+    dest_bk = ""
+    if reuse_external == "yes":
+        # Set rerun_flag=1 to do blockcopy twice, and the first time created
+        # file can be reused in the second time, if no dest_path given
+        if dest_path == "/tmp/non-exist.img":
+            if os.path.exists(dest_path):
+                dest_bk = dest_path + ".blcokcopy.rename"
+                if os.rename(dest_path, dest_bk):
+                    logging.error("Rename %s to %s failed", dest_path, dest_bk)
+                else:
+                    rename_dest = 1
+        elif not os.path.exists(dest_path):
+            rerun_flag = 1
+        options += "--reuse-external"
+
+    # Prepare other options
+    if dest_format == "raw":
+        options += "--raw"
+    if len(bandwidth):
+        options += "--bandwidth %s" % bandwidth
+    if timeout != "no":
+        status_error = "yes"
+        if timeout == "yes":
+        #set minmal value(=1) to make sure copy job will timeout
+            timeout = "1"
+        if "--wait" not in options:
+            options += "--wait --timeout %s" % timeout
+        else:
+            options += "--timeout %s" % timeout
+
+    # Before raise TestFail, need recover the env
+    def cleanup(xml, dest_path, rename_dest):
+        """
+        Re-define the domain and recover the dest file
+        """
+        try:
+            if not vm.is_alive():
+                raise error.TestFail("Domain is dead.")
+            else:
+                vm.destroy()
+                virsh.define(xml)
+            if os.path.exists(dest_path):
+                os.remove(dest_path)
+            if rename_dest == 1:
+                if os.rename(dest_bk, dest_path):
+                    logging.error("Rename %s to %s failed", dest_bk, dest_path)
+        except Exception, detail:
+            logging.error("Cleaning up fail.\n%s", detail)
+
+    def finish_job(vm_name, target, limit_time):
+        """
+        Make sure the block copy job finish.
+        """
+        timeout = 0
+        while timeout < limit_time:
+            if blockjob_check(vm_name, target, "progress", "100"):
+                logging.debug("Blockcopy job progress up to 100%")
+                break
+            else:
+                timeout += 2
+                time.sleep(2)
+
+    # Run virsh command
+    exception = False
+    try:
+        if rerun_flag == 1:
+            options1 = "--wait --raw --finish --verbose"
+            cmd_result = virsh.blockcopy(vm_name, target, dest_path, options1,
+                                         ignore_status=True, debug=True)
+            status = cmd_result.exit_status
+            if status != 0:
+                exception = True
+                raise error.TestFail("Run blockcopy fail!")
+            elif not os.path.exists(dest_path):
+                exception = True
+                raise error.TestFail("Can't find the dest file!")
+
+        cmd_result = virsh.blockcopy(vm_name, target, dest_path, options,
+                                     ignore_status=True, debug=True)
+        output = cmd_result.stdout.strip()
+        status = cmd_result.exit_status
+
+    except Exception, detail:
+        exception = True
+        logging.error("%s: %s", detail.__class__, detail)
+
+    # Check result
+    if not libvirt_vm.service_libvirtd_control("status"):
+        raise error.TestFail("Libvirtd service is dead.")
+
+    if status_error == "no":
+        if status == 0:
+            if not os.path.exists(dest_path):
+                exception = True
+                raise error.TestFail("Can't find the dest file!")
+            elif re.search("--raw", options):
+                if (not re.search("--pivot", options) and
+                   not re.search("--finish", options)):
+                    finish_job(vm_name, target, 120)
+                    copy_xml = vm.backup_xml()
+                    if (xml_check(copy_xml, dest_path, 1) and
+                        format_check(dest_path, "raw")):
+                        logging.info("Blockcopy --raw test pass!")
+                    else:
+                        exception = True
+                        raise error.TestFail("Blockcopy --raw test check 
fail!")
+                elif format_check(dest_path, "raw"):
+                    exception = True
+                    raise error.TestFail("Image format is not raw!")
+            elif re.search("--bandwidth", options):
+                if (not re.search("--pivot", options) and
+                   not re.search("--finish", options)):
+                    finish_job(vm_name, target, 120)
+                    copy_xml = vm.backup_xml()
+                    if (xml_check(copy_xml, dest_path, 1) and
+                        blockjob_check(vm_name, target, "bandwidth", 
bandwidth)):
+                        logging.info("Blockcopy --bandwidth test check pass!")
+                    else:
+                        exception = True
+                        raise error.TestFail("Blockcopy --bandwidth test "
+                                             "check fail!")
+                else:
+                    logging.info("Skip bandwidth check!")
+            elif re.search("--pivot", options):
+                copy_xml = vm.backup_xml()
+                if xml_check(copy_xml, dest_path, 2):
+                    logging.info("Blockcopy --pivot test check pass!")
+                else:
+                    exception = True
+                    raise error.TestFail("Blockcopy --pivot test check fail!")
+            elif re.search("--finish", options):
+                copy_xml = vm.backup_xml()
+                if xml_check(copy_xml, dest_path, 3):
+                    logging.info("Blockcopy --finish test check pass!")
+                else:
+                    exception = True
+                    raise error.TestFail("Blockcopy --finish test check fail!")
+            else:
+                finish_job(vm_name, target, 120)
+                copy_xml = vm.backup_xml()
+                if (xml_check(copy_xml, dest_path, 1) and
+                    blockjob_check(vm_name, target, "progress", "100")):
+                    logging.info("Blockcopy test check pass!")
+                else:
+                    exception = True
+                    raise error.TestFail("Blockcopy test check fail!")
+
+        else:
+            exception = True
+            raise error.TestFail("Expect succeed, but run fail!")
+
+    elif status_error == "yes":
+        if status == 0:
+            exception = True
+            raise error.TestFail("Expect fail, but run successfully!")
+        elif re.search("--timeout", options):
+            finish_job(vm_name, target, 1)
+            copy_xml = vm.backup_xml()
+            if (xml_check(copy_xml, dest_path, 3) and
+                blockjob_check(vm_name, target, "timeout", timeout)):
+                logging.info("Block copy timeout test check pass!")
+            else:
+                exception = True
+                raise error.TestFail("Block copy timeout test check fail!")
+    else:
+        exception = True
+        raise error.TestFail("The status_error must be 'yes' or 'no'!")
+
+    # Cleanup
+    cleanup(original_xml, dest_path, rename_dest)
+
+    if exception:
+        raise error.TestError("Error occurred. \n%s: %s" % (detail.__class__, 
detail))
-- 
1.7.1

_______________________________________________
Virt-test-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/virt-test-devel

Reply via email to