示例#1
0
def run(test, params, env):
    """
        Test cdrom operation with throttle feature.
        1) Boot up guest with cdrom device in throttle groups.
        2) Query cdrom device.
        3) Execute change media operation
        4) Query cdrom device
        5) Execute eject media operation
    """

    error_context.context("Get the main VM", test.log.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    vm.wait_for_login(timeout=120)

    p_dict = {"removable": True, "drv": "throttle"}
    device_name = vm.get_block(p_dict)

    if device_name is None:
        test.fail("Fail to get cdrom device with drv throttle")

    test.log.info("Found cdrom device %s", device_name)

    eject_check = QMPEventCheckCDEject(vm, device_name)
    change_check = QMPEventCheckCDChange(vm, device_name)

    monitor = vm.get_monitors_by_type('qmp')[0]
    if vm.check_capability(Flags.BLOCKDEV):
        qdev = vm.devices.get_qdev_by_drive(device_name)
        monitor.blockdev_open_tray(qdev, force=True)

    # change media
    new_img_name = params.get("new_img_name")
    error_context.context("Insert new image to device.", test.log.info)
    with change_check:
        vm.change_media(device_name, new_img_name)

    # After change medium throttle property is expected to be removed
    error_context.context("Query cdrom device with new image.", test.log.info)
    p_dict = {"removable": True, "file": new_img_name}
    device_name = vm.get_block(p_dict)

    if device_name is None:
        test.fail("Fail to get cdrom device with new image after change")

    # eject media
    error_context.context("Eject device.", test.log.info)
    with eject_check:
        monitor.blockdev_open_tray(qdev, force=True)
        monitor.blockdev_remove_medium(qdev)
示例#2
0
def run(test, params, env):
    """
    change a removable media:
    1) Boot VM with QMP/human monitor enabled.
    2) Connect to QMP/human monitor server.
    3) Eject original cdrom.
    4) Eject original cdrom for second time.
    5) Insert new image to cdrom.
    6) Eject device after add new image by change command.
    7) Insert original cdrom to cdrom.
    8) Try to eject non-removable device w/o force option.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment
    """

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    logging.info("Wait until device is ready")
    time.sleep(10)

    def check_block(block):
        return True if block in str(vm.monitor.info("block")) else False

    orig_img_name = params.get("cdrom_cd1")
    p_dict = {"file": orig_img_name}
    device_name = vm.get_block(p_dict)
    if device_name is None:
        msg = "Fail to get device using image %s" % orig_img_name
        test.fail(msg)

    eject_check = QMPEventCheckCDEject(vm, device_name)
    change_check = QMPEventCheckCDChange(vm, device_name)

    # eject first time
    error_context.context("Eject original device.", logging.info)
    with eject_check:
        vm.eject_cdrom(device_name)
    if check_block(orig_img_name):
        test.fail("Fail to eject cdrom %s. " % orig_img_name)

    # eject second time
    error_context.context("Eject original device for second time",
                          logging.info)
    with eject_check:
        vm.eject_cdrom(device_name)

    # change media
    new_img_name = params.get("new_img_name")
    error_context.context("Insert new image to device.", logging.info)
    with change_check:
        vm.change_media(device_name, new_img_name)
    if not check_block(new_img_name):
        test.fail("Fail to change cdrom to %s." % new_img_name)

    # eject after change
    error_context.context("Eject device after add new image by change command",
                          logging.info)
    with eject_check:
        vm.eject_cdrom(device_name)
    if check_block(new_img_name):
        test.fail("Fail to eject cdrom %s." % orig_img_name)

    # change back to orig_img_name
    error_context.context(
        "Insert %s to device %s" % (orig_img_name, device_name), logging.info)
    with change_check:
        vm.change_media(device_name, orig_img_name)
    if not check_block(orig_img_name):
        test.fail("Fail to change cdrom to %s." % orig_img_name)

    # change again
    error_context.context(
        "Insert %s to device %s" % (new_img_name, device_name), logging.info)
    with change_check:
        vm.change_media(device_name, new_img_name)
    if not check_block(new_img_name):
        test.fail("Fail to change cdrom to %s." % new_img_name)

    # eject non-removable
    error_context.context("Try to eject non-removable device", logging.info)
    p_dict = {"removable": False}
    device_name = vm.get_block(p_dict)
    if vm.check_capability(Flags.BLOCKDEV):
        sys_image = QemuImg(params, data_dir.get_data_dir(),
                            params['images'].split()[0])
        device_name = vm.get_block({"filename": sys_image.image_filename})
    if device_name is None:
        test.error("Could not find non-removable device")
    try:
        if params.get("force_eject", "no") == "yes":
            vm.eject_cdrom(device_name, force=True)
        else:
            vm.eject_cdrom(device_name)
    except Exception as e:
        if "is not removable" not in str(e):
            test.fail(e)
        logging.debug("Catch exception message: %s" % e)
    if not check_block(device_name):
        test.fail("Could remove non-removable device!")

    session.close()
示例#3
0
def run(test, params, env):
    """
    Test block devices with migration..

        Scenario "with_scsi_on2off":
            1) Boot guest with scsi=on on src host.
            2) Boot guest with scsi=off on dst host.
            3) Do live Migration.

        Scenario "with_change_cdrom":
            1) Run qemu with specified cdrom loaded.
            2) Check the cdrom info by qmp.
            3) Check the cdrom's size inside guest.
            4) Eject cdrom, and check the info again.
            5) Load a new cdrom image, and check the cdrom info again.
            6) Check the cdrom's size inside guest.
            7) Start dest vm with new iso file in listening mode.
            8) Migrate from src to dst.
            9) Do system_reset in dst vm.

        Scenario "with_dataplane_on2off":
            1) Start VM with dataplane (both system disk and data disk).
            2) For Windows: check whether viostor.sys verifier enabled in guest.
            3) Do live migration.
            4) Do iozone testing after migration.
            5) Reboot guest.

        Scenario "with_post_copy.with_mem_stress":
            1) Start source VM with virtio-scsi-pci (system and data disks)
            2) For Windows: check whether viostor.sys verifier enabled in guest.
            3) Run stress guest.
            4) Start dst guest with "-incoming tcp:x:xxxx"/
            5) On source qemu & dst qemu, set postcopy mode on.
            6) Do live migration.
            7) Migration could not finish under high stress,
               then change into postcopy mode.
            8) Repeat step 4~7 to migrate guest back to source host.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    class _StressThread(threading.Thread):
        def __init__(self, target, exit_event, args=()):
            threading.Thread.__init__(self)
            self.exc_info = None
            self.exit_event = exit_event
            self._target = target
            self._args = args

        def run(self):
            try:
                self._target(*self._args)
            except Exception as e:
                logging.error(str(e))
                self.exc_info = sys.exc_info()
                self.exit_event.set()

    def scp_package(src, dst):
        """ Copy file from the host to the guest. """
        scp_to_remote(vm.get_address(), '22', params.get('username'),
                      params.get('password'), src, dst)

    def unpack_package(session, src, dst):
        """ Unpack the package. """
        session.cmd('tar -xvf %s -C %s' % (src, dst))

    def install_package(session, src, dst):
        """ Install the package. """
        cmd = ' && '.join(
            ("cd %s && ./configure --prefix=%s", "make && make install"))
        session.cmd(cmd % (src, dst), 300)

    def cleanup(session, src):
        """ Remove files. """
        session.cmd('rm -rf %s' % src)

    def _get_data_disks_linux():
        """ Get the data disks by serial or wwn options in linux. """
        for data_image in params['images'].split()[1:]:
            extra_params = params.get("blk_extra_params_%s" % data_image, '')
            match = re.search(r"(serial|wwn)=(\w+)", extra_params, re.M)
            if match:
                drive_id = match.group(2)
            else:
                continue
            drive_path = utils_misc.get_linux_drive_path(session, drive_id)
            if not drive_path:
                test.error("Failed to get '%s' drive path" % data_image)
            yield drive_path[5:], params.object_params(
                data_image)['image_size']

    def _get_data_disks_win():
        """ Get the data disks in windows. """
        for data_image in params['images'].split()[1:]:
            size = params.object_params(data_image)['image_size']
            yield utils_disk.get_windows_disks_index(session, size)[0], size

    def get_data_disks():
        """ Get the data disks. """
        _get_disks = _get_data_disks_win if windows else _get_data_disks_linux
        for disk, size in _get_disks():
            yield disk, size

    def format_data_disks():
        """ Format the data disks. """
        for disk, size in get_data_disks():
            if windows:
                if not utils_disk.update_windows_disk_attributes(
                        session, disk):
                    test.fail("Failed to update windows disk attributes.")
            yield utils_disk.configure_empty_disk(session, disk, size,
                                                  os_type)[0]

    def run_iozone(timeout):
        """ Do iozone testing inside guest. """
        logging.info("Do iozone testing on data disks.")
        iozone = generate_instance(params, vm, 'iozone')
        try:
            for target in format_data_disks():
                iozone.run(stress_options.format(target), timeout)
        finally:
            iozone.clean()

    def run_stressapptest(timeout):
        """ Do stressapptest testing inside guest. """
        logging.info("Do stressapptest testing on data disks.")
        sub_session = vm.wait_for_login(timeout=360)
        try:
            host_path = os.path.join(data_dir.get_deps_dir('stress'),
                                     'stressapptest.tar')
            scp_package(host_path, '/home/')
            unpack_package(sub_session, '/home/stressapptest.tar', '/home')
            install_package(sub_session, '/home/stressapptest',
                            '/home/stressapptest')
            stress_bin_path = '/home/stressapptest/bin/stressapptest'
            sub_session.cmd('{} {}'.format(stress_bin_path, stress_options),
                            timeout)
        finally:
            cleanup(sub_session, '/home/stressapptest*')
            sub_session.close()

    def run_stress_background(timeout):
        """ Run stress inside guest. """
        thread = _StressThread(stress_maps[stress_name], exit_event,
                               (timeout, ))
        thread.start()
        return thread

    def get_cdrom_size():
        """ Get the size of cdrom device inside guest. """
        error_context.context("Get the cdrom's size in guest.", logging.info)
        cmd = params["check_size"]
        if not utils_misc.wait_for(
                lambda: re.search(r'(\d+)', session.cmd(cmd), re.M), 10):
            test.fail('Failed to get the cdrom\'s size.')
        cdrom_size = re.search(r'(\d+)', session.cmd(cmd), re.M).group(1)
        cdrom_size = int(cdrom_size) * 512 if not windows else int(cdrom_size)
        logging.info("The cdrom's size is %s in guest.", cdrom_size)
        return cdrom_size

    def get_iso_size(iso_file):
        """ Get the size of iso on host."""
        error_context.context("Get the iso size on host.", logging.info)
        return int(
            process.system_output('ls -l %s | awk \'{print $5}\'' % iso_file,
                                  shell=True).decode())

    def compare_cdrom_size(iso_file):
        """ Compare the cdrom's size between host and guest. """
        error_context.context(
            "Compare the cdrom's size between host and guest.", logging.info)
        ios_size = get_iso_size(iso_file)
        if not utils_misc.wait_for(
                lambda: get_cdrom_size() == ios_size, 30, step=3):
            test.fail(
                'The size inside guest is not equal to iso size on host.')
        return get_cdrom_size()

    def check_cdrom_info_by_qmp(check_items):
        """ Check the cdrom device info by qmp. """
        error_context.context(
            'Check if the info \"%s\" are match with the output of query-block.'
            % str(check_items), logging.info)
        blocks = vm.monitor.info_block()
        for key, val in check_items.items():
            if (key == 'device'
                    and val == dev_id) or blocks[dev_id][key] == val:
                continue
            test.fail('No such \"%s: %s\" in the output of query-block.' %
                      (key, val))

    def check_block(block):
        """ Check if the block device is existed in query-block."""
        return True if block in str(vm.monitor.info("block")) else False

    def eject_cdrom():
        """ Eject cdrom. """
        error_context.context("Eject the original device.", logging.info)
        with eject_check:
            vm.eject_cdrom(device_name, True)
        if check_block(orig_img_name):
            test.fail("Failed to eject cdrom %s. " % orig_img_name)

    def change_cdrom():
        """ Change cdrom. """
        new_img_name = params["cdrom_new_file"]
        error_context.context("Insert new image to device.", logging.info)
        with change_check:
            vm.change_media(device_name, new_img_name)
        if not check_block(new_img_name):
            test.fail("Fail to change cdrom to %s." % new_img_name)

    def change_vm_power():
        """ Change the vm power. """
        method, command = params['command_opts'].split(',')
        logging.info('Sending command(%s): %s', method, command)
        if method == 'shell':
            p_session = vm.wait_for_login(timeout=360)
            p_session.sendline(command)
            p_session.close()
        else:
            getattr(vm.monitor, command)()

    def check_vm_status(timeout=600):
        """ Check the status of vm. """
        action = 'shutdown' if shutdown_vm else 'login'
        if not getattr(vm, 'wait_for_%s' % action)(timeout=timeout):
            test.fail('Failed to %s vm.' % action)

    def set_dst_params():
        """ Set the params of dst vm. """
        for name, val in ast.literal_eval(params.get('set_dst_params',
                                                     '{}')).items():
            vm.params[name] = val

    def ping_pong_migration(repeat_times):
        """ Do ping pong migration. """
        for i in range(repeat_times):
            set_dst_params()
            if i % 2 == 0:
                logging.info("Round %s ping...", str(i / 2))
            else:
                logging.info("Round %s pong...", str(i / 2))
            if do_migration_background:
                args = (mig_timeout, mig_protocol, mig_cancel_delay)
                kwargs = {
                    'migrate_capabilities': capabilities,
                    'mig_inner_funcs': inner_funcs,
                    'env': env
                }
                migration_thread = utils_misc.InterruptedThread(
                    vm.migrate, args, kwargs)
                migration_thread.start()
                if not utils_misc.wait_for(
                        lambda:
                    (bool(vm.monitor.query("migrate")) and
                     ('completed' != vm.monitor.query("migrate")['status'])),
                        30):
                    test.error('Migration thread is not alive.')
                vm.monitor.wait_for_migrate_progress(
                    float(params['percent_start_post_copy']))
                vm.monitor.migrate_start_postcopy()
                migration_thread.join()
                logging.info('Migration thread is done.')
            else:
                vm.migrate(mig_timeout,
                           mig_protocol,
                           mig_cancel_delay,
                           migrate_capabilities=capabilities,
                           mig_inner_funcs=inner_funcs,
                           env=env)

    def bg_stress_is_alive(session, name):
        """ Check whether the background stress is alive. """
        return session.cmd_output('pgrep -xl %s' % name)

    shutdown_vm = params.get('shutdown_vm', 'no') == 'yes'
    reboot = params.get('reboot_vm', 'no') == 'yes'
    with_cdrom = params.get('with_cdrom', 'no') == 'yes'
    os_type = params['os_type']
    windows = os_type == 'windows'
    src_desc = params.get('src_addition_desc', '')
    dst_desc = params.get('dst_addition_desc', '')

    mig_timeout = float(params.get("mig_timeout", "3600"))
    mig_protocol = params.get("migration_protocol", "tcp")
    mig_cancel_delay = int(params.get("mig_cancel") == "yes") * 2
    inner_funcs = ast.literal_eval(params.get("migrate_inner_funcs", "[]"))
    capabilities = ast.literal_eval(params.get("migrate_capabilities", "{}"))
    do_migration_background = params.get('do_migration_background',
                                         'no') == 'yes'

    stress_name = params.get('stress_name')
    stress_maps = {'iozone': run_iozone, 'stressapptest': run_stressapptest}
    stress_options = params.get('stress_options')
    stress_timeout = int(params.get('stress_timeout', '1800'))
    do_stress_background = params.get('do_stress_background', 'no') == 'yes'
    kill_bg_stress = params.get('kill_bg_stress', 'no') == 'yes'

    exit_event = threading.Event()

    error_context.context('Boot guest %s on src host.' % src_desc,
                          logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=360)
    if windows:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, params["driver_name"])

    if params.get('run_stress_before_migration', 'no') == 'yes':
        if do_stress_background:
            stress_thread = run_stress_background(stress_timeout)
            if not utils_misc.wait_for(
                    lambda: (stress_thread.exit_event.is_set() or
                             bg_stress_is_alive(session, stress_name)),
                    120,
                    step=3):
                test.error('The %s is not alive.' % stress_name)
            if stress_thread.exit_event.is_set():
                stress_thread.exit_event.clear()
                six.reraise(stress_thread.exc_info[0],
                            stress_thread.exc_info[1],
                            stress_thread.exc_info[2])
        else:
            stress_maps[stress_name](stress_timeout)

    if with_cdrom:
        cdrom_params = params.object_params(params['cdroms'])
        check_orig_items = ast.literal_eval(cdrom_params['check_orig_items'])
        dev_id = check_orig_items['device']
        check_cdrom_info_by_qmp(check_orig_items)
        orig_size = compare_cdrom_size(params['cdrom_orig_file'])

        orig_img_name = params["cdrom_orig_file"]
        device_name = vm.get_block({"file": orig_img_name})
        if device_name is None:
            test.fail("Failed to get device using image %s." % orig_img_name)

        eject_check = QMPEventCheckCDEject(vm, device_name)
        change_check = QMPEventCheckCDChange(vm, device_name)
        eject_cdrom()
        change_cdrom()

        check_new_items = ast.literal_eval(cdrom_params['check_new_items'])
        check_cdrom_info_by_qmp(check_new_items)
        new_size = compare_cdrom_size(params['cdrom_new_file'])
        if new_size == orig_size:
            test.fail(
                'The new size inside guest is equal to the orig iso size.')

    error_context.context('Boot guest %s on dst host.' % dst_desc,
                          logging.info)
    ping_pong_migration(int(params.get('repeat_ping_pong', '1')))

    if params.get('run_stress_after_migration', 'no') == 'yes':
        if do_stress_background:
            run_stress_background(stress_timeout)
        else:
            stress_maps[stress_name](stress_timeout)

    if do_stress_background:
        if bg_stress_is_alive(session, stress_name):
            if kill_bg_stress:
                session.cmd('killall %s' % stress_name)
            else:
                stress_thread.join(stress_timeout)
                if stress_thread.exit_event.is_set():
                    stress_thread.exit_event.clear()
                    six.reraise(stress_thread.exc_info[0],
                                stress_thread.exc_info[1],
                                stress_thread.exc_info[2])

    if shutdown_vm or reboot:
        change_vm_power()
        check_vm_status()
def run(test, params, env):
    """
    qemu cdrom block size check test.

    1) Boot the guest with empty iso.
    2) Get the cdrom's size in guest.
    3) Attach a small cd iso file to the cdrom.
    4) mount the cdrom in guest and check its block size.
    5) umount and eject cdrom in guest.
    6) Change cdrom media to another file with different size.
    7) Get the cdrom's size in guest again.

    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """

    def list_guest_cdroms(session):
        """
        Get cdrom lists from guest os;

        :param session: ShellSession object;
        :param params: test params dict;
        :return: list of cdroms;
        :rtype: list
        """
        list_cdrom_cmd = "wmic cdrom get Drive"
        filter_cdrom_re = r"\w:"
        if params["os_type"] != "windows":
            list_cdrom_cmd = "ls /dev/cdrom*"
            filter_cdrom_re = r"/dev/cdrom-\w+|/dev/cdrom\d*"
        output = session.cmd_output(list_cdrom_cmd)
        return re.findall(filter_cdrom_re, output)

    def get_cdrom_mount_point(session, os_type="linux", drive_letter=None):
        """
        Get default cdrom mount point;
        """
        mount_point = "/mnt"
        if os_type == "windows":
            cmd = "wmic volume where DriveLetter='%s' " % drive_letter
            cmd += "get DeviceID | more +1"
            mount_point = session.cmd_output(cmd).strip()
        return mount_point

    def get_cdrom_device(vm):
        """
        Get cdrom device when cdrom is not insert.
        """
        device = None
        blocks = vm.monitor.info("block")
        if isinstance(blocks, six.string_types):
            for block in blocks.strip().split('\n'):
                if 'not inserted' in block:
                    device = block.split(':')[0]
        else:
            for block in blocks:
                if 'inserted' not in block.keys():
                    device = block['device']
                else:
                    if (vm.check_capability(Flags.BLOCKDEV) and
                            block['inserted']['file'] == 'null-co://'):
                        device = block['inserted']['node-name']
        return device

    def create_iso_image(params, name, prepare=True, file_size=None):
        """
        Creates 'new' iso image with one file on it

        :param params: parameters for test
        :param name: name of new iso image file. It could be the full path
                     of cdrom.
        :param preapre: if True then it prepare cd images.
        :param file_size: Size of iso image in MB

        :return: path to new iso image file.
        """
        error_context.context("Creating test iso image '%s'" % name,
                              logging.info)
        if not os.path.isabs(name):
            cdrom_path = utils_misc.get_path(data_dir.get_data_dir(), name)
        else:
            cdrom_path = name
        if not cdrom_path.endswith(".iso"):
            cdrom_path = "%s.iso" % cdrom_path
        name = os.path.basename(cdrom_path)

        if file_size is None:
            file_size = 10

        if prepare:
            cmd = "dd if=/dev/urandom of=%s bs=1M count=%d"
            process.run(cmd % (name, file_size))
            process.run("mkisofs -o %s %s" % (cdrom_path, name))
            process.run("rm -rf %s" % (name))
        return cdrom_path

    def check_cdrom_size(session):
        error_context.context("Get the cdrom's size in guest.", logging.info)
        check_cdrom_size_cmd = params["check_cdrom_size_cmd"]
        output = session.cmd(check_cdrom_size_cmd, timeout=60)
        if not output:
            msg = "Unable to get the cdrom's size in guest."
            msg += " Command: %s\nOutput: %s" % (check_cdrom_size_cmd, output)
            test.error(msg)
        size = output.strip().splitlines()[-1]
        try:
            cdrom_size = int(size)
        except ValueError:
            cdrom_size = 0
        logging.info("Cdrom's size in guest %s", cdrom_size)
        return cdrom_size

    def mount_cdrom(session, guest_cdrom, mount_point,
                    show_mount_cmd, mount_cmd):
        txt = "Mount the cdrom in guest and check its block size."
        error_context.context(txt, logging.info)
        mounted = session.cmd(show_mount_cmd)
        if mount_point not in mounted:
            mount_cmd = params.get("mount_cdrom_cmd") % (guest_cdrom,
                                                         mount_point)
            status, output = session.cmd_status_output(mount_cmd, timeout=360)
            if status:
                msg = "Unable to mount cdrom. command: %s\n" % mount_cmd
                msg += " Output: %s" % output
                test.error(msg)

    def is_tray_open(qdev):
        for block in vm.monitor.info("block"):
            if qdev == block.get('qdev'):
                return block.get('tray_open')

    def wait_for_tray_open(qdev):
        if not utils_misc.wait_for(lambda: is_tray_open(qdev), 30, 1, 3):
            test.error("The cdrom's tray did not open.")

    def change_media(device, target):
        try:
            with change_check:
                vm.change_media(device, target)
        except QMPCmdError as e:
            if excepted_qmp_err not in str(e):
                test.error(str(e))
            logging.warn(str(e))
            wait_for_tray_open(cdroms)
            with change_check:
                vm.change_media(device, target)
        # FIXME: sleep to wait to sync the status of CD-ROM to VM.
        time.sleep(sleep_time_after_change)

    def eject_cdrom(device):
        with eject_check:
            vm.eject_cdrom(device, True)

    cdroms = params["test_cdroms"]
    params["cdroms"] = cdroms
    params["start_vm"] = "yes"
    show_mount_cmd = params.get("show_mount_cmd")
    mount_cmd = params.get("mount_cdrom_cmd")
    umount_cmd = params.get("umount_cdrom_cmd")
    excepted_qmp_err = params.get('excepted_qmp_err')
    sleep_time_after_change = params.get_numeric('sleep_time_after_change', 30)
    os_type = params["os_type"]
    error_context.context("Get the main VM", logging.info)
    main_vm = params["main_vm"]
    env_process.preprocess_vm(test, params, env, main_vm)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = int(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=timeout)

    guest_cdrom = list_guest_cdroms(session)[-1]
    mount_point = get_cdrom_mount_point(session, os_type, guest_cdrom)
    empty_size = check_cdrom_size(session)

    cdrom_name = params.get("orig_cdrom", "images/orig.iso")
    file_size = params.get("orig_cdrom_size", 100)
    orig_cdrom = create_iso_image(params, cdrom_name, prepare=True,
                                  file_size=file_size)

    cdrom_device = get_cdrom_device(vm)
    eject_check = QMPEventCheckCDEject(vm, cdrom_device)
    change_check = QMPEventCheckCDChange(vm, cdrom_device)

    error_context.context("Attach a small cd iso file to the cdrom.",
                          logging.info)
    change_media(cdrom_device, orig_cdrom)
    if mount_cmd:
        mount_cdrom(session, guest_cdrom, mount_point,
                    show_mount_cmd, mount_cmd)
    orig_size = utils_misc.wait_for(lambda: check_cdrom_size(session), 60, 5, 3)

    if orig_size == empty_size:
        err = "Get same block size '%s' after new cdrom attached" % orig_size
        test.fail(err)

    if umount_cmd:
        error_context.context("umount cdrom in guest.", logging.info)
        umount_cmd = umount_cmd % mount_point
        status, output = session.cmd_status_output(umount_cmd, timeout=360)
        if status:
            msg = "Unable to umount cdrom. command: %s\n" % umount_cmd
            msg += "Output: %s" % output
            test.error(msg)

    error_context.context("eject the cdrom from monitor.", logging.info)
    eject_cdrom(cdrom_device)

    cdrom_name = params.get("final_cdrom", "images/final.iso")
    file_size = params.get("final_cdrom_size", 1000)
    final_cdrom = create_iso_image(params, cdrom_name, prepare=True,
                                   file_size=file_size)
    error_context.context("Attach a bigger cd iso file to the cdrom.",
                          logging.info)
    change_media(cdrom_device, final_cdrom)
    if mount_cmd:
        mount_cdrom(session, guest_cdrom, mount_point,
                    show_mount_cmd, mount_cmd)
    final_size = utils_misc.wait_for(lambda: check_cdrom_size(session),
                                     60, 5, 3)

    if final_size == empty_size or final_size == orig_size:
        err = "Get same block size '%s' after new cdrom attached" % final_size
        test.fail(err)

    # Check guest's network.
    vm.wait_for_login(timeout=timeout)