Re: [Autotest] [PATCH] [Autotest PATCH v2] KVM-test: Add a subtest 'qemu_img'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Mar 31, 2010 at 4:23 AM, Yolkfull Chow <yzhou@xxxxxxxxxx> wrote:
> This is designed to test all subcommands of 'qemu-img' however
> so far 'commit' is not implemented.
>
> * For 'check' subcommand test, it will 'dd' to create a file with specified
> size and see whether it's supported to be checked. Then convert it to be
> supported formats ('qcow2' and 'raw' so far) to see whether there's error
> after convertion.
>
> * For 'convert' subcommand test, it will convert both to 'qcow2' and 'raw' from
> the format specified in config file. And only check 'qcow2' after convertion.
>
> * For 'snapshot' subcommand test, it will create two snapshots and list them.
> Finally delete them if no errors found.
>
> * For 'info' subcommand test, it will check image format & size according to
> output of 'info' subcommand  at specified image file.
>
> * For 'rebase' subcommand test, it will create first snapshot 'sn1' based on original
> base_img, and create second snapshot based on sn1. And then rebase sn2 to base_img.
> After rebase check the baking_file of sn2.
>
> This supports two rebase mode: unsafe mode and safe mode:
> Unsafe mode:
> With -u an unsafe mode is enabled that doesn't require the backing files to exist.
> It merely changes the backing file reference in the COW image. This is useful for
> renaming or moving the backing file. The user is responsible to make sure that the
> new backing file has no changes compared to the old one, or corruption may occur.
>
> Safe Mode:
> Both the current and the new backing file need to exist, and after the rebase, the
> COW image is guaranteed to have the same guest visible content as before.
> To achieve this, old and new backing file are compared and, if necessary, data is
> copied from the old backing file into the COW image.
>
> Improvement from v1:
> * Add an underscore _ at the beginning of all the auxiliary functions.

Yolkfull, after testing I found some small issues, fixed them, changed
the commands APIs for autotest ones, and re-sent the result. I am
going to apply this shortly, thanks for your work on this test!

Cheers,

Lucas

> Results in:
>
> # ./scan_results.py
> Test                                                    Status  Seconds Info
> ----                                                    ------  ------- ----
>        (Result file: ../../results/default/status)
>        smp2.RHEL.5.4.i386.qemu_img.check                       GOOD    132 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.create                      GOOD    144 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.convert.to_qcow2            GOOD    251 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.convert.to_raw              GOOD    245 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.snapshot                    GOOD    140 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.commit                      GOOD    146 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.info                        GOOD    133 completed successfully
>        smp2.RHEL.5.4.i386.qemu_img.rebase                      TEST_NA 137 Current kvm user space version does not support 'rebase' subcommand
>        ----                                                    GOOD    1392
>        [root@aFu kvm]#
>
> shows only 'rebase' subtest is not supported currently.
> Others runs good from my side.
>
> Signed-off-by: Yolkfull Chow <yzhou@xxxxxxxxxx>
> ---
>  client/tests/kvm/tests/qemu_img.py     |  280 ++++++++++++++++++++++++++++++++
>  client/tests/kvm/tests_base.cfg.sample |   40 +++++
>  2 files changed, 320 insertions(+), 0 deletions(-)
>  create mode 100644 client/tests/kvm/tests/qemu_img.py
>
> diff --git a/client/tests/kvm/tests/qemu_img.py b/client/tests/kvm/tests/qemu_img.py
> new file mode 100644
> index 0000000..7f786c5
> --- /dev/null
> +++ b/client/tests/kvm/tests/qemu_img.py
> @@ -0,0 +1,280 @@
> +import re, os, logging, commands
> +from autotest_lib.client.common_lib import utils, error
> +import kvm_vm, kvm_utils
> +
> +
> +def run_qemu_img(test, params, env):
> +    """
> +    `qemu-img' functions test:
> +    1) Judge what subcommand is going to be tested
> +    2) Run subcommand test
> +
> +    @param test: kvm test object
> +    @param params: Dictionary with the test parameters
> +    @param env: Dictionary with test environment.
> +    """
> +    cmd = kvm_utils.get_path(test.bindir, params.get("qemu_img_binary"))
> +    if not os.path.exists(cmd):
> +        raise error.TestError("Binary of 'qemu-img' not found")
> +    image_format = params.get("image_format")
> +    image_size = params.get("image_size", "10G")
> +    image_name = kvm_vm.get_image_filename(params, test.bindir)
> +
> +    def _check(cmd, img):
> +        """
> +        Simple 'qemu-img check' function implementation.
> +
> +        @param cmd: binary of 'qemu_img'
> +        @param img: image to be checked
> +        """
> +        cmd += " check %s" % img
> +        logging.info("Checking image '%s'..." % img)
> +        o = commands.getoutput(cmd)
> +        if "does not support checks" in o or "No errors" in o:
> +            return (True, "")
> +        return (False, o)
> +
> +    # Subcommand 'qemu-img check' test
> +    # This tests will 'dd' to create a specified size file, and check it.
> +    # Then convert it to supported image_format in each loop and check again.
> +    def check_test(cmd):
> +        test_image = params.get("image_name_dd")
> +        create_image_cmd = params.get("create_image_cmd")
> +        create_image_cmd = create_image_cmd % test_image
> +        s, o = commands.getstatusoutput(create_image_cmd)
> +        if s != 0:
> +            raise error.TestError("Failed command: %s; Output is: %s" %
> +                                                 (create_image_cmd, o))
> +        s, o = _check(cmd, test_image)
> +        if not s:
> +            raise error.TestFail("Check image '%s' failed with error: %s" %
> +                                                           (test_image, o))
> +        for fmt in params.get("supported_image_formats").split():
> +            output_image = test_image + ".%s" % fmt
> +            _convert(cmd, fmt, test_image, output_image)
> +            s, o = _check(cmd, output_image)
> +            if not s:
> +                raise error.TestFail("Check image '%s' got error: %s" %
> +                                                     (output_image, o))
> +            os.remove(output_image)
> +        os.remove(test_image)
> +
> +    def _create(cmd, img_name, fmt, img_size=None, base_img=None,
> +               base_img_fmt=None, encrypted="no"):
> +        """
> +        Simple wrapper of 'qemu-img create'
> +
> +        @param cmd: binary of 'qemu-img'
> +        @param img_name: name of the image file
> +        @param fmt: image format
> +        @param img_size:  image size
> +        @param base_img: base image if create a snapshot image
> +        @param base_img_fmt: base image format if create a snapshot image
> +        @param encrypted: indicates whether the created image is encrypted
> +        """
> +        cmd += " create"
> +        if encrypted == "yes":
> +            cmd += " -e"
> +        if base_img:
> +            cmd += " -b %s" % base_img
> +            if base_img_fmt:
> +                cmd += " -F %s" % base_img_fmt
> +        cmd += " -f %s" % fmt
> +        cmd += " %s" % img_name
> +        if img_size:
> +            cmd += " %s" % img_size
> +        s, o = commands.getstatusoutput(cmd)
> +        if s != 0:
> +            raise error.TestFail("Create image '%s' failed: %s;Command:\n%s" %
> +                                                           (img_name, o, cmd))
> +        logging.info("Created image '%s'" % img_name)
> +
> +    # Subcommand 'qemu-img create' test
> +    def create_test(cmd):
> +        image_large = params.get("image_name_large")
> +        img = kvm_utils.get_path(test.bindir, image_large)
> +        img += '.' + image_format
> +        _create(cmd, img_name=img, fmt=image_format,
> +               img_size=params.get("image_size_large"))
> +        os.remove(img)
> +
> +    def _convert(cmd, output_fmt, img_name, output_filename,
> +                fmt=None, compressed="no", encrypted="no"):
> +        """
> +        Simple wrapper of 'qemu-img convert' function.
> +
> +        @param cmd: binary of 'qemu-img'
> +        @param output_fmt: the output format of converted image
> +        @param img_name: image name that to be converted
> +        @param output_filename: output image name that converted
> +        @param fmt: output image format
> +        @param compressed: whether output image is compressed
> +        @param encrypted: whether output image is encrypted
> +        """
> +        cmd += " convert"
> +        if compressed == "yes":
> +            cmd += " -c"
> +        if encrypted == "yes":
> +            cmd += " -e"
> +        if fmt:
> +            cmd += " -f %s" % fmt
> +        cmd += " -O %s" % output_fmt
> +        cmd += " %s %s" % (img_name, output_filename)
> +        logging.info("Converting '%s' from format '%s' to '%s'" %
> +                                     (img_name, fmt, output_fmt))
> +        s, o = commands.getstatusoutput(cmd)
> +        if s != 0:
> +            raise error.TestFail("Image converted failed; Command: %s;"
> +                                 "Output is: %s" % (cmd, o))
> +
> +    # Subcommand 'qemu-img convert' test
> +    def convert_test(cmd):
> +        dest_img_fmt = params.get("dest_image_format")
> +        output_filename = "%s.converted_%s" % (image_name, dest_img_fmt)
> +
> +        _convert(cmd, dest_img_fmt, image_name, output_filename,
> +                image_format, params.get("compressed"), params.get("encrypted"))
> +
> +        if dest_img_fmt == "qcow2":
> +            s, o = _check(cmd, output_filename)
> +            if s:
> +                os.remove(output_filename)
> +            else:
> +                raise error.TestFail("Check image '%s' failed with error: %s" %
> +                                                        (output_filename, o))
> +        else:
> +            os.remove(output_filename)
> +
> +    def _info(cmd, img, string=None, fmt=None):
> +        """
> +        Simple wrapper of 'qemu-img info'.
> +
> +        @param cmd: binary of 'qemu-img'
> +        @param img: image file
> +        @param string: sub info, say 'backing file'
> +        @param fmt: image format
> +        """
> +        cmd += " info"
> +        if fmt:
> +            cmd += " -f %s" % fmt
> +        cmd += " %s" % img
> +        s, o = commands.getstatusoutput(cmd)
> +        if s != 0:
> +            logging.error("Get info of image '%s' failed: %s" % (img, o))
> +            return None
> +        if not string:
> +            return o
> +        string += ": (.*)"
> +        str = re.findall(string, o)
> +        if str:
> +            return str[0]
> +        return None
> +
> +    # Subcommand 'qemu-img info' test
> +    def info_test(cmd):
> +        img_info = _info(cmd, image_name)
> +        logging.info("Info of image '%s': \n%s" % (image_name, img_info))
> +        if not image_format in img_info:
> +            raise error.TestFail("Got unexpected format of image '%s'"
> +                                 " in info test" % image_name)
> +        if not image_size in img_info:
> +            raise error.TestFail("Got unexpected size of image '%s'"
> +                                 " in info test" % image_name)
> +
> +    # Subcommand 'qemu-img snapshot' test
> +    def snapshot_test(cmd):
> +        cmd += " snapshot"
> +        for i in range(2):
> +            crtcmd = cmd
> +            sn_name = "snapshot%d" % i
> +            crtcmd += " -c %s %s" % (sn_name, image_name)
> +            s, o = commands.getstatusoutput(crtcmd)
> +            if s != 0:
> +                raise error.TestFail("Create snapshot failed via command: %s;"
> +                                     "Output is: %s" % (crtcmd, o))
> +            logging.info("Created snapshot '%s' in '%s'" % (sn_name,image_name))
> +        listcmd = cmd
> +        listcmd += " -l %s" % image_name
> +        s, o = commands.getstatusoutput(listcmd)
> +        if not ("snapshot0" in o and "snapshot1" in o and s == 0):
> +            raise error.TestFail("Snapshot created failed or missed;"
> +                                 "snapshot list is: \n%s" % o)
> +        for i in range(2):
> +            sn_name = "snapshot%d" % i
> +            delcmd = cmd
> +            delcmd += " -d %s %s" % (sn_name, image_name)
> +            s, o = commands.getstatusoutput(delcmd)
> +            if s != 0:
> +                raise error.TestFail("Delete snapshot '%s' failed: %s" %
> +                                                     (sn_name, o))
> +
> +    #Subcommand 'qemu-img commit' test
> +    def commit_test(cmd):
> +        pass
> +
> +    def _rebase(cmd, img_name, base_img, backing_fmt, mode="unsafe"):
> +        """
> +        Simple wrapper of 'qemu-img rebase'.
> +
> +        @param cmd: binary of 'qemu-img'
> +        @param img_name: image name to be rebased
> +        @param base_img: indicates the base image
> +        @param backing_fmt: the format of base image
> +        @param mode: rebase mode: safe mode, unsafe mode
> +        """
> +        cmd += " rebase"
> +        if mode == "unsafe":
> +            cmd += " -u"
> +        cmd += " -b %s -F %s %s" % (base_img, backing_fmt, img_name)
> +        logging.info("Trying to rebase '%s' to '%s'..." % (img_name, base_img))
> +        s, o = commands.getstatusoutput(cmd)
> +        if s != 0:
> +            raise error.TestError("Failed to rebase '%s' to '%s': %s" %
> +                                               (img_name, base_img, o))
> +
> +    # Subcommand 'qemu-img rebase' test
> +    # Change the backing file of a snapshot image in "unsafe mode":
> +    # Assume the previous backing file had missed and we just have to change
> +    # reference of snapshot to new one. After change the backing file of a
> +    # snapshot image in unsafe mode, the snapshot should work still.
> +    def rebase_test(cmd):
> +        if not 'rebase' in utils.system_output(cmd+' --help',ignore_status=True):
> +            raise error.TestNAError("Current kvm user space version does not"
> +                                    " support 'rebase' subcommand")
> +        sn_fmt = params.get("snapshot_format", "qcow2")
> +        sn1 = params.get("image_name_snapshot1")
> +        sn1 = kvm_utils.get_path(test.bindir, sn1) + ".%s" % sn_fmt
> +        base_img = kvm_vm.get_image_filename(params, test.bindir)
> +        _create(cmd, sn1, sn_fmt, base_img=base_img, base_img_fmt=image_format)
> +
> +        # Create snapshot2 based on snapshot1
> +        sn2 = params.get("image_name_snapshot2")
> +        sn2 = kvm_utils.get_path(test.bindir, sn2) + ".%s" % sn_fmt
> +        _create(cmd, sn2, sn_fmt, base_img=sn1, base_img_fmt=sn_fmt)
> +
> +        rebase_mode = params.get("rebase_mode")
> +        if rebase_mode == "unsafe":
> +            os.remove(sn1)
> +
> +        _rebase(cmd, sn2, base_img, image_format, mode=rebase_mode)
> +
> +        # Check sn2's format and backing_file
> +        actual_base_img = _info(cmd, sn2, "backing file")
> +        base_img_name = os.path.basename(params.get("image_name"))
> +        if not base_img_name in actual_base_img:
> +            raise error.TestFail("After rebase the backing_file of 'sn2' is "
> +                                 "'%s' which is not expected as '%s'"
> +                                 % (actual_base_img, base_img_name))
> +        s, o = _check(cmd, sn2)
> +        if not s:
> +            raise error.TestFail("Check image '%s' failed after rebase;"
> +                                 "got error: %s" % (sn2, o))
> +        try:
> +            os.remove(sn2)
> +            os.remove(sn1)
> +        except:
> +            pass
> +
> +    # Here starts test
> +    subcommand = params.get("subcommand")
> +    eval("%s_test(cmd)" % subcommand)
> diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
> index d162cf8..cf397ea 100644
> --- a/client/tests/kvm/tests_base.cfg.sample
> +++ b/client/tests/kvm/tests_base.cfg.sample
> @@ -310,6 +310,46 @@ variants:
>         sleep_before_reset = 20
>         kill_vm_on_error = yes
>
> +    - qemu_img:
> +        type = qemu_img
> +        vms = ''
> +        variants:
> +            - check:
> +                subcommand = check
> +                image_name_dd = dd_created_image
> +                force_create_image_dd = no
> +                remove_image_dd = yes
> +                create_image_cmd = "dd if=/dev/zero of=%s bs=1G count=1"
> +                # Test the convertion from 'dd_image_name' to specified format
> +                supported_image_formats = qcow2 raw
> +            - create:
> +                subcommand = create
> +                images += " large"
> +                force_create_image_large = yes
> +                image_size_large = 1G
> +                image_name_large = create_large_image
> +                remove_image_large = yes
> +            - convert:
> +                subcommand = convert
> +                variants:
> +                    - to_qcow2:
> +                        dest_image_format = qcow2
> +                        compressed = no
> +                        encrypted = no
> +                    - to_raw:
> +                        dest_image_format = raw
> +            - snapshot:
> +                subcommand = snapshot
> +            - commit:
> +                subcommand = commit
> +            - info:
> +                subcommand = info
> +            - rebase:
> +                subcommand = rebase
> +                rebase_mode = unsafe
> +                image_name_snapshot1 = sn1
> +                image_name_snapshot2 = sn2
> +
>     - shutdown:     install setup unattended_install
>         type = shutdown
>         shutdown_method = shell
> --
> 1.7.0.1
>
> _______________________________________________
> Autotest mailing list
> Autotest@xxxxxxxxxxxxxxx
> http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
>



-- 
Lucas
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux