qemu_img.py 26.3 KB
Newer Older
L
Lucas Meneghel Rodrigues 已提交
1
import os
2 3
import time
import re
L
Lucas Meneghel Rodrigues 已提交
4 5
import logging
import commands
6 7
import shutil
import tempfile
8

9 10
from autotest.client.shared import error
from autotest.client.shared import utils
11

12 13 14 15 16
from virttest import utils_misc
from virttest import env_process
from virttest import storage
from virttest import data_dir
from virttest import gluster
17 18


19
@error.context_aware
20
def run(test, params, env):
21 22 23 24 25
    """
    'qemu-img' functions test:
    1) Judge what subcommand is going to be tested
    2) Run subcommand test

L
Lucas Meneghel Rodrigues 已提交
26 27 28
    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
29
    """
30 31
    qemu_img_binary = utils_misc.get_qemu_img_binary(params)
    cmd = qemu_img_binary
32 33
    if not os.path.exists(cmd):
        raise error.TestError("Binary of 'qemu-img' not found")
34
    image_format = params["image_format"]
35
    image_size = params.get("image_size", "10G")
F
Feng Yang 已提交
36
    enable_gluster = params.get("enable_gluster", "no") == "yes"
37
    image_name = storage.get_image_filename(params, data_dir.get_data_dir())
38

F
Feng Yang 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    def remove(path):
        try:
            os.remove(path)
        except OSError:
            pass

    def _get_image_filename(img_name, enable_gluster=False, img_fmt=None):
        """
        Generate an image path.

        :param image_name: Force name of image.
        :param enable_gluster: Enable gluster or not.
        :param image_format: Format for image.
        """
        if enable_gluster:
            gluster_uri = gluster.create_gluster_uri(params)
            image_filename = "%s%s" % (gluster_uri, img_name)
            if img_fmt:
                image_filename += ".%s" % img_fmt
        else:
            if img_fmt:
                img_name = "%s.%s" % (img_name, img_fmt)
            image_filename = utils_misc.get_path(data_dir.get_data_dir(),
                                                 img_name)
        return image_filename

65 66 67 68
    def _check(cmd, img):
        """
        Simple 'qemu-img check' function implementation.

L
Lucas Meneghel Rodrigues 已提交
69 70
        :param cmd: qemu-img base command.
        :param img: image to be checked
71 72
        """
        cmd += " check %s" % img
73 74
        error.context("Checking image '%s' by command '%s'" % (img, cmd),
                      logging.info)
75
        try:
76 77 78
            output = utils.system_output(cmd, verbose=False)
        except error.CmdError, err:
            if "does not support checks" in str(err):
79 80
                return (True, "")
            else:
81
                return (False, str(err))
82 83 84 85 86 87 88 89 90
        return (True, output)

    def check_test(cmd):
        """
        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.

L
Lucas Meneghel Rodrigues 已提交
91
        :param cmd: qemu-img base command.
92
        """
F
Feng Yang 已提交
93 94
        test_image = _get_image_filename(params["image_name_dd"],
                                         enable_gluster)
95
        create_image_cmd = params["create_image_cmd"]
96
        create_image_cmd = create_image_cmd % test_image
97 98 99 100 101
        msg = " Create image %s by command %s" % (test_image, create_image_cmd)
        error.context(msg, logging.info)
        utils.system(create_image_cmd, verbose=False)
        status, output = _check(cmd, test_image)
        if not status:
102
            raise error.TestFail("Check image '%s' failed with error: %s" %
103
                                 (test_image, output))
104
        for fmt in params["supported_image_formats"].split():
105 106
            output_image = test_image + ".%s" % fmt
            _convert(cmd, fmt, test_image, output_image)
107 108
            status, output = _check(cmd, output_image)
            if not status:
109
                raise error.TestFail("Check image '%s' got error: %s" %
110
                                     (output_image, output))
F
Feng Yang 已提交
111 112
            remove(output_image)
        remove(test_image)
113 114

    def _create(cmd, img_name, fmt, img_size=None, base_img=None,
115
                base_img_fmt=None, encrypted="no",
116
                preallocated="off", cluster_size=None):
117 118 119
        """
        Simple wrapper of 'qemu-img create'

L
Lucas Meneghel Rodrigues 已提交
120 121 122 123 124 125 126
        :param cmd: qemu-img base command.
        :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
127 128 129
        :param preallocated: if preallocation when create image,
                             allowed values: off, metadata. Default is "off"
        :param cluster_size: the cluster size for the image
130 131
        """
        cmd += " create"
132

133 134 135 136 137 138
        if encrypted == "yes":
            cmd += " -e"
        if base_img:
            cmd += " -b %s" % base_img
            if base_img_fmt:
                cmd += " -F %s" % base_img_fmt
139

140
        cmd += " -f %s" % fmt
141 142 143 144 145 146 147

        options = []
        if preallocated != "off":
            options.append("preallocation=%s" % preallocated)
        if cluster_size is not None:
            options.append("cluster_size=%s" % cluster_size)
        if options:
148
            cmd += " -o %s" % ",".join(options)
149

150 151 152
        cmd += " %s" % img_name
        if img_size:
            cmd += " %s" % img_size
153

154 155 156 157 158 159 160
        msg = "Creating image %s by command %s" % (img_name, cmd)
        error.context(msg, logging.info)
        utils.system(cmd, verbose=False)
        status, out = _check(qemu_img_binary, img_name)
        if not status:
            raise error.TestFail("Check image '%s' got error: %s" %
                                 (img_name, out))
161 162 163 164 165

    def create_test(cmd):
        """
        Subcommand 'qemu-img create' test.

L
Lucas Meneghel Rodrigues 已提交
166
        :param cmd: qemu-img base command.
167
        """
168
        image_large = params["image_name_large"]
169 170
        device = params.get("device")
        if not device:
F
Feng Yang 已提交
171 172
            img = _get_image_filename(image_large, enable_gluster,
                                      image_format)
173 174
        else:
            img = device
175
        _create(cmd, img_name=img, fmt=image_format,
176
                img_size=params["image_size_large"],
177 178
                preallocated=params.get("preallocated", "off"),
                cluster_size=params.get("image_cluster_size"))
F
Feng Yang 已提交
179
        remove(img)
180

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    def send_signal(timeout=360):
        """
        send signal "SIGUSR1" to qemu-img without the option -p
        to report progress
        """
        logging.info("Send signal to qemu-img")
        end_time = time.time() + timeout
        while time.time() < end_time:
            time.sleep(1)
            status = utils.system("kill -SIGUSR1 `pidof qemu-img`",
                                  ignore_status=True)
            if status == 0:
                return None
        logging.info("Fail to get pid of qemu-img")

    def check_command_output(CmdResult):
        """
        Check standard error or standard output of command
        : param CmdResult: a list of CmdResult objects
        """
        logging.info("Check result of command")
        check_output = params.get("check_output", "exit_status")
        if not hasattr(CmdResult, check_output):
            raise error.TestError("Unknown check output '%s'" % check_output)
        output = getattr(CmdResult, check_output)
        if check_output == "exit_status" and output == 0:
            return None
        if check_output == "exit_status" and output != 0:
            err_msg = "Get nonzero exit status(%d) '%s'"
            raise error.TestFail(err_msg % (output, CmdResult.command))
        pattern = params.get("command_result_pattern")
        if not re.findall(pattern, output):
            err_msg = "Fail to get expected result!"
            err_msg += "Output: %s, expected pattern: %s" % (output, pattern)
            raise error.TestFail(err_msg)

217
    def _convert(cmd, output_fmt, img_name, output_filename,
L
Lucas Meneghel Rodrigues 已提交
218
                 fmt=None, compressed="no", encrypted="no"):
219 220 221
        """
        Simple wrapper of 'qemu-img convert' function.

L
Lucas Meneghel Rodrigues 已提交
222 223 224 225 226 227 228
        :param cmd: qemu-img base command.
        :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
229 230 231 232 233 234
        """
        cmd += " convert"
        if compressed == "yes":
            cmd += " -c"
        if encrypted == "yes":
            cmd += " -e"
235 236 237
        show_progress = params.get("show_progress", "")
        if show_progress == "on":
            cmd += " -p"
238 239 240
        if fmt:
            cmd += " -f %s" % fmt
        cmd += " -O %s" % output_fmt
241 242 243 244 245 246 247 248
        options = params.get("qemu_img_options")
        if options:
            options = options.split()
            cmd += " -o "
            for option in options:
                value = params.get(option)
                cmd += "%s=%s," % (option, value)
            cmd = cmd.rstrip(",")
249
        cmd += " %s %s" % (img_name, output_filename)
250 251 252
        msg = "Converting '%s' from format '%s'" % (img_name, fmt)
        msg += " to '%s'" % output_fmt
        error.context(msg, logging.info)
253 254 255 256
        if show_progress == "off":
            bg = utils.InterruptedThread(send_signal)
            bg.start()
        check_command_output(utils.run(cmd, ignore_status=True))
257 258 259 260 261

    def convert_test(cmd):
        """
        Subcommand 'qemu-img convert' test.

L
Lucas Meneghel Rodrigues 已提交
262
        :param cmd: qemu-img base command.
263
        """
264
        dest_img_fmt = params["dest_image_format"]
265 266
        output_filename = "%s.converted_%s.%s" % (image_name,
                                                  dest_img_fmt, dest_img_fmt)
267 268

        _convert(cmd, dest_img_fmt, image_name, output_filename,
L
Lucas Meneghel Rodrigues 已提交
269
                 image_format, params["compressed"], params["encrypted"])
270 271 272 273
        orig_img_name = params.get("image_name")
        img_name = "%s.%s.converted_%s" % (orig_img_name,
                                           image_format, dest_img_fmt)
        _boot(img_name, dest_img_fmt)
274 275

        if dest_img_fmt == "qcow2":
276 277
            status, output = _check(cmd, output_filename)
            if status:
F
Feng Yang 已提交
278
                remove(output_filename)
279 280
            else:
                raise error.TestFail("Check image '%s' failed with error: %s" %
281
                                     (output_filename, output))
282
        else:
F
Feng Yang 已提交
283
            remove(output_filename)
284 285 286 287 288

    def _info(cmd, img, sub_info=None, fmt=None):
        """
        Simple wrapper of 'qemu-img info'.

L
Lucas Meneghel Rodrigues 已提交
289 290 291 292
        :param cmd: qemu-img base command.
        :param img: image file
        :param sub_info: sub info, say 'backing file'
        :param fmt: image format
293 294 295 296 297 298 299 300
        """
        cmd += " info"
        if fmt:
            cmd += " -f %s" % fmt
        cmd += " %s" % img

        try:
            output = utils.system_output(cmd)
301 302
        except error.CmdError, err:
            logging.error("Get info of image '%s' failed: %s", img, str(err))
303 304 305 306 307 308 309
            return None

        if not sub_info:
            return output

        sub_info += ": (.*)"
        matches = re.findall(sub_info, output)
310 311 312
        if "virtual size" in sub_info:
            p = re.compile(r'\.0*(G|K)$')
            return p.sub(r'\1', matches[0].split()[0])
313 314 315 316 317 318 319 320
        if matches:
            return matches[0]
        return None

    def info_test(cmd):
        """
        Subcommand 'qemu-img info' test.

L
Lucas Meneghel Rodrigues 已提交
321
        :param cmd: qemu-img base command.
322 323 324
        """
        img_info = _info(cmd, image_name)
        logging.info("Info of image '%s':\n%s", image_name, img_info)
325
        if image_format not in img_info:
326 327
            raise error.TestFail("Got unexpected format of image '%s'"
                                 " in info test" % image_name)
328
        if image_size not in img_info:
329 330 331 332 333 334 335
            raise error.TestFail("Got unexpected size of image '%s'"
                                 " in info test" % image_name)

    def snapshot_test(cmd):
        """
        Subcommand 'qemu-img snapshot' test.

L
Lucas Meneghel Rodrigues 已提交
336
        :param cmd: qemu-img base command.
337 338 339 340 341 342
        """
        cmd += " snapshot"
        for i in range(2):
            crtcmd = cmd
            sn_name = "snapshot%d" % i
            crtcmd += " -c %s %s" % (sn_name, image_name)
343
            msg = "Created snapshot '%s' in '%s' by command %s" % (sn_name,
F
Feng Yang 已提交
344 345
                                                                   image_name,
                                                                   crtcmd)
346 347 348
            error.context(msg, logging.info)
            status, output = commands.getstatusoutput(crtcmd)
            if status != 0:
349
                raise error.TestFail("Create snapshot failed via command: %s;"
350
                                     "Output is: %s" % (crtcmd, output))
351 352
        listcmd = cmd
        listcmd += " -l %s" % image_name
353 354
        status, out = commands.getstatusoutput(listcmd)
        if not ("snapshot0" in out and "snapshot1" in out and status == 0):
355
            raise error.TestFail("Snapshot created failed or missed;"
356
                                 "snapshot list is: \n%s" % out)
357 358 359 360
        for i in range(2):
            sn_name = "snapshot%d" % i
            delcmd = cmd
            delcmd += " -d %s %s" % (sn_name, image_name)
361 362 363 364
            msg = "Delete snapshot '%s' by command %s" % (sn_name, delcmd)
            error.context(msg, logging.info)
            status, output = commands.getstatusoutput(delcmd)
            if status != 0:
365
                raise error.TestFail("Delete snapshot '%s' failed: %s" %
366
                                     (sn_name, output))
367 368 369 370

    def commit_test(cmd):
        """
        Subcommand 'qemu-img commit' test.
C
Cong Li 已提交
371 372 373
        1) Create a overlay file of the qemu harddisk specified by image_name.
        2) Start a VM using the overlay file as its harddisk.
        3) Touch a file "commit_testfile" in the overlay file, and shutdown the
374
           VM.
C
Cong Li 已提交
375
        4) Commit the change to the backing harddisk by executing
376
           "qemu-img commit" command.
C
Cong Li 已提交
377 378
        5) Start the VM using the backing harddisk.
        6) Check if the file "commit_testfile" exists.
379

L
Lucas Meneghel Rodrigues 已提交
380
        :param cmd: qemu-img base command.
381 382 383
        """

        logging.info("Commit testing started!")
F
Feng Yang 已提交
384 385 386
        image_name = storage.get_image_filename(params,
                                                data_dir.get_data_dir())
        pre_name = '.'.join(image_name.split('.')[:-1])
387
        image_format = params.get("image_format", "qcow2")
F
Feng Yang 已提交
388
        overlay_file_name = "%s_overlay.%s" % (pre_name, image_format)
389 390 391 392 393 394 395 396
        file_create_cmd = params.get("file_create_cmd",
                                     "touch /commit_testfile")
        file_info_cmd = params.get("file_info_cmd",
                                   "ls / | grep commit_testfile")
        file_exist_chk_cmd = params.get("file_exist_chk_cmd",
                                        "[ -e /commit_testfile ] && echo $?")
        file_del_cmd = params.get("file_del_cmd",
                                  "rm -f /commit_testfile")
397
        try:
C
Cong Li 已提交
398
            # Remove the existing overlay file
F
Feng Yang 已提交
399 400
            if os.path.isfile(overlay_file_name):
                remove(overlay_file_name)
401

C
Cong Li 已提交
402
            # Create the new overlay file
F
Feng Yang 已提交
403 404 405
            create_cmd = "%s create -b %s -f %s %s" % (cmd, image_name,
                                                       image_format,
                                                       overlay_file_name)
C
Cong Li 已提交
406
            msg = "Create overlay file by command: %s" % create_cmd
407
            error.context(msg, logging.info)
408
            try:
409 410
                utils.system(create_cmd, verbose=False)
            except error.CmdError:
C
Cong Li 已提交
411
                raise error.TestFail("Could not create a overlay file!")
412
            logging.info("overlay file (%s) created!" % overlay_file_name)
413

C
Cong Li 已提交
414
            # Set the qemu harddisk to the overlay file
L
Lucas Meneghel Rodrigues 已提交
415 416
            logging.info(
                "Original image_name is: %s", params.get('image_name'))
417
            params['image_name'] = '.'.join(overlay_file_name.split('.')[:-1])
418 419 420
            logging.info("Param image_name changed to: %s",
                         params.get('image_name'))

C
Cong Li 已提交
421
            msg = "Start a new VM, using overlay file as its harddisk"
422
            error.context(msg, logging.info)
423
            vm_name = params['main_vm']
424 425
            env_process.preprocess_vm(test, params, env, vm_name)
            vm = env.get_vm(vm_name)
426
            vm.verify_alive()
427 428 429
            timeout = int(params.get("login_timeout", 360))
            session = vm.wait_for_login(timeout=timeout)

C
Cong Li 已提交
430
            # Do some changes to the overlay_file harddisk
431
            try:
432 433 434 435 436
                output = session.cmd(file_create_cmd)
                logging.info("Output of %s: %s", file_create_cmd, output)
                output = session.cmd(file_info_cmd)
                logging.info("Output of %s: %s", file_info_cmd, output)
            except Exception, err:
437
                raise error.TestFail("Could not create commit_testfile in the "
C
Cong Li 已提交
438
                                     "overlay file %s" % err)
439 440
            vm.destroy()

L
Lucas Meneghel Rodrigues 已提交
441
            # Execute the commit command
F
Feng Yang 已提交
442 443
            cmitcmd = "%s commit -f %s %s" % (cmd, image_format,
                                              overlay_file_name)
L
Lucas Meneghel Rodrigues 已提交
444
            error.context("Committing image by command %s" % cmitcmd,
445
                          logging.info)
446
            try:
447 448
                utils.system(cmitcmd, verbose=False)
            except error.CmdError:
C
Cong Li 已提交
449
                raise error.TestFail("Could not commit the overlay file")
450
            logging.info("overlay file (%s) committed!" % overlay_file_name)
451

452 453
            msg = "Start a new VM, using image_name as its harddisk"
            error.context(msg, logging.info)
454
            params['image_name'] = pre_name
455
            vm_name = params['main_vm']
456 457
            env_process.preprocess_vm(test, params, env, vm_name)
            vm = env.get_vm(vm_name)
458
            vm.verify_alive()
459 460 461
            timeout = int(params.get("login_timeout", 360))
            session = vm.wait_for_login(timeout=timeout)
            try:
462 463 464
                output = session.cmd(file_exist_chk_cmd)
                logging.info("Output of %s: %s", file_exist_chk_cmd, output)
                session.cmd(file_del_cmd)
465 466 467 468 469 470
            except Exception:
                raise error.TestFail("Could not find commit_testfile after a "
                                     "commit")
            vm.destroy()

        finally:
C
Cong Li 已提交
471
            # Remove the overlay file
F
Feng Yang 已提交
472 473
            if os.path.isfile(overlay_file_name):
                remove(overlay_file_name)
474 475 476 477 478

    def _rebase(cmd, img_name, base_img, backing_fmt, mode="unsafe"):
        """
        Simple wrapper of 'qemu-img rebase'.

L
Lucas Meneghel Rodrigues 已提交
479 480 481 482 483
        :param cmd: qemu-img base command.
        :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
484 485
        """
        cmd += " rebase"
486
        show_progress = params.get("show_progress", "")
487 488
        if mode == "unsafe":
            cmd += " -u"
489 490
        if show_progress == "on":
            cmd += " -p"
491
        cmd += " -b %s -F %s %s" % (base_img, backing_fmt, img_name)
492
        msg = "Trying to rebase '%s' to '%s' by command %s" % (img_name,
L
Lucas Meneghel Rodrigues 已提交
493
                                                               base_img, cmd)
494
        error.context(msg, logging.info)
495 496 497 498
        if show_progress == "off":
            bg = utils.InterruptedThread(send_signal)
            bg.start()
        check_command_output(utils.run(cmd))
499 500 501 502 503 504 505 506 507 508

    def rebase_test(cmd):
        """
        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.

L
Lucas Meneghel Rodrigues 已提交
509
        :param cmd: qemu-img base command.
510
        """
511
        if 'rebase' not in utils.system_output(cmd + ' --help',
512 513 514 515
                                               ignore_status=True):
            raise error.TestNAError("Current kvm user space version does not"
                                    " support 'rebase' subcommand")
        sn_fmt = params.get("snapshot_format", "qcow2")
516
        sn1 = params["image_name_snapshot1"]
F
Feng Yang 已提交
517
        sn1 = _get_image_filename(sn1, enable_gluster, sn_fmt)
518
        base_img = storage.get_image_filename(params, data_dir.get_data_dir())
519 520 521
        _create(cmd, sn1, sn_fmt, base_img=base_img, base_img_fmt=image_format)

        # Create snapshot2 based on snapshot1
522
        sn2 = params["image_name_snapshot2"]
F
Feng Yang 已提交
523
        sn2 = _get_image_filename(sn2, enable_gluster, sn_fmt)
524 525
        _create(cmd, sn2, sn_fmt, base_img=sn1, base_img_fmt=sn_fmt)

526
        rebase_mode = params.get("rebase_mode", "safe")
527
        if rebase_mode == "unsafe":
F
Feng Yang 已提交
528
            remove(sn1)
529 530

        _rebase(cmd, sn2, base_img, image_format, mode=rebase_mode)
531
        # Boot snapshot image after rebase
F
Feng Yang 已提交
532 533
        img_format = sn2.split('.')[-1]
        img_name = ".".join(sn2.split('.')[:-1])
534
        _boot(img_name, img_format)
535 536 537

        # Check sn2's format and backing_file
        actual_base_img = _info(cmd, sn2, "backing file")
538
        base_img_name = os.path.basename(base_img)
539
        if base_img_name not in actual_base_img:
540 541 542
            raise error.TestFail("After rebase the backing_file of 'sn2' is "
                                 "'%s' which is not expected as '%s'"
                                 % (actual_base_img, base_img_name))
543 544
        status, output = _check(cmd, sn2)
        if not status:
545
            raise error.TestFail("Check image '%s' failed after rebase;"
546
                                 "got error: %s" % (sn2, output))
F
Feng Yang 已提交
547 548
        remove(sn2)
        remove(sn1)
549

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
    def _amend(cmd, img_name, img_fmt, options):
        """
        Simple wrapper of 'qemu-img amend'.

        :param cmd: qemu-img base command
        :param img_name: image name that should be amended
        :param img_fmt: image format
        :param options: a comma separated list of format specific options
        """

        msg = "Amend '%s' with options '%s'" % (img_name, options)
        cmd += " amend"
        if img_fmt:
            cmd += " -f %s" % img_fmt
        cache = params.get("cache_mode", '')
        if cache:
            cmd += " -t %s" % cache
        if options:
            cmd += " -o "
            for option in options:
                cmd += "%s=%s," % (option, params.get(option))
            cmd = cmd.rstrip(',')
        cmd += " %s" % img_name
        error.context(msg, logging.info)
        check_command_output(utils.run(cmd, ignore_status=True))

    def amend_test(cmd):
        """
        Subcommand 'qemu-img amend' test
        Amend the image format specific options for the image file

        :param cmd: qemu-img base command.
        """
        img_name = params.get("image_name_stg")
        img_fmt = params.get("image_format_stg", "qcow2")
        options = params.get("qemu_img_options", "").split()
        check_output = params.get("check_output", "exit_status")
        img = _get_image_filename(img_name, img_fmt=img_fmt)
        _amend(cmd, img, img_fmt, options)
        if check_output == "exit_status":
            for option in options:
                expect = params.get(option)
                if option == "size":
                    option = "virtual size"
                actual = _info(cmd, img, option)
                if actual is not None and actual != expect:
                    msg = "Get wrong %s from image %s!" % (option, img_name)
                    msg += "Expect: %s, actual: %s" % (expect, actual)
                    raise error.TestFail(msg)
        status, output = _check(cmd, img)
        if not status:
            raise error.TestFail("Check image '%s' failed after rebase;"
                                 "got error: %s" % (img, output))

604 605 606 607 608 609 610
    def _boot(img_name, img_fmt):
        """
        Boot test:
        1) Login guest
        2) Run dd in rhel guest
        3) Shutdown guest

L
Lucas Meneghel Rodrigues 已提交
611 612
        :param img_name: image name
        :param img_fmt: image format
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
        """
        params['image_name'] = img_name
        params['image_format'] = img_fmt
        image_name = "%s.%s" % (img_name, img_fmt)
        msg = "Try to boot vm with image %s" % image_name
        error.context(msg, logging.info)
        vm_name = params.get("main_vm")
        dd_timeout = int(params.get("dd_timeout", 60))
        params['vms'] = vm_name
        env_process.preprocess_vm(test, params, env, vm_name)
        vm = env.get_vm(params.get("main_vm"))
        vm.verify_alive()
        login_timeout = int(params.get("login_timeout", 360))
        session = vm.wait_for_login(timeout=login_timeout)

        # Run dd in linux guest
        if params.get("os_type") == 'linux':
            cmd = "dd if=/dev/zero of=/mnt/test bs=1000 count=1000"
            status = session.get_command_status(cmd, timeout=dd_timeout)
            if status != 0:
                raise error.TestError("dd failed")

635
        error.context("Shutdown guest", logging.info)
636
        try:
X
Xu Tian 已提交
637 638 639 640 641 642 643
            vm.graceful_shutdown(timeout=login_timeout)
        except Exception:
            image_filename = _get_image_filename(img_name,
                                                 enable_gluster,
                                                 img_fmt)
            backup_img_chain(image_filename)
            raise
644
        finally:
X
Xu Tian 已提交
645 646
            vm.destroy(gracefully=True)
            utils.system("sync")
647

648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
    def backup_img_chain(image_file):
        """
        Backup whole image in a image chain;
        """
        mount_point = tempfile.mkdtemp(dir=test.resultsdir)
        qemu_img = utils_misc.get_qemu_img_binary(params)
        if enable_gluster:
            g_uri = gluster.create_gluster_uri(params)
            gluster.glusterfs_mount(g_uri, mount_point)
            image_name = os.path.basename(image_file)
            image_file = os.path.join(mount_point, image_name)
        logging.warn("backup %s to %s" % (image_file, test.resultsdir))
        shutil.copy(image_file, test.resultsdir)
        backing_file = _info(qemu_img, image_file, "backing file", None)
        if backing_file:
            backup_img_chain(backing_file)
        elif enable_gluster:
            utils_misc.umount(g_uri, mount_point,
                              "glusterfs", False,
                              "fuse.glusterfs")
            shutil.rmtree(mount_point)
        return None

671
    # Here starts test
672
    subcommand = params["subcommand"]
673
    error.context("Running %s_test(cmd)" % subcommand, logging.info)
674
    eval("%s_test(cmd)" % subcommand)