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

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

 



On Thu, Jan 28, 2010 at 09:01:43AM +0530, sudhir kumar wrote:
> Yolkfull,
> Good test. Did never come to my mind to add such a test to autotest.
> I would like to test your latest patch!!

Thanks Sudhir, please then help review that patch as well.:)

> 
> On Thu, Jan 28, 2010 at 8:37 AM, Yolkfull Chow <yzhou@xxxxxxxxxx> wrote:
> > On Wed, Jan 27, 2010 at 07:37:46AM -0500, Michael Goldish wrote:
> >>
> >> ----- "Yolkfull Chow" <yzhou@xxxxxxxxxx> wrote:
> >>
> >> > On Tue, Jan 26, 2010 at 03:11:34PM -0200, Lucas Meneghel Rodrigues
> >> > wrote:
> >> > > On Tue, 2010-01-26 at 11:25 +0800, Yolkfull Chow wrote:
> >> > > > This is designed to test all subcommands of 'qemu-img' however
> >> > > > so far 'commit' is not implemented.
> >> > >
> >> > > Hi Yolkful, this is very good! Seeing this test made me think about
> >> > that
> >> > > stand alone autotest module we commited a while ago, that does
> >> > > qemu_iotests testsuite on the host.
> >> > >
> >> > > Perhaps we could 'port' this module to the kvm test, since it is
> >> > more
> >> >
> >> > Lucas, do you mean the client-side 'kvmtest' ?
> >> >
> >> > And thanks for comments. :)
> >> >
> >> > > convenient to execute it inside a kvm test job (in a job where we
> >> > test
> >> > > more than 2 build types, for example, we need to execute qemu_img
> >> > and
> >> > > qemu_io_tests for every qemu-img built).
> >> > >
> >> > > Could you look at implementing this?
> >> > >
> >> > > > * 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 simply get output from specified
> >> > image file.
> >> > > >
> >> > > > Signed-off-by: Yolkfull Chow <yzhou@xxxxxxxxxx>
> >> > > > ---
> >> > > >  client/tests/kvm/tests/qemu_img.py     |  155
> >> > ++++++++++++++++++++++++++++++++
> >> > > >  client/tests/kvm/tests_base.cfg.sample |   36 ++++++++
> >> > > >  2 files changed, 191 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..1ae04f0
> >> > > > --- /dev/null
> >> > > > +++ b/client/tests/kvm/tests/qemu_img.py
> >> > > > @@ -0,0 +1,155 @@
> >> > > > +import os, logging, commands
> >> > > > +from autotest_lib.client.common_lib import error
> >> > > > +import kvm_vm
> >> > > > +
> >> > > > +
> >> > > > +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 = params.get("qemu_img_binary")
> >> > >
> >> > > It is a good idea to verify if cmd above resolves to an absolute
> >> > path,
> >> > > to avoid problems. If it doesn't resolve, verify if there's the
> >> > symbolic
> >> > > link under kvm test dir pointing to qemu-img, and if it does exist,
> >> > make
> >> > > sure it points to a valid file (ie, symlink is not broken).
> >>
> >> This can be done quickly using kvm_utils.get_path() and os.path.exists(),
> >> like this:
> >>
> >> cmd = kvm_utils.get_path(params.get("qemu_img_binary"))
> >> if not os.path.exists(cmd):
> >>     raise error.TestError("qemu-img binary not found")
> >>
> >> kvm_utils.get_path() is the standard way of getting both absolute and
> >> relative paths, and os.path.exists() checks whether the file exists and
> >> makes sure it's not a broken symlink.
> >
> > Yes, thanks for pointing that out.
> >
> >>
> >> > > > +    subcommand = params.get("subcommand")
> >> > > > +    image_format = params.get("image_format")
> >> > > > +    image_name = kvm_vm.get_image_filename(params, test.bindir)
> >> > > > +
> >> > > > +    def check(img):
> >> > > > +        global cmd
> >> > > > +        cmd += " check %s" % img
> >> > > > +        logging.info("Checking image '%s'..." % img)
> >> > > > +        s, o = commands.getstatusoutput(cmd)
> >> > > > +        if not (s == 0 or "does not support checks" in o):
> >> > > > +            return (False, o)
> >> > > > +        return (True, "")
> >> > >
> >> > > Please use utils.system_output here instead of the equivalent
> >> > commands
> >> > > API on the above code. This comment applies to all further uses of
> >> > > commands.[function].
> >> > >
> >> > > > +
> >> > > > +    # 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():
> >> > > > +        size = params.get("dd_image_size")
> >> > > > +        test_image = params.get("dd_image_name")
> >> > > > +        create_image_cmd = params.get("create_image_cmd")
> >> > > > +        create_image_cmd = create_image_cmd % (test_image, size)
> >> > > > +        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(test_image)
> >> > > > +        if not s:
> >> > > > +            raise error.TestFail("Failed to check image '%s' with
> >> > error: %s" %
> >> > > > +
> >> > (test_image, o))
> >> > > > +        for fmt in
> >> > params.get("supported_image_formats").split():
> >> > > > +            output_image = test_image + ".%s" % fmt
> >> > > > +            convert(fmt, test_image, output_image)
> >> > > > +            s, o = check(output_image)
> >> > > > +            if not s:
> >> > > > +                raise error.TestFail("Check image '%s' got error:
> >> > %s" %
> >> > > > +
> >> > (output_image, o))
> >> > > > +            commands.getoutput("rm -f %s" % output_image)
> >> > > > +        commands.getoutput("rm -f %s" % test_image)
> >> > > > +    #Subcommand 'qemu-img create' test
> >> > > > +    def create_test():
> >> > > > +        global cmd
> >> > >
> >> > > I don't like very much this idea of using a global variable, instead
> >> > it
> >> > > should be preferrable to use a class and have a class attribute
> >> > with
> >> > > 'cmd'. This way it would be safer, since the usage of cmd is
> >> > > encapsulated. This comment applies to all further usage of 'global
> >> > cmd'.
> >>
> >> Do we really need a class for this?  If we want to avoid using a global
> >> variable, 'cmd' can be passed as a parameter to all the inner functions
> >> that use it (check(), convert(), create_test(), etc).
> >
> > Actually before using 'global' to declare it, I was passing 'cmd' as a parameter
> > to all inner functions of subcommand. Anyway, I could change it back. :)
> >
> >>
> >> > > > +        cmd += " create"
> >> > > > +        if params.get("encrypted") == "yes":
> >> > > > +            cmd += " -e"
> >> > > > +        if params.get("base_image"):
> >> > > > +            cmd += " -F %s -b %s" %
> >> > (params.get("base_image_format"),
> >> > > > +                                     params.get("base_image"))
> >> > > > +        format = params.get("image_format")
> >> > > > +        cmd += " -f %s" % format
> >> > > > +        image_name_test = os.path.join(test.bindir,
> >> > > > +                          params.get("image_name_test")) + '.' +
> >> > format
> >> > > > +        cmd += " %s %s" % (image_name_test,
> >> > params.get("image_size_test"))
> >> > > > +        s, o = commands.getstatusoutput(cmd)
> >> > > > +        if s != 0:
> >> > > > +            raise error.TestFail("Create image '%s' failed: %s"
> >> > %
> >> > > > +                                            (image_name_test,
> >> > o))
> >> > > > +        commands.getoutput("rm -f %s" % image_name_test)
> >> > > > +    def convert(output_format, image_name, output_filename,
> >> > > > +                format=None, compressed="no", encrypted="no"):
> >> > > > +        global cmd
> >> > > > +        cmd += " convert"
> >> > > > +        if compressed == "yes":
> >> > > > +            cmd += " -c"
> >> > > > +        if encrypted == "yes":
> >> > > > +            cmd += " -e"
> >> > > > +        if format:
> >> > > > +            cmd += " -f %s" % image_format
> >> > > > +        cmd += " -O %s" % params.get("dest_image_format")
> >> > > > +        cmd += " %s %s" % (image_name, output_filename)
> >> > > > +        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():
> >> > > > +        dest_image_format = params.get("dest_image_format")
> >> > > > +        output_filename = "%s.converted_%s" % (image_name,
> >> > dest_image_format)
> >> > > > +
> >> > > > +        convert(dest_image_format, image_name,
> >> > params.get("dest_image_format"),
> >> > > > +                image_format, params.get("compressed"),
> >> > params.get("encrypted"))
> >> > > > +
> >> > > > +        if dest_image_format == "qcow2":
> >> > > > +            s, o = check(output_filename)
> >> > > > +            if s:
> >> > > > +                commands.getoutput("rm -f %s" % output_filename)
> >> > > > +            else:
> >> > > > +                raise error.TestFail("Check image '%s' failed
> >> > with error: %s" %
> >> > > > +
> >> > (dest_image_format, o))
> >> > > > +        else:
> >> > > > +            commands.getoutput("rm -f %s" % output_filename)
> >> > > > +    #Subcommand 'qemu-img info' test
> >> > > > +    def info_test():
> >> > > > +        global cmd
> >> > > > +        cmd += " info"
> >> > > > +        cmd += " -f %s %s" % (image_format, image_name)
> >> > > > +        s, o = commands.getstatusoutput(cmd)
> >> > > > +        if s != 0:
> >> > > > +            raise error.TestFail("Get info of image '%s' failed:
> >> > %s" %
> >> > > > +
> >> > (image_name, o))
> >> > > > +        logging.info("Info of image '%s': \n%s" % (image_name,
> >> > o))
> >> > >
> >> > > In the above, we could parse info output and see if at least it
> >> > says
> >> > > that the image is the type we expected it to be.
> >> > >
> >> > > > +    #Subcommand 'qemu-img snapshot' test
> >> > > > +    def snapshot_test():
> >> > > > +        global cmd
> >> > > > +        cmd += " snapshot"
> >> > > > +        for i in range(2):
> >> > > > +            crtcmd = cmd
> >> > > > +            snapshot_name = "snapshot%d" % i
> >> > > > +            crtcmd += " -c %s %s" % (snapshot_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#%d" % i)
> >> > > > +        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):
> >> > > > +            snapshot_name = "snapshot%d" % i
> >> > > > +            delcmd = cmd
> >> > > > +            delcmd += " -d %s %s" % (snapshot_name, image_name)
> >> > > > +            s, o = commands.getstatusoutput(delcmd)
> >> > > > +            if s != 0:
> >> > > > +                raise error.TestFail("Delete snapshot '%s'
> >> > failed: %s" %
> >> > > > +
> >> > (snapshot_name, o))
> >> > > > +
> >> > > > +    #Subcommand 'qemu-img commit' test
> >> > > > +    def commit_test(cmd):
> >> > > > +        pass
> >> > > > +
> >> > > > +    # Here starts test
> >> > > > +    eval("%s_test" % subcommand)
> >>
> >> Aren't you missing a () -- eval("%s_test()" % subcommand)?
> >>
> >> BTW, Yolkfull, have you tried running the test and verifying that it
> >> works?
> >
> > Oh, really missed it. I tested it when using method of passing 'cmd' as a parameter
> > to subcommand functions and it worked fine. So introduced this mistake when changing
> > to use 'global'. Will fix it in next version which will also add 'rebase' subcommand test.
> >
> > Thanks for comments, Michael.
> >
> >>
> >> > >
> >> > > In the above expression, we would also benefit from encapsulating
> >> > all
> >> > > qemu-img tests on a class:
> >> > >
> >> > >       tester = QemuImgTester()
> >> > >       tester.test(subcommand)
> >> > >
> >> > > Or something similar.
> >> > >
> >> > > That said, I was wondering if we could consolidate all qemu-img
> >> > tests to
> >> > > a single execution, instead of splitting it to several variants. We
> >> > > could keep a failure record, execute all tests and fail the entire
> >> > test
> >> > > if any of them failed. It's not like terribly important, but it
> >> > seems
> >> > > more logical to group all qemu-img subcommands testing under a
> >> > single
> >> > > test.
> >> > >
> >> > > Thanks for your work, and please take a look at implementing my
> >> > > suggestions.
> >> >
> >> > > --
> >> > > 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
> >> > --
> >> > 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
> > _______________________________________________
> > Autotest mailing list
> > Autotest@xxxxxxxxxxxxxxx
> > http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
> >
> 
> 
> 
> -- 
> Sudhir Kumar
--
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