Ejemplo n.º 1
0
    def check_migration_res(result):
        """
        Check if the migration result is as expected

        :param result: the output of migration
        :raise: test.fail if test is failed
        """
        logging.info("Migration out: %s", results_stdout_52lts(result).strip())
        logging.info("Migration error: %s",
                     results_stderr_52lts(result).strip())

        if status_error:  # Migration should fail
            if err_msg:  # Special error messages are expected
                if not re.search(err_msg,
                                 results_stderr_52lts(result).strip()):
                    test.fail("Can not find the expected patterns '%s' in "
                              "output '%s'" %
                              (err_msg, results_stderr_52lts(result).strip()))
                else:
                    logging.debug("It is the expected error message")
            else:
                if int(result.exit_status) != 0:
                    logging.debug("Migration failure is expected result")
                else:
                    test.fail("Migration success is unexpected result")
        else:
            if int(result.exit_status) != 0:
                test.fail(results_stderr_52lts(result).strip())
Ejemplo n.º 2
0
def find_hbas(hba_type="hba", status="online"):
    """
    Find online hba/vhba cards.

    :params hba_type: "vhba" or "hba"
    :params status: "online" or "offline"
    :return: A list contains the online/offline vhba/hba list
    """
    # TODO: add status=offline/online judgement, we don't test offline vhba now
    # so leave it here as a placeholder.
    result = virsh.nodedev_list(cap="scsi_host")
    if result.exit_status:
        raise exceptions.TestFail(results_stderr_52lts(result))
    scsi_hosts = results_stdout_52lts(result).strip().splitlines()
    online_hbas_list = []
    online_vhbas_list = []
    # go through all scsi hosts, and split hbas/vhbas into lists
    for scsi_host in scsi_hosts:
        result = virsh.nodedev_dumpxml(scsi_host)
        stdout = results_stdout_52lts(result).strip()
        if result.exit_status:
            raise exceptions.TestFail(results_stderr_52lts(result))
        if (re.search('vport_ops', stdout)
                and not re.search('<fabric_wwn>ffffffffffffffff</fabric_wwn>', stdout)
                and not re.search('<fabric_wwn>0</fabric_wwn>', stdout)):
            online_hbas_list.append(scsi_host)
        if re.search('fc_host', stdout) and not re.search('vport_ops', stdout):
            online_vhbas_list.append(scsi_host)
    if hba_type == "hba":
        return online_hbas_list
    if hba_type == "vhba":
        return online_vhbas_list
    def check_migration_res(result):
        """
        Check if the migration result is as expected

        :param result: the output of migration
        :raise: test.fail if test is failed
        """
        logging.info("Migration out: %s", results_stdout_52lts(result).strip())
        logging.info("Migration error: %s", results_stderr_52lts(result).strip())

        if status_error:  # Migration should fail
            if err_msg:   # Special error messages are expected
                if not re.search(err_msg, results_stderr_52lts(result).strip()):
                    test.fail("Can not find the expected patterns '%s' in "
                              "output '%s'" % (err_msg,
                                               results_stderr_52lts(result).strip()))
                else:
                    logging.debug("It is the expected error message")
            else:
                if int(result.exit_status) != 0:
                    logging.debug("Migration failure is expected result")
                else:
                    test.fail("Migration success is unexpected result")
        else:
            if int(result.exit_status) != 0:
                test.fail(results_stderr_52lts(result).strip())
Ejemplo n.º 4
0
def find_hbas(hba_type="hba", status="online"):
    """
    Find online hba/vhba cards.

    :params hba_type: "vhba" or "hba"
    :params status: "online" or "offline"
    :return: A list contains the online/offline vhba/hba list
    """
    # TODO: add status=offline/online judgement, we don't test offline vhba now
    # so leave it here as a placeholder.
    result = virsh.nodedev_list(cap="scsi_host")
    if result.exit_status:
        raise exceptions.TestFail(results_stderr_52lts(result))
    scsi_hosts = results_stdout_52lts(result).strip().splitlines()
    online_hbas_list = []
    online_vhbas_list = []
    # go through all scsi hosts, and split hbas/vhbas into lists
    for scsi_host in scsi_hosts:
        result = virsh.nodedev_dumpxml(scsi_host)
        stdout = results_stdout_52lts(result).strip()
        if result.exit_status:
            raise exceptions.TestFail(results_stderr_52lts(result))
        if (re.search('vport_ops', stdout)
                and not re.search('<fabric_wwn>ffffffffffffffff</fabric_wwn>', stdout)
                and not re.search('<fabric_wwn>0</fabric_wwn>', stdout)):
            online_hbas_list.append(scsi_host)
        if re.search('fc_host', stdout) and not re.search('vport_ops', stdout):
            online_vhbas_list.append(scsi_host)
    if hba_type == "hba":
        return online_hbas_list
    if hba_type == "vhba":
        return online_vhbas_list
Ejemplo n.º 5
0
def get_cpustats(vm, cpu=None):
    """
    Get the cpustats output of a given domain
    :param vm: VM domain
    :param cpu: Host cpu index, default all cpus
    :return: dict of cpu stats values
    result format:
    {0:[vcputime,emulatortime,cputime]
    ..
    'total':[cputime]}
     """
    host_cpu_online = utils.cpu_online_list()
    cpustats = {}
    if cpu:
        cpustats[cpu] = []
        option = "--start %s --count 1" % cpu
        result = virsh.cpu_stats(vm.name, option)
        if result.exit_status != 0:
            logging.error("cpu stats command failed: %s",
                          results_stderr_52lts(result))
            return None
        output = results_stdout_52lts(result).strip().split()
        if re.match("CPU%s" % cpu, output[0]):
            cpustats[cpu] = [
                float(output[5]),  # vcputime
                float(output[2]) - float(output[5]),  # emulator
                float(output[2])
            ]  # cputime

    else:
        for i in range(len(host_cpu_online)):
            cpustats[host_cpu_online[i]] = []
            option = "--start %s --count 1" % host_cpu_online[i]
            result = virsh.cpu_stats(vm.name, option)
            if result.exit_status != 0:
                logging.error("cpu stats command failed: %s",
                              results_stderr_52lts(result))
                return None
            output = results_stdout_52lts(result).strip().split()
            if re.match("CPU%s" % host_cpu_online[i], output[0]):
                cpustats[host_cpu_online[i]] = [
                    float(output[5]),
                    float(output[2]) - float(output[5]),
                    float(output[2])
                ]
    result = virsh.cpu_stats(vm.name, "--total")
    cpustats["total"] = []
    if result.exit_status != 0:
        logging.error("cpu stats command failed: %s",
                      results_stderr_52lts(result))
        return None
    output = results_stdout_52lts(result).strip().split()
    cpustats["total"] = [float(output[2])]  # cputime
    return cpustats
Ejemplo n.º 6
0
def get_cpustats(vm, cpu=None):
    """
    Get the cpustats output of a given domain
    :param vm: VM domain
    :param cpu: Host cpu index, default all cpus
    :return: dict of cpu stats values
    result format:
    {0:[vcputime,emulatortime,cputime]
    ..
    'total':[cputime]}
     """
    host_cpu_online = utils.cpu_online_list()
    cpustats = {}
    if cpu:
        cpustats[cpu] = []
        option = "--start %s --count 1" % cpu
        result = virsh.cpu_stats(vm.name, option)
        if result.exit_status != 0:
            logging.error("cpu stats command failed: %s",
                          results_stderr_52lts(result))
            return None
        output = results_stdout_52lts(result).strip().split()
        if re.match("CPU%s" % cpu, output[0]):
            cpustats[cpu] = [float(output[5]),  # vcputime
                             float(output[2]) - float(output[5]),  # emulator
                             float(output[2])]  # cputime

    else:
        for i in range(len(host_cpu_online)):
            cpustats[host_cpu_online[i]] = []
            option = "--start %s --count 1" % host_cpu_online[i]
            result = virsh.cpu_stats(vm.name, option)
            if result.exit_status != 0:
                logging.error("cpu stats command failed: %s",
                              results_stderr_52lts(result))
                return None
            output = results_stdout_52lts(result).strip().split()
            if re.match("CPU%s" % host_cpu_online[i], output[0]):
                cpustats[host_cpu_online[i]] = [float(output[5]),
                                                float(output[2]) - float(output[5]),
                                                float(output[2])]
    result = virsh.cpu_stats(vm.name, "--total")
    cpustats["total"] = []
    if result.exit_status != 0:
        logging.error("cpu stats command failed: %s",
                      results_stderr_52lts(result))
        return None
    output = results_stdout_52lts(result).strip().split()
    cpustats["total"] = [float(output[2])]  # cputime
    return cpustats
Ejemplo n.º 7
0
def lv_take_snapshot(vg_name, lv_name, lv_snapshot_name, lv_snapshot_size):
    """
    Take a snapshot of the original logical volume.
    """
    error_context.context("Taking snapshot from original logical volume",
                          logging.info)

    if not vg_check(vg_name):
        raise exceptions.TestError("Volume group could not be found")
    if lv_check(vg_name, lv_snapshot_name):
        raise exceptions.TestError("Snapshot already exists")
    if not lv_check(vg_name, lv_name):
        raise exceptions.TestError("Snapshot's origin could not be found")

    cmd = ("lvcreate --size " + lv_snapshot_size + " --snapshot " +
           " --name " + lv_snapshot_name + " /dev/" + vg_name + "/" + lv_name)
    try:
        result = process.run(cmd)
    except process.CmdError as ex:
        if ('Logical volume "%s" already exists in volume group "%s"' %
            (lv_snapshot_name, vg_name) in results_stderr_52lts(ex.result)
                and re.search(re.escape(lv_snapshot_name + " [active]"),
                              results_stdout_52lts(process.run("lvdisplay")))):
            # the above conditions detect if merge of snapshot was postponed
            logging.warning(("Logical volume %s is still active! " +
                             "Attempting to deactivate..."), lv_name)
            lv_reactivate(vg_name, lv_name)
            result = process.run(cmd)
        else:
            raise ex
    logging.info(results_stdout_52lts(result).rstrip())
Ejemplo n.º 8
0
def iscsi_logout(target_name=None):
    """
    Logout from a target. If the target name is not set then logout all
    targets.

    :params target_name: Name of the target.
    """
    if target_name:
        cmd = "iscsiadm --mode node --logout -T %s" % target_name
    else:
        cmd = "iscsiadm --mode node --logout all"

    output = ''
    try:
        output = decode_to_text(process.system_output(cmd))
    except process.CmdError as detail:
        # iscsiadm will fail when no matching sessions found
        # This failure makes no sense when target name is not specified
        stderr = results_stderr_52lts(detail.result)
        if not target_name and 'No matching sessions' in stderr:
            logging.info("%s: %s", detail, stderr)
        else:
            raise

    target_logout = ""
    if "successful" in output:
        target_logout = target_name

    return target_logout
Ejemplo n.º 9
0
    def run(self, args):
        # Enable root logger as some Avocado-vt libraries use that
        handler = logging.StreamHandler()
        handler.setLevel(logging.DEBUG)
        logging.getLogger("").addHandler(handler)

        try:
            bootstrap.bootstrap(options=args, interactive=True)
            sys.exit(0)
        except process.CmdError as ce:
            if ce.result.interrupted:
                logging.info('Bootstrap command interrupted by user')
                logging.info('Command: %s', ce.command)
            else:
                logging.error('Bootstrap command failed')
                logging.error('Command: %s', ce.command)
                stderr = results_stderr_52lts(ce.result)
                if stderr:
                    logging.error('stderr output:')
                    logging.error(stderr)
                stdout = results_stdout_52lts(ce.result)
                if stdout:
                    logging.error('stdout output:')
                    logging.error(stdout)
            sys.exit(1)
        except KeyboardInterrupt:
            logging.info('Bootstrap interrupted by user')
            sys.exit(1)
Ejemplo n.º 10
0
def iscsi_logout(target_name=None):
    """
    Logout from a target. If the target name is not set then logout all
    targets.

    :params target_name: Name of the target.
    """
    if target_name:
        cmd = "iscsiadm --mode node --logout -T %s" % target_name
    else:
        cmd = "iscsiadm --mode node --logout all"

    output = ''
    try:
        output = decode_to_text(process.system_output(cmd))
    except process.CmdError as detail:
        # iscsiadm will fail when no matching sessions found
        # This failure makes no sense when target name is not specified
        stderr = results_stderr_52lts(detail.result)
        if not target_name and 'No matching sessions' in stderr:
            logging.info("%s: %s", detail, stderr)
        else:
            raise

    target_logout = ""
    if "successful" in output:
        target_logout = target_name

    return target_logout
Ejemplo n.º 11
0
    def run(self, args):
        # Enable root logger as some Avocado-vt libraries use that
        handler = logging.StreamHandler()
        handler.setLevel(logging.DEBUG)
        logging.getLogger("").addHandler(handler)

        try:
            bootstrap.bootstrap(options=args, interactive=True)
            sys.exit(0)
        except process.CmdError as ce:
            if ce.result.interrupted:
                logging.info('Bootstrap command interrupted by user')
                logging.info('Command: %s', ce.command)
            else:
                logging.error('Bootstrap command failed')
                logging.error('Command: %s', ce.command)
                stderr = results_stderr_52lts(ce.result)
                if stderr:
                    logging.error('stderr output:')
                    logging.error(stderr)
                stdout = results_stdout_52lts(ce.result)
                if stdout:
                    logging.error('stdout output:')
                    logging.error(stdout)
            sys.exit(1)
        except KeyboardInterrupt:
            logging.info('Bootstrap interrupted by user')
            sys.exit(1)
Ejemplo n.º 12
0
def set_defcon(context_type, pathregex, context_range=None, selinux_force=False):
    """
    Set the default context of a file/path in local SELinux policy

    :param context_type: The selinux context (only type is used)
    :param pathregex: Pathname regex e.g. r"/foo/bar/baz(/.*)?"
    :param context_range: MLS/MCS Security Range e.g. s0:c87,c520
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SelinuxError: if semanage command not found
    :raise SeCmdError: if semanage exits non-zero
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    cmd = "semanage fcontext --add"
    if context_type:
        cmd += ' -t %s' % context_type
    if context_range:
        cmd += ' -r %s' % context_range
    if pathregex:
        cmd += ' "%s"' % pathregex
    result = process.run(cmd, ignore_status=True)
    result.stdout = result.stdout_text
    result.stderr = result.stderr_text
    _no_semanage(result)
    if result.exit_status != 0:
        raise SeCmdError(cmd, results_stderr_52lts(result))
Ejemplo n.º 13
0
def get_status(selinux_force=False):
    """
    Get the status of selinux.

    :param selinux_force: True to force selinux configuration on Ubuntu
    :return: string of status in STATUS_LIST.
    :raise SeCmdError: if execute 'getenforce' failed.
    :raise SelinuxError: if 'getenforce' command exit 0,
                    but the output is not expected.
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return 'disabled'

    cmd = 'getenforce'
    try:
        result = process.run(cmd, ignore_status=True)
    except OSError:
        raise SeCmdError(cmd, "Command not available")

    if result.exit_status:
        raise SeCmdError(cmd, results_stderr_52lts(result))

    for status in STATUS_LIST:
        if results_stdout_52lts(result).lower().count(status):
            return status
        else:
            continue

    raise SelinuxError("result of 'getenforce' (%s)is not expected."
                       % results_stdout_52lts(result))
Ejemplo n.º 14
0
def get_status(selinux_force=False):
    """
    Get the status of selinux.

    :param selinux_force: True to force selinux configuration on Ubuntu
    :return: string of status in STATUS_LIST.
    :raise SeCmdError: if execute 'getenforce' failed.
    :raise SelinuxError: if 'getenforce' command exit 0,
                    but the output is not expected.
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return 'disabled'

    cmd = 'getenforce'
    try:
        result = process.run(cmd, ignore_status=True)
    except OSError:
        raise SeCmdError(cmd, "Command not available")

    if result.exit_status:
        raise SeCmdError(cmd, results_stderr_52lts(result))

    for status in STATUS_LIST:
        if results_stdout_52lts(result).lower().count(status):
            return status
        else:
            continue

    raise SelinuxError("result of 'getenforce' (%s)is not expected."
                       % results_stdout_52lts(result))
Ejemplo n.º 15
0
    def do_migration(vm, dest_uri, options, extra):
        """
        Execute the migration with given parameters
        :param vm: the guest to be migrated
        :param dest_uri: the destination uri for migration
        :param options: options next to 'migrate' command
        :param extra: options in the end of the migrate command line

        :return: CmdResult object
        """
        logging.info("Sleeping 10 seconds before migration")
        time.sleep(10)
        # Migrate the guest.
        migration_res = vm.migrate(dest_uri, options, extra, **virsh_args)
        logging.info("Migration out: %s",
                     results_stdout_52lts(migration_res).strip())
        logging.info("Migration error: %s",
                     results_stderr_52lts(migration_res).strip())
        if int(migration_res.exit_status) != 0:
            logging.error("Migration failed for %s.", vm_name)
            return migration_res

        if vm.is_alive():  # vm.connect_uri was updated
            logging.info("VM is alive on destination %s.", dest_uri)
        else:
            test.fail("VM is not alive on destination %s" % dest_uri)

        # Throws exception if console shows panic message
        vm.verify_kernel_crash()
        return migration_res
Ejemplo n.º 16
0
def set_defcon(context_type, pathregex, context_range=None, selinux_force=False):
    """
    Set the default context of a file/path in local SELinux policy

    :param context_type: The selinux context (only type is used)
    :param pathregex: Pathname regex e.g. r"/foo/bar/baz(/.*)?"
    :param context_range: MLS/MCS Security Range e.g. s0:c87,c520
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SelinuxError: if semanage command not found
    :raise SeCmdError: if semanage exits non-zero
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    cmd = "semanage fcontext --add"
    if context_type:
        cmd += ' -t %s' % context_type
    if context_range:
        cmd += ' -r %s' % context_range
    if pathregex:
        cmd += ' "%s"' % pathregex
    result = process.run(cmd, ignore_status=True)
    result.stdout = result.stdout_text
    result.stderr = result.stderr_text
    _no_semanage(result)
    if result.exit_status != 0:
        raise SeCmdError(cmd, results_stderr_52lts(result))
Ejemplo n.º 17
0
    def run(self, command, timeout=60, ignore_status=False):
        """
        Method to provide a utils.run-like interface to execute command on
        remote host or guest.

        :param timeout: Total time duration to wait for command return.
        :param ignore_status: If ignore_status=True, do not raise an exception,
                              no matter what the exit code of the command is.
                              Else, raise CmdError if exit code of command is
                              not zero.
        """
        # Redirect the stdout and stderr to file, Deviding error message
        # from output, and taking off the color of output. To return the same
        # result with utils.run() function.
        command = "%s 1>%s 2>%s" % (
            command, self.stdout_pipe, self.stderr_pipe)
        status, _ = self.session.cmd_status_output(command, timeout=timeout)
        output = self.session.cmd_output("cat %s;rm -f %s" %
                                         (self.stdout_pipe, self.stdout_pipe))
        errput = self.session.cmd_output("cat %s;rm -f %s" %
                                         (self.stderr_pipe, self.stderr_pipe))
        cmd_result = process.CmdResult(command=command, exit_status=status,
                                       stdout=output, stderr=errput)
        cmd_result.stdout = results_stdout_52lts(cmd_result)
        cmd_result.stderr = results_stderr_52lts(cmd_result)
        if status and (not ignore_status):
            raise process.CmdError(command, cmd_result)
        return cmd_result
Ejemplo n.º 18
0
    def run(self, command, timeout=60, ignore_status=False):
        """
        Method to provide a utils.run-like interface to execute command on
        remote host or guest.

        :param timeout: Total time duration to wait for command return.
        :param ignore_status: If ignore_status=True, do not raise an exception,
                              no matter what the exit code of the command is.
                              Else, raise CmdError if exit code of command is
                              not zero.
        """
        # Redirect the stdout and stderr to file, Deviding error message
        # from output, and taking off the color of output. To return the same
        # result with utils.run() function.
        command = "%s 1>%s 2>%s" % (
            command, self.stdout_pipe, self.stderr_pipe)
        status, _ = self.session.cmd_status_output(command, timeout=timeout)
        output = self.session.cmd_output("cat %s;rm -f %s" %
                                         (self.stdout_pipe, self.stdout_pipe))
        errput = self.session.cmd_output("cat %s;rm -f %s" %
                                         (self.stderr_pipe, self.stderr_pipe))
        cmd_result = process.CmdResult(command=command, exit_status=status,
                                       stdout=output, stderr=errput)
        cmd_result.stdout = results_stdout_52lts(cmd_result)
        cmd_result.stderr = results_stderr_52lts(cmd_result)
        if status and (not ignore_status):
            raise process.CmdError(command, cmd_result)
        return cmd_result
Ejemplo n.º 19
0
def lv_take_snapshot(vg_name, lv_name,
                     lv_snapshot_name, lv_snapshot_size):
    """
    Take a snapshot of the original logical volume.
    """
    error_context.context("Taking snapshot from original logical volume",
                          logging.info)

    if not vg_check(vg_name):
        raise exceptions.TestError("Volume group could not be found")
    if lv_check(vg_name, lv_snapshot_name):
        raise exceptions.TestError("Snapshot already exists")
    if not lv_check(vg_name, lv_name):
        raise exceptions.TestError("Snapshot's origin could not be found")

    cmd = ("lvcreate --size " + lv_snapshot_size + " --snapshot " +
           " --name " + lv_snapshot_name + " /dev/" + vg_name + "/" + lv_name)
    try:
        result = process.run(cmd)
    except process.CmdError as ex:
        if ('Logical volume "%s" already exists in volume group "%s"' %
            (lv_snapshot_name, vg_name) in results_stderr_52lts(ex.result) and
            re.search(re.escape(lv_snapshot_name + " [active]"),
                      results_stdout_52lts(process.run("lvdisplay")))):
            # the above conditions detect if merge of snapshot was postponed
            logging.warning(("Logical volume %s is still active! " +
                             "Attempting to deactivate..."), lv_name)
            lv_reactivate(vg_name, lv_name)
            result = process.run(cmd)
        else:
            raise ex
    logging.info(results_stdout_52lts(result).rstrip())
Ejemplo n.º 20
0
    def __init__(self, params):
        self.nfs_client_ip = params.get("nfs_client_ip")
        # To Avoid host key verification failure
        ret = process.run("ssh-keygen -R %s" % self.nfs_client_ip,
                          ignore_status=True)
        stderr = results_stderr_52lts(ret)
        if ret.exit_status and "No such file or directory" not in stderr:
            raise exceptions.TestFail("Failed to update host key: %s" %
                                      stderr)
        # Setup SSH connection
        self.ssh_obj = SSHConnection(params)
        ssh_timeout = int(params.get("ssh_timeout", 10))
        self.ssh_obj.conn_setup(timeout=ssh_timeout)

        self.params = params
        self.mkdir_mount_remote = False
        self.mount_dir = params.get("nfs_mount_dir")
        self.mount_options = params.get("nfs_mount_options")
        self.mount_src = params.get("nfs_mount_src")
        self.nfs_server_ip = params.get("nfs_server_ip")
        self.ssh_user = params.get("ssh_username", "root")
        self.remote_nfs_mount = params.get("remote_nfs_mount", "yes")
        self.ssh_hostkey_check = params.get("ssh_hostkey_check", "no") == "yes"
        self.ssh_cmd = "ssh %s@%s " % (self.ssh_user, self.nfs_client_ip)
        if not self.ssh_hostkey_check:
            self.ssh_cmd += "-o StrictHostKeyChecking=no "
Ejemplo n.º 21
0
    def amend(self, params, cache_mode=None, ignore_status=False):
        """
        Amend the image format specific options for the image

        :param params: dictionary containing the test parameters
        :param cache_mode: the cache mode used to write the output disk image,
                           the valid options are: 'none', 'writeback'
                           (default), 'writethrough', 'directsync' and
                           'unsafe'.
        :param ignore_status: Whether to raise an exception when command
                              returns =! 0 (False), or not (True).

        :note: params may contain amend options:

               amend_size
                   virtual disk size of the image (a string qemu-img can
                   understand, such as '10G')
               amend_compat
                   compatibility level (0.10 or 1.1)
               amend_backing_file
                   file name of a base image
               amend_backing_fmt
                   image format of the base image
               amend_encryption
                   encrypt the image, allowed values: on and off.
                   Default is "off"
               amend_cluster_size
                   cluster size for the image
               amend_preallocation
                   preallocation mode when create image, allowed values: off,
                   metadata. Default is "off"
               amend_lazy_refcounts
                   postpone refcount updates, allowed values: on and off.
                   Default is "off"
               amend_refcount_bits
                   width of a reference count entry in bits
               amend_extra_params
                   additional options, used for extending amend

        :return: process.CmdResult object containing the result of the
                command
        """
        cmd_list = [self.image_cmd, 'amend']
        options = [
            "%s=%s" % (key[6:], val) for key, val in six.iteritems(params)
            if key.startswith('amend_')
        ]
        if cache_mode:
            cmd_list.append("-t %s" % cache_mode)
        if options:
            cmd_list.append("-o %s" %
                            ",".join(options).replace("extra_params=", ""))
        cmd_list.append("-f %s %s" % (self.image_format, self.image_filename))
        logging.info("Amend image %s" % self.image_filename)
        cmd_result = process.run(" ".join(cmd_list), ignore_status=False)
        cmd_result.stdout = results_stdout_52lts(cmd_result)
        cmd_result.stderr = results_stderr_52lts(cmd_result)
        return cmd_result
Ejemplo n.º 22
0
 def start(self):
     """
     Start network with self.virsh.
     """
     cmd_result = self.virsh.net_start(self.name)
     if cmd_result.exit_status:
         raise xcepts.LibvirtXMLError(
             "Failed to start network %s.\n"
             "Detail: %s" % (self.name, results_stderr_52lts(cmd_result)))
Ejemplo n.º 23
0
 def define(self):
     """
     Define network from self.xml.
     """
     cmd_result = self.virsh.net_define(self.xml)
     if cmd_result.exit_status:
         raise xcepts.LibvirtXMLError(
             "Failed to define network %s.\n"
             "Detail: %s" % (self.name, results_stderr_52lts(cmd_result)))
Ejemplo n.º 24
0
    def check_migration_res(result):
        """
        Check if the migration result is as expected

        :param result: the output of migration
        :raise: test.fail if test is failed
        """
        if not err_msg:
            if int(result.exit_status) != 0:
                test.fail(results_stderr_52lts(result).strip())
        else:
            logging.debug(result)
            if not re.search(err_msg, results_stderr_52lts(result).strip()):
                test.fail("Can not find the expected patterns '%s' in "
                          "output '%s'" % (err_msg,
                                           results_stderr_52lts(result).strip()))
            else:
                logging.debug("It is the expected error message")
Ejemplo n.º 25
0
def vg_ramdisk_cleanup(ramdisk_filename, vg_ramdisk_dir, vg_name, loop_device):
    """
    Inline cleanup function in case of test error.
    """
    result = process.run("vgremove " + vg_name, ignore_status=True)
    if result.exit_status == 0:
        logging.info(results_stdout_52lts(result).rstrip())
    else:
        logging.debug("%s -> %s", result.command, results_stderr_52lts(result))

    result = process.run("pvremove " + loop_device, ignore_status=True)
    if result.exit_status == 0:
        logging.info(results_stdout_52lts(result).rstrip())
    else:
        logging.debug("%s -> %s", result.command, results_stderr_52lts(result))

    for _ in range(10):
        time.sleep(0.1)
        result = process.run("losetup -d " + loop_device, ignore_status=True)
        if b"resource busy" not in result.stderr:
            if result.exit_status != 0:
                logging.debug("%s -> %s", result.command,
                              results_stderr_52lts(result))
            else:
                logging.info("Loop device %s deleted", loop_device)
            break

    if os.path.exists(ramdisk_filename):
        os.unlink(ramdisk_filename)
        logging.info("Ramdisk filename %s deleted", ramdisk_filename)

    process.run("umount " + vg_ramdisk_dir, ignore_status=True)
    if result.exit_status == 0:
        if loop_device != "":
            logging.info("Loop device %s unmounted", loop_device)
    else:
        logging.debug("%s -> %s", result.command, results_stderr_52lts(result))

    if os.path.exists(vg_ramdisk_dir):
        try:
            shutil.rmtree(vg_ramdisk_dir)
            logging.info("Ramdisk directory %s deleted", vg_ramdisk_dir)
        except OSError:
            pass
Ejemplo n.º 26
0
def vg_ramdisk_cleanup(ramdisk_filename, vg_ramdisk_dir,
                       vg_name, loop_device):
    """
    Inline cleanup function in case of test error.
    """
    result = process.run("vgremove " + vg_name, ignore_status=True)
    if result.exit_status == 0:
        logging.info(results_stdout_52lts(result).rstrip())
    else:
        logging.debug("%s -> %s", result.command, results_stderr_52lts(result))

    result = process.run("pvremove " + loop_device, ignore_status=True)
    if result.exit_status == 0:
        logging.info(results_stdout_52lts(result).rstrip())
    else:
        logging.debug("%s -> %s", result.command, results_stderr_52lts(result))

    for _ in range(10):
        time.sleep(0.1)
        result = process.run("losetup -d " + loop_device, ignore_status=True)
        if b"resource busy" not in result.stderr:
            if result.exit_status != 0:
                logging.debug("%s -> %s", result.command, results_stderr_52lts(result))
            else:
                logging.info("Loop device %s deleted", loop_device)
            break

    if os.path.exists(ramdisk_filename):
        os.unlink(ramdisk_filename)
        logging.info("Ramdisk filename %s deleted", ramdisk_filename)

    process.run("umount " + vg_ramdisk_dir, ignore_status=True)
    if result.exit_status == 0:
        if loop_device != "":
            logging.info("Loop device %s unmounted", loop_device)
    else:
        logging.debug("%s -> %s", result.command, results_stderr_52lts(result))

    if os.path.exists(vg_ramdisk_dir):
        try:
            shutil.rmtree(vg_ramdisk_dir)
            logging.info("Ramdisk directory %s deleted", vg_ramdisk_dir)
        except OSError:
            pass
Ejemplo n.º 27
0
def v2v_cmd(params):
    """
    Append 'virt-v2v' and execute it.

    :param params: A dictionary includes all of required parameters such as
                    'target', 'hypervisor' and 'hostname', etc.
    :return: A CmdResult object
    """
    if V2V_EXEC is None:
        raise ValueError('Missing command: virt-v2v')

    target = params.get('target')
    hypervisor = params.get('hypervisor')
    # vpx:// or esx://
    src_uri_type = params.get('src_uri_type')
    hostname = params.get('hostname')
    vpx_dc = params.get('vpx_dc')
    esxi_host = params.get('esxi_host', params.get('esx_ip'))
    opts_extra = params.get('v2v_opts')
    # Set v2v_timeout to 3 hours, the value can give v2v enough time to execute,
    # and avoid v2v process be killed by mistake.
    # the value is bigger than the timeout value in CI, so when some timeout
    # really happens, CI will still interrupt the v2v process.
    v2v_timeout = params.get('v2v_timeout', 10800)
    rhv_upload_opts = params.get('rhv_upload_opts')

    uri_obj = Uri(hypervisor)
    # Return actual 'uri' according to 'hostname' and 'hypervisor'
    if src_uri_type == 'esx':
        vpx_dc = None
    uri = uri_obj.get_uri(hostname, vpx_dc, esxi_host)

    target_obj = Target(target, uri)
    try:
        # Return virt-v2v command line options based on 'target' and
        # 'hypervisor'
        options = target_obj.get_cmd_options(params)

        if rhv_upload_opts:
            options = options + ' ' + rhv_upload_opts
        if opts_extra:
            options = options + ' ' + opts_extra

        # Construct a final virt-v2v command
        cmd = '%s %s' % (V2V_EXEC, options)
        cmd_result = process.run(cmd,
                                 timeout=v2v_timeout,
                                 verbose=True,
                                 ignore_status=True)
    finally:
        target_obj.cleanup()

    cmd_result.stdout = results_stdout_52lts(cmd_result)
    cmd_result.stderr = results_stderr_52lts(cmd_result)

    return cmd_result
Ejemplo n.º 28
0
    def amend(self, params, cache_mode=None, ignore_status=False):
        """
        Amend the image format specific options for the image

        :param params: dictionary containing the test parameters
        :param cache_mode: the cache mode used to write the output disk image,
                           the valid options are: 'none', 'writeback'
                           (default), 'writethrough', 'directsync' and
                           'unsafe'.
        :param ignore_status: Whether to raise an exception when command
                              returns =! 0 (False), or not (True).

        :note: params may contain amend options:

               amend_size
                   virtual disk size of the image (a string qemu-img can
                   understand, such as '10G')
               amend_compat
                   compatibility level (0.10 or 1.1)
               amend_backing_file
                   file name of a base image
               amend_backing_fmt
                   image format of the base image
               amend_encryption
                   encrypt the image, allowed values: on and off.
                   Default is "off"
               amend_cluster_size
                   cluster size for the image
               amend_preallocation
                   preallocation mode when create image, allowed values: off,
                   metadata. Default is "off"
               amend_lazy_refcounts
                   postpone refcount updates, allowed values: on and off.
                   Default is "off"
               amend_refcount_bits
                   width of a reference count entry in bits
               amend_extra_params
                   additional options, used for extending amend

        :return: process.CmdResult object containing the result of the
                command
        """
        cmd_list = [self.image_cmd, 'amend']
        options = ["%s=%s" % (key[6:], val) for key, val in six.iteritems(params)
                   if key.startswith('amend_')]
        if cache_mode:
            cmd_list.append("-t %s" % cache_mode)
        if options:
            cmd_list.append("-o %s" %
                            ",".join(options).replace("extra_params=", ""))
        cmd_list.append("-f %s %s" % (self.image_format, self.image_filename))
        logging.info("Amend image %s" % self.image_filename)
        cmd_result = process.run(" ".join(cmd_list), ignore_status=False)
        cmd_result.stdout = results_stdout_52lts(cmd_result)
        cmd_result.stderr = results_stderr_52lts(cmd_result)
        return cmd_result
Ejemplo n.º 29
0
 def start(self):
     """
     Start network with self.virsh.
     """
     cmd_result = self.virsh.net_start(self.name)
     if cmd_result.exit_status:
         raise xcepts.LibvirtXMLError("Failed to start network %s.\n"
                                      "Detail: %s" %
                                      (self.name,
                                       results_stderr_52lts(cmd_result)))
Ejemplo n.º 30
0
 def define(self):
     """
     Define network from self.xml.
     """
     cmd_result = self.virsh.net_define(self.xml)
     if cmd_result.exit_status:
         raise xcepts.LibvirtXMLError("Failed to define network %s.\n"
                                      "Detail: %s" %
                                      (self.name,
                                       results_stderr_52lts(cmd_result)))
Ejemplo n.º 31
0
 def undefine(self):
     """
     Undefine network witch name is self.name.
     """
     self.virsh.net_destroy(self.name)
     cmd_result = self.virsh.net_undefine(self.name)
     if cmd_result.exit_status:
         raise xcepts.LibvirtXMLError(
             "Failed to undefine network %s.\n"
             "Detail: %s" % (self.name, results_stderr_52lts(cmd_result)))
Ejemplo n.º 32
0
 def undefine(self):
     """
     Undefine network witch name is self.name.
     """
     self.virsh.net_destroy(self.name)
     cmd_result = self.virsh.net_undefine(self.name)
     if cmd_result.exit_status:
         raise xcepts.LibvirtXMLError("Failed to undefine network %s.\n"
                                      "Detail: %s" %
                                      (self.name,
                                       results_stderr_52lts(cmd_result)))
Ejemplo n.º 33
0
 def virt_xml_validate(filename, schema_name=None):
     """
     Return CmdResult from running virt-xml-validate on backing XML
     """
     command = 'virt-xml-validate %s' % filename
     if schema_name:
         command += ' %s' % schema_name
     cmdresult = process.run(command, ignore_status=True)
     cmdresult.stdout = results_stdout_52lts(cmdresult)
     cmdresult.stderr = results_stderr_52lts(cmdresult)
     return cmdresult
Ejemplo n.º 34
0
 def virt_xml_validate(filename, schema_name=None):
     """
     Return CmdResult from running virt-xml-validate on backing XML
     """
     command = 'virt-xml-validate %s' % filename
     if schema_name:
         command += ' %s' % schema_name
     cmdresult = process.run(command, ignore_status=True)
     cmdresult.stdout = results_stdout_52lts(cmdresult)
     cmdresult.stderr = results_stderr_52lts(cmdresult)
     return cmdresult
Ejemplo n.º 35
0
def del_defcon(context_type, pathregex, selinux_force=False):
    """
    Remove the default local SELinux policy type for a file/path

    :param context: The selinux context (only type is used)
    :pramm pathregex: Pathname regex e.g. r"/foo/bar/baz(/.*)?"
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SelinuxError: if semanage command not found
    :raise SeCmdError: if semanage exits non-zero
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    cmd = ("semanage fcontext --delete -t %s '%s'" % (context_type, pathregex))
    result = process.run(cmd, ignore_status=True)
    result.stdout = results_stdout_52lts(result)
    result.stderr = results_stderr_52lts(result)
    _no_semanage(result)
    if result.exit_status != 0:
        raise SeCmdError(cmd, results_stderr_52lts(result))
Ejemplo n.º 36
0
def del_defcon(context_type, pathregex, selinux_force=False):
    """
    Remove the default local SELinux policy type for a file/path

    :param context: The selinux context (only type is used)
    :pramm pathregex: Pathname regex e.g. r"/foo/bar/baz(/.*)?"
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SelinuxError: if semanage command not found
    :raise SeCmdError: if semanage exits non-zero
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    cmd = ("semanage fcontext --delete -t %s '%s'" % (context_type, pathregex))
    result = process.run(cmd, ignore_status=True)
    result.stdout = results_stdout_52lts(result)
    result.stderr = results_stderr_52lts(result)
    _no_semanage(result)
    if result.exit_status != 0:
        raise SeCmdError(cmd, results_stderr_52lts(result))
Ejemplo n.º 37
0
    def new_from_dumpxml(dev_name, virsh_instance=base.virsh):
        """
        Get a instance of NodedevXML by dumpxml dev_name.
        """
        nodedevxml = NodedevXML(virsh_instance=virsh_instance)
        dumpxml_result = virsh_instance.nodedev_dumpxml(dev_name)
        if dumpxml_result.exit_status:
            stderr = results_stderr_52lts(dumpxml_result)
            raise xcepts.LibvirtXMLError("Nodedev_dumpxml %s failed.\n"
                                         "Error: %s." % (dev_name, stderr))
        nodedevxml.xml = results_stdout_52lts(dumpxml_result)

        return nodedevxml
Ejemplo n.º 38
0
def get_vcpucount_details(vm, options):
    """
    To get vcpucount output

    :param vm: VM object
    :param options: options to passed to vcpucount

    :return: tuple of result and dict of vcpucount output values
    """
    vcpucount_details = {
        'max_config': None,
        'max_live': None,
        'cur_config': None,
        'cur_live': None,
        'guest_live': None
    }

    result = virsh.vcpucount(vm.name, options, ignore_status=True, debug=True)
    if results_stderr_52lts(result):
        logging.debug("vcpu count command failed")
        return (result, vcpucount_details)

    if options:
        stdout = results_stdout_52lts(result).strip()
        if 'guest' in options:
            vcpucount_details['guest_live'] = int(stdout)
        elif 'config' in options:
            if 'maximum' in options:
                vcpucount_details['max_config'] = int(stdout)
            else:
                vcpucount_details['cur_config'] = int(stdout)
        elif 'live' in options:
            if 'maximum' in options:
                vcpucount_details['max_live'] = int(stdout)
            else:
                vcpucount_details['cur_live'] = int(stdout)
    else:
        output = results_stdout_52lts(result).strip().split('\n')
        for item in output:
            if ('maximum' in item) and ('config' in item):
                vcpucount_details['max_config'] = int(item.split()[2].strip())
            elif ('maximum' in item) and ('live' in item):
                vcpucount_details['max_live'] = int(item.split()[2].strip())
            elif ('current' in item) and ('config' in item):
                vcpucount_details['cur_config'] = int(item.split()[2].strip())
            elif ('current' in item) and ('live' in item):
                vcpucount_details['cur_live'] = int(item.split()[2].strip())
            else:
                pass
    return (result, vcpucount_details)
Ejemplo n.º 39
0
        def run(**kwargs):
            """
            Wrapped process.run invocation that will start, stop, restart, etc. a service.

            :param kwargs: extra arguments to process.run, .e.g. timeout. But not for ignore_status.
                           We need a CmdResult to parse and raise a exceptions.TestError if command failed.
                           We will not let the CmdError out.
            :return: result of parse_func.
            """
            logging.debug("Setting ignore_status to True.")
            kwargs["ignore_status"] = True
            result = run_func(" ".join(command(service_name)), **kwargs)
            result.stdout = results_stdout_52lts(result)
            result.stderr = results_stderr_52lts(result)
            return parse_func(result)
Ejemplo n.º 40
0
        def run(**kwargs):
            """
            Wrapped process.run invocation that will start, stop, restart, etc. a service.

            :param kwargs: extra arguments to process.run, .e.g. timeout. But not for ignore_status.
                           We need a CmdResult to parse and raise a exceptions.TestError if command failed.
                           We will not let the CmdError out.
            :return: result of parse_func.
            """
            logging.debug("Setting ignore_status to True.")
            kwargs["ignore_status"] = True
            result = run_func(" ".join(command(service_name)), **kwargs)
            result.stdout = results_stdout_52lts(result)
            result.stderr = results_stderr_52lts(result)
            return parse_func(result)
Ejemplo n.º 41
0
    def compare_images(self,
                       image1,
                       image2,
                       strict_mode=False,
                       verbose=True,
                       force_share=False):
        """
        Compare 2 images using the appropriate tools for each virt backend.

        :param image1: image path of first image
        :param image2: image path of second image
        :param strict_mode: Boolean value, True for strict mode,
                            False for default mode.
        :param verbose: Record output in debug file or not

        :return: process.CmdResult object containing the result of the command
        """
        compare_images = self.support_cmd("compare")
        force_share &= self.cap_force_share
        if not compare_images:
            logging.warn("sub-command compare not supported by qemu-img")
            return None
        else:
            logging.info("Comparing images %s and %s", image1, image2)
            compare_cmd = "%s compare" % self.image_cmd
            if force_share:
                compare_cmd += " -U"
            if strict_mode:
                compare_cmd += " -s"
            compare_cmd += " %s %s" % (image1, image2)
            cmd_result = process.run(compare_cmd,
                                     ignore_status=True,
                                     shell=True)

            if verbose:
                logging.debug("Output from command: %s",
                              results_stdout_52lts(cmd_result))

            if cmd_result.exit_status == 0:
                logging.info("Compared images are equal")
            elif cmd_result.exit_status == 1:
                raise exceptions.TestFail("Compared images differ")
            else:
                raise exceptions.TestError("Error in image comparison")

            cmd_result.stdout = results_stdout_52lts(cmd_result)
            cmd_result.stderr = results_stderr_52lts(cmd_result)
            return cmd_result
Ejemplo n.º 42
0
    def run_remote_cmd(cmd):
        """
        A function to run a command on remote host.

        :param cmd: the command to be executed

        :return: CmdResult object
        """
        remote_runner = remote.RemoteRunner(host=server_ip,
                                            username=server_user,
                                            password=server_pwd)
        cmdResult = remote_runner.run(cmd, ignore_status=True)
        if cmdResult.exit_status:
            test.fail("Failed to run '%s' on remote: %s" %
                      (cmd, results_stderr_52lts(cmdResult).strip()))
        return cmdResult
Ejemplo n.º 43
0
def get_vcpucount_details(vm, options):
    """
    To get vcpucount output

    :param vm: VM object
    :param options: options to passed to vcpucount

    :return: tuple of result and dict of vcpucount output values
    """
    vcpucount_details = {'max_config': None, 'max_live': None,
                         'cur_config': None, 'cur_live': None,
                         'guest_live': None}

    result = virsh.vcpucount(vm.name, options, ignore_status=True,
                             debug=True)
    if results_stderr_52lts(result):
        logging.debug("vcpu count command failed")
        return (result, vcpucount_details)

    if options:
        stdout = results_stdout_52lts(result).strip()
        if 'guest' in options:
            vcpucount_details['guest_live'] = int(stdout)
        elif 'config' in options:
            if 'maximum' in options:
                vcpucount_details['max_config'] = int(stdout)
            else:
                vcpucount_details['cur_config'] = int(stdout)
        elif 'live' in options:
            if 'maximum' in options:
                vcpucount_details['max_live'] = int(stdout)
            else:
                vcpucount_details['cur_live'] = int(stdout)
    else:
        output = results_stdout_52lts(result).strip().split('\n')
        for item in output:
            if ('maximum' in item) and ('config' in item):
                vcpucount_details['max_config'] = int(item.split()[2].strip())
            elif ('maximum' in item) and ('live' in item):
                vcpucount_details['max_live'] = int(item.split()[2].strip())
            elif ('current' in item) and ('config' in item):
                vcpucount_details['cur_config'] = int(item.split()[2].strip())
            elif ('current' in item) and ('live' in item):
                vcpucount_details['cur_live'] = int(item.split()[2].strip())
            else:
                pass
    return (result, vcpucount_details)
Ejemplo n.º 44
0
def check_vcpucount(vm, exp_vcpu, option="", guest_agent=False):
    """
    To check the vcpu count details from vcpucount API

    :param vm: VM object
    :param exp_vcpu: dict of expected vcpus
    :param option: options to vcpucount API if any
    :param guest_agest: True if need to check inside guest,guest agent present

    :return: True if exp_vcpu matches the vcpucount output, False if not
    """
    result = True
    vcpucount_result = {}
    vcpucount_option = ""
    if option == "--guest" and vm.is_alive() and guest_agent:
        vcpucount_option = "--guest"
    (vcresult, vcpucount_result) = get_vcpucount_details(vm, vcpucount_option)
    if results_stderr_52lts(vcresult):
        result = False
    if vcpucount_option == "--guest" and guest_agent:
        if vcpucount_result['guest_live'] != exp_vcpu['guest_live']:
            logging.error(
                "Virsh vcpucount output is unexpected\nExpected: "
                "%s\nActual: %s", exp_vcpu, vcpucount_result)
            result = False
    else:
        # Check for config option results
        if vm.is_dead():
            if (exp_vcpu['max_config'] != vcpucount_result['max_config'] or
                    exp_vcpu['cur_config'] != vcpucount_result['cur_config']):
                logging.error(
                    "Virsh vcpucount output is unexpected\nExpected"
                    ":%s\nActual:%s", exp_vcpu, vcpucount_result)
                result = False
        else:
            if (exp_vcpu['max_config'] != vcpucount_result['max_config']
                    or exp_vcpu['max_live'] != vcpucount_result['max_live']
                    or exp_vcpu['cur_config'] != vcpucount_result['cur_config']
                    or exp_vcpu['cur_live'] != vcpucount_result['cur_live']):
                logging.error(
                    "Virsh vcpucount output is unexpected\n "
                    "Expected:%s\nActual:%s", exp_vcpu, vcpucount_result)
                result = False
    if result:
        logging.debug("Command vcpucount check pass")
    return result
Ejemplo n.º 45
0
def check_vcpucount(vm, exp_vcpu, option="", guest_agent=False):
    """
    To check the vcpu count details from vcpucount API

    :param vm: VM object
    :param exp_vcpu: dict of expected vcpus
    :param option: options to vcpucount API if any
    :param guest_agest: True if need to check inside guest,guest agent present

    :return: True if exp_vcpu matches the vcpucount output, False if not
    """
    result = True
    vcpucount_result = {}
    vcpucount_option = ""
    if option == "--guest" and vm.is_alive() and guest_agent:
        vcpucount_option = "--guest"
    (vcresult, vcpucount_result) = get_vcpucount_details(vm, vcpucount_option)
    if results_stderr_52lts(vcresult):
        result = False
    if vcpucount_option == "--guest" and guest_agent:
        if vcpucount_result['guest_live'] != exp_vcpu['guest_live']:
            logging.error("Virsh vcpucount output is unexpected\nExpected: "
                          "%s\nActual: %s", exp_vcpu, vcpucount_result)
            result = False
    else:
        # Check for config option results
        if vm.is_dead():
            if (exp_vcpu['max_config'] != vcpucount_result['max_config'] or
                    exp_vcpu['cur_config'] != vcpucount_result['cur_config']):
                logging.error("Virsh vcpucount output is unexpected\nExpected"
                              ":%s\nActual:%s", exp_vcpu, vcpucount_result)
                result = False
        else:
            if (exp_vcpu['max_config'] != vcpucount_result['max_config'] or
                    exp_vcpu['max_live'] != vcpucount_result['max_live'] or
                    exp_vcpu['cur_config'] != vcpucount_result['cur_config'] or
                    exp_vcpu['cur_live'] != vcpucount_result['cur_live']):
                logging.error("Virsh vcpucount output is unexpected\n "
                              "Expected:%s\nActual:%s", exp_vcpu,
                              vcpucount_result)
                result = False
    if result:
        logging.debug("Command vcpucount check pass")
    return result
Ejemplo n.º 46
0
def get_defcon(local=False, selinux_force=False):
    """
    Return list of dictionaries containing SELinux default file context types

    :param local: Only return locally modified default contexts
    :param selinux_force: True to force selinux configuration on Ubuntu
    :return: list of dictionaries of default context attributes
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    if local:
        result = process.run("semanage fcontext --list -C", ignore_status=True)
    else:
        result = process.run("semanage fcontext --list", ignore_status=True)
    _no_semanage(result)
    if result.exit_status != 0:
        raise SeCmdError('semanage', results_stderr_52lts(result))
    result_list = results_stdout_52lts(result).strip().split('\n')
    # Need to process top-down instead of bottom-up
    result_list.reverse()
    first_line = result_list.pop()
    # First column name has a space in it
    column_names = [
        name.strip().lower().replace(' ', '_')
        for name in first_line.split('  ') if len(name) > 0
    ]
    # Shorten first column name
    column_names[0] = column_names[0].replace("selinux_", "")
    fcontexts = []
    for line in result_list:
        if len(line) < 1:  # skip blank lines
            continue
        column_data = [
            name.strip() for name in line.split('  ') if len(name) > 0
        ]
        # Enumerating data raises exception if no column_names match
        fcontext = dict([(column_names[idx], data)
                         for idx, data in enumerate(column_data)])
        # find/set functions only accept type, not full context string
        fcontext['context'] = get_type_from_context(fcontext['context'])
        fcontexts.append(fcontext)
    return fcontexts
Ejemplo n.º 47
0
def get_defcon(local=False, selinux_force=False):
    """
    Return list of dictionaries containing SELinux default file context types

    :param local: Only return locally modified default contexts
    :param selinux_force: True to force selinux configuration on Ubuntu
    :return: list of dictionaries of default context attributes
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    if local:
        result = process.run("semanage fcontext --list -C", ignore_status=True)
    else:
        result = process.run("semanage fcontext --list", ignore_status=True)
    _no_semanage(result)
    if result.exit_status != 0:
        raise SeCmdError('semanage', results_stderr_52lts(result))
    result_list = results_stdout_52lts(result).strip().split('\n')
    # Need to process top-down instead of bottom-up
    result_list.reverse()
    first_line = result_list.pop()
    # First column name has a space in it
    column_names = [name.strip().lower().replace(' ', '_')
                    for name in first_line.split('  ')
                    if len(name) > 0]
    # Shorten first column name
    column_names[0] = column_names[0].replace("selinux_", "")
    fcontexts = []
    for line in result_list:
        if len(line) < 1:  # skip blank lines
            continue
        column_data = [name.strip()
                       for name in line.split('  ')
                       if len(name) > 0]
        # Enumerating data raises exception if no column_names match
        fcontext = dict([(column_names[idx], data)
                         for idx, data in enumerate(column_data)])
        # find/set functions only accept type, not full context string
        fcontext['context'] = get_type_from_context(fcontext['context'])
        fcontexts.append(fcontext)
    return fcontexts
Ejemplo n.º 48
0
    def compare_images(self, image1, image2, strict_mode=False,
                       verbose=True, force_share=False):
        """
        Compare 2 images using the appropriate tools for each virt backend.

        :param image1: image path of first image
        :param image2: image path of second image
        :param strict_mode: Boolean value, True for strict mode,
                            False for default mode.
        :param verbose: Record output in debug file or not

        :return: process.CmdResult object containing the result of the command
        """
        compare_images = self.support_cmd("compare")
        force_share &= self.cap_force_share
        if not compare_images:
            logging.warn("sub-command compare not supported by qemu-img")
            return None
        else:
            logging.info("Comparing images %s and %s", image1, image2)
            compare_cmd = "%s compare" % self.image_cmd
            if force_share:
                compare_cmd += " -U"
            if strict_mode:
                compare_cmd += " -s"
            compare_cmd += " %s %s" % (image1, image2)
            cmd_result = process.run(compare_cmd, ignore_status=True,
                                     shell=True)

            if verbose:
                logging.debug("Output from command: %s",
                              results_stdout_52lts(cmd_result))

            if cmd_result.exit_status == 0:
                logging.info("Compared images are equal")
            elif cmd_result.exit_status == 1:
                raise exceptions.TestFail("Compared images differ")
            else:
                raise exceptions.TestError("Error in image comparison")

            cmd_result.stdout = results_stdout_52lts(cmd_result)
            cmd_result.stderr = results_stderr_52lts(cmd_result)
            return cmd_result
Ejemplo n.º 49
0
def v2v_cmd(params):
    """
    Append 'virt-v2v' and execute it.

    :param params: A dictionary includes all of required parameters such as
                    'target', 'hypervisor' and 'hostname', etc.
    :return: A CmdResult object
    """
    if V2V_EXEC is None:
        raise ValueError('Missing command: virt-v2v')

    target = params.get('target')
    hypervisor = params.get('hypervisor')
    hostname = params.get('hostname')
    vpx_dc = params.get('vpx_dc')
    esx_ip = params.get('esx_ip')
    opts_extra = params.get('v2v_opts')
    v2v_timeout = params.get('v2v_timeout', 2400)
    rhv_upload_opts = params.get('rhv_upload_opts')

    uri_obj = Uri(hypervisor)
    # Return actual 'uri' according to 'hostname' and 'hypervisor'
    uri = uri_obj.get_uri(hostname, vpx_dc, esx_ip)

    target_obj = Target(target, uri)
    # Return virt-v2v command line options based on 'target' and 'hypervisor'
    options = target_obj.get_cmd_options(params)

    if rhv_upload_opts:
        options = options + ' ' + rhv_upload_opts
    if opts_extra:
        options = options + ' ' + opts_extra

    # Construct a final virt-v2v command
    cmd = '%s %s' % (V2V_EXEC, options)
    cmd_result = process.run(cmd,
                             timeout=v2v_timeout,
                             verbose=True,
                             ignore_status=True)
    cmd_result.stdout = results_stdout_52lts(cmd_result)
    cmd_result.stderr = results_stderr_52lts(cmd_result)
    return cmd_result
Ejemplo n.º 50
0
def get_context_of_file(filename, selinux_force=False):
    """
    Get the context of file.

    :param filename: filename for the context to be get
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SeCmdError: if execute 'getfattr' failed.
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    # More direct than scraping 'ls' output.
    cmd = "getfattr --name security.selinux %s" % filename
    result = process.run(cmd, ignore_status=True)
    if result.exit_status:
        raise SeCmdError(cmd, results_stderr_52lts(result))

    output = results_stdout_52lts(result)
    return get_context_from_str(output)
Ejemplo n.º 51
0
def get_context_of_file(filename, selinux_force=False):
    """
    Get the context of file.

    :param filename: filename for the context to be get
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SeCmdError: if execute 'getfattr' failed.
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    # More direct than scraping 'ls' output.
    cmd = "getfattr --name security.selinux %s" % filename
    result = process.run(cmd, ignore_status=True)
    if result.exit_status:
        raise SeCmdError(cmd, results_stderr_52lts(result))

    output = results_stdout_52lts(result)
    return get_context_from_str(output)
Ejemplo n.º 52
0
def set_status(status, selinux_force=False):
    """
    Set status of selinux.

    :param status: status want to set selinux.
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SelinuxError: status is not supported.
    :raise SelinuxError: need to reboot host.
    :raise SeCmdError: execute setenforce failed.
    :raise SelinuxError: cmd setenforce exit normally,
                but status of selinux is not set to expected.
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    if status not in STATUS_LIST:
        raise SelinuxError("Status %s is not accepted." % status)

    current_status = get_status(selinux_force)
    if status == current_status:
        return
    else:
        if current_status == "disabled" or status == "disabled":
            raise SelinuxError("Please modify /etc/selinux/config and "
                               "reboot host to set selinux to %s." % status)
        else:
            cmd = "setenforce %s" % status
            result = process.run(cmd, ignore_status=True)
            if result.exit_status:
                raise SeCmdError(cmd, results_stderr_52lts(result))
            else:
                current_status = get_status(selinux_force)
                if not status == current_status:
                    raise SelinuxError("Status of selinux is set to %s,"
                                       "but not expected %s. "
                                       % (current_status, status))
                else:
                    pass

    logging.debug("Set status of selinux to %s success.", status)
Ejemplo n.º 53
0
def set_status(status, selinux_force=False):
    """
    Set status of selinux.

    :param status: status want to set selinux.
    :param selinux_force: True to force selinux configuration on Ubuntu
    :raise SelinuxError: status is not supported.
    :raise SelinuxError: need to reboot host.
    :raise SeCmdError: execute setenforce failed.
    :raise SelinuxError: cmd setenforce exit normally,
                but status of selinux is not set to expected.
    """
    if ubuntu and not selinux_force:
        logging.warning("Ubuntu doesn't support selinux by default")
        return

    if status not in STATUS_LIST:
        raise SelinuxError("Status %s is not accepted." % status)

    current_status = get_status(selinux_force)
    if status == current_status:
        return
    else:
        if current_status == "disabled" or status == "disabled":
            raise SelinuxError("Please modify /etc/selinux/config and "
                               "reboot host to set selinux to %s." % status)
        else:
            cmd = "setenforce %s" % status
            result = process.run(cmd, ignore_status=True)
            if result.exit_status:
                raise SeCmdError(cmd, results_stderr_52lts(result))
            else:
                current_status = get_status(selinux_force)
                if not status == current_status:
                    raise SelinuxError("Status of selinux is set to %s,"
                                       "but not expected %s. "
                                       % (current_status, status))
                else:
                    pass

    logging.debug("Set status of selinux to %s success.", status)
Ejemplo n.º 54
0
def v2v_cmd(params):
    """
    Append 'virt-v2v' and execute it.

    :param params: A dictionary includes all of required parameters such as
                    'target', 'hypervisor' and 'hostname', etc.
    :return: A CmdResult object
    """
    if V2V_EXEC is None:
        raise ValueError('Missing command: virt-v2v')

    target = params.get('target')
    hypervisor = params.get('hypervisor')
    hostname = params.get('hostname')
    vpx_dc = params.get('vpx_dc')
    esx_ip = params.get('esx_ip')
    opts_extra = params.get('v2v_opts')
    v2v_timeout = params.get('v2v_timeout', 5400)
    rhv_upload_opts = params.get('rhv_upload_opts')

    uri_obj = Uri(hypervisor)
    # Return actual 'uri' according to 'hostname' and 'hypervisor'
    uri = uri_obj.get_uri(hostname, vpx_dc, esx_ip)

    target_obj = Target(target, uri)
    # Return virt-v2v command line options based on 'target' and 'hypervisor'
    options = target_obj.get_cmd_options(params)

    if rhv_upload_opts:
        options = options + ' ' + rhv_upload_opts
    if opts_extra:
        options = options + ' ' + opts_extra

    # Construct a final virt-v2v command
    cmd = '%s %s' % (V2V_EXEC, options)
    cmd_result = process.run(cmd, timeout=v2v_timeout,
                             verbose=True, ignore_status=True)
    cmd_result.stdout = results_stdout_52lts(cmd_result)
    cmd_result.stderr = results_stderr_52lts(cmd_result)
    return cmd_result
Ejemplo n.º 55
0
    def check_image(self, params, root_dir, force_share=False):
        """
        Check an image using the appropriate tools for each virt backend.

        :param params: Dictionary containing the test parameters.
        :param root_dir: Base directory for relative filenames.

        :note: params should contain:
               image_name -- the name of the image file, without extension
               image_format -- the format of the image (qcow2, raw etc)

        :raise VMImageCheckError: In case qemu-img check fails on the image.
        """
        image_filename = self.image_filename
        logging.debug("Checking image file %s", image_filename)
        image_is_checkable = self.image_format in ['qcow2', 'qed']
        force_share &= self.cap_force_share

        if (storage.file_exists(params, image_filename) or
                self.is_remote_image()) and image_is_checkable:
            check_img = self.support_cmd("check") and self.support_cmd("info")
            if not check_img:
                logging.debug("Skipping image check "
                              "(lack of support in qemu-img)")
            else:
                try:
                    # FIXME: do we really need it?
                    self.info(force_share)
                except process.CmdError:
                    logging.error("Error getting info from image %s",
                                  image_filename)

                chk_cmd = "%s check" % self.image_cmd
                if force_share:
                    chk_cmd += " -U"
                chk_cmd += " %s" % image_filename
                cmd_result = process.run(chk_cmd, ignore_status=True,
                                         shell=True, verbose=False)
                # Error check, large chances of a non-fatal problem.
                # There are chances that bad data was skipped though
                if cmd_result.exit_status == 1:
                    stdout = results_stdout_52lts(cmd_result)
                    for e_line in stdout.splitlines():
                        logging.error("[stdout] %s", e_line)
                    stderr = results_stderr_52lts(cmd_result)
                    for e_line in stderr.splitlines():
                        logging.error("[stderr] %s", e_line)
                    chk = params.get("backup_image_on_check_error", "no")
                    if chk == "yes":
                        self.backup_image(params, root_dir, "backup", False)
                    raise exceptions.TestWarn("qemu-img check exceptions. Some bad "
                                              "data in the image may have gone"
                                              " unnoticed (%s)" % image_filename)
                # Exit status 2 is data corruption for sure,
                # so fail the test
                elif cmd_result.exit_status == 2:
                    stdout = results_stdout_52lts(cmd_result)
                    for e_line in stdout.splitlines():
                        logging.error("[stdout] %s", e_line)
                    stderr = results_stderr_52lts(cmd_result)
                    for e_line in stderr.splitlines():
                        logging.error("[stderr] %s", e_line)
                    chk = params.get("backup_image_on_check_error", "no")
                    if chk == "yes":
                        self.backup_image(params, root_dir, "backup", False)
                    raise virt_vm.VMImageCheckError(image_filename)
                # Leaked clusters, they are known to be harmless to data
                # integrity
                elif cmd_result.exit_status == 3:
                    raise exceptions.TestWarn("Leaked clusters were noticed"
                                              " during image check. No data "
                                              "integrity problem was found "
                                              "though. (%s)" % image_filename)

                # Just handle normal operation
                if params.get("backup_image", "no") == "yes":
                    self.backup_image(params, root_dir, "backup", True, True)
        else:
            if not storage.file_exists(params, image_filename):
                logging.debug("Image file %s not found, skipping check",
                              image_filename)
            elif not image_is_checkable:
                logging.debug(
                    "Image format %s is not checkable, skipping check",
                    self.image_format)
def run(test, params, env):
    """
    Test virsh migrate command.
    """

    def set_feature(vmxml, feature, value):
        """
        Set guest features for PPC

        :param state: the htm status
        :param vmxml: guest xml
        """
        features_xml = vm_xml.VMFeaturesXML()
        if feature == 'hpt':
            features_xml.hpt_resizing = value
        elif feature == 'htm':
            features_xml.htm = value
        vmxml.features = features_xml
        vmxml.sync()

    def trigger_hpt_resize(session):
        """
        Check the HPT order file and dmesg

        :param session: the session to guest

        :raise: test.fail if required message is not found
        """
        hpt_order_path = "/sys/kernel/debug/powerpc/hpt_order"
        hpt_order = session.cmd_output('cat %s' % hpt_order_path).strip()
        hpt_order = int(hpt_order)
        logging.info('Current hpt_order is %d', hpt_order)
        hpt_order += 1
        cmd = 'echo %d > %s' % (hpt_order, hpt_order_path)
        cmd_result = session.cmd_status_output(cmd)
        result = process.CmdResult(stderr=cmd_result[1],
                                   stdout=cmd_result[1],
                                   exit_status=cmd_result[0])
        libvirt.check_exit_status(result)
        dmesg = session.cmd('dmesg')
        dmesg_content = params.get('dmesg_content').split('|')
        for content in dmesg_content:
            if content % hpt_order not in dmesg:
                test.fail("'%s' is missing in dmesg" % (content % hpt_order))
            else:
                logging.info("'%s' is found in dmesg", content % hpt_order)

    def check_vm_network_accessed(session=None):
        """
        The operations to the VM need to be done before or after
        migration happens

        :param session: The session object to the host

        :raise: test.error when ping fails
        """
        # Confirm local/remote VM can be accessed through network.
        logging.info("Check VM network connectivity")
        s_ping, _ = utils_test.ping(vm.get_address(),
                                    count=10,
                                    timeout=20,
                                    output_func=logging.debug,
                                    session=session)
        if s_ping != 0:
            if session:
                session.close()
            test.fail("%s did not respond after %d sec." % (vm.name, 20))

    def check_virsh_command_and_option(command, option=None):
        """
        Check if virsh command exists

        :param command: the command to be checked
        :param option: the command option to be checked
        """
        msg = "This version of libvirt does not support "
        if not virsh.has_help_command(command):
            test.cancel(msg + "virsh command '%s'" % command)

        if option and not virsh.has_command_help_match(command, option):
            test.cancel(msg + "virsh command '%s' with option '%s'" % (command,
                                                                       option))

    def add_ctrls(vm_xml, dev_type="pci", dev_index="0", dev_model="pci-root"):
        """
        Add multiple devices

        :param dev_type: the type of the device to be added
        :param dev_index: the maximum index of the device to be added
        :param dev_model: the model of the device to be added
        """
        for inx in range(0, int(dev_index) + 1):
            newcontroller = Controller("controller")
            newcontroller.type = dev_type
            newcontroller.index = inx
            newcontroller.model = dev_model
            logging.debug("New device is added:\n%s", newcontroller)
            vm_xml.add_device(newcontroller)
        vm_xml.sync()

    def do_migration(vm, dest_uri, options, extra):
        """
        Execute the migration with given parameters
        :param vm: the guest to be migrated
        :param dest_uri: the destination uri for migration
        :param options: options next to 'migrate' command
        :param extra: options in the end of the migrate command line

        :return: CmdResult object
        """
        logging.info("Sleeping 10 seconds before migration")
        time.sleep(10)
        # Migrate the guest.
        virsh_args.update({"ignore_status": True})
        migration_res = vm.migrate(dest_uri, options, extra, **virsh_args)
        if int(migration_res.exit_status) != 0:
            logging.error("Migration failed for %s.", vm_name)
            return migration_res

        if vm.is_alive():  # vm.connect_uri was updated
            logging.info("VM is alive on destination %s.", dest_uri)
        else:
            test.fail("VM is not alive on destination %s" % dest_uri)

        # Throws exception if console shows panic message
        vm.verify_kernel_crash()
        return migration_res

    def cleanup_libvirtd_log(log_file):
        """
        Remove existing libvirtd log file on source and target host.

        :param log_file: log file with absolute path
        """
        if os.path.exists(log_file):
            logging.debug("Delete local libvirt log file '%s'", log_file)
            os.remove(log_file)
        cmd = "rm -f %s" % log_file
        logging.debug("Delete remote libvirt log file '%s'", log_file)
        cmd_parms = {'server_ip': server_ip, 'server_user': server_user, 'server_pwd': server_pwd}
        remote.run_remote_cmd(cmd, cmd_parms, runner_on_target)

    def cleanup_dest(vm):
        """
        Clean up the destination host environment
        when doing the uni-direction migration.

        :param vm: the guest to be cleaned up
        """
        logging.info("Cleaning up VMs on %s", vm.connect_uri)
        try:
            if virsh.domain_exists(vm.name, uri=vm.connect_uri):
                vm_state = vm.state()
                if vm_state == "paused":
                    vm.resume()
                elif vm_state == "shut off":
                    vm.start()
                vm.destroy(gracefully=False)

                if vm.is_persistent():
                    vm.undefine()

        except Exception as detail:
            logging.error("Cleaning up destination failed.\n%s", detail)

    def run_stress_in_vm():
        """
        The function to load stress in VM
        """
        stress_args = params.get("stress_args", "--cpu 8 --io 4 "
                                 "--vm 2 --vm-bytes 128M "
                                 "--timeout 20s")
        try:
            vm_session.cmd('stress %s' % stress_args)
        except Exception as detail:
            logging.debug(detail)

    def control_migrate_speed(to_speed=1):
        """
        Control migration duration

        :param to_speed: the speed value in Mbps to be set for migration
        :return int: the new migration speed after setting
        """
        virsh_args.update({"ignore_status": False})
        old_speed = virsh.migrate_getspeed(vm_name, **virsh_args)
        logging.debug("Current migration speed is %s MiB/s\n", old_speed.stdout.strip())
        logging.debug("Set migration speed to %d MiB/s\n", to_speed)
        cmd_result = virsh.migrate_setspeed(vm_name, to_speed, "", **virsh_args)
        actual_speed = virsh.migrate_getspeed(vm_name, **virsh_args)
        logging.debug("New migration speed is %s MiB/s\n", actual_speed.stdout.strip())
        return int(actual_speed.stdout.strip())

    def check_setspeed(params):
        """
        Set/get migration speed

        :param params: the parameters used
        :raise: test.fail if speed set does not take effect
        """
        expected_value = int(params.get("migrate_speed", '41943040')) // (1024 * 1024)
        actual_value = control_migrate_speed(to_speed=expected_value)
        params.update({'compare_to_value': actual_value})
        if actual_value != expected_value:
            test.fail("Migration speed is expected to be '%d MiB/s', but '%d MiB/s' "
                      "found" % (expected_value, actual_value))

    def check_domjobinfo(params, option=""):
        """
        Check given item in domjobinfo of the guest is as expected

        :param params: the parameters used
        :param option: options for domjobinfo
        :raise: test.fail if the value of given item is unexpected
        """
        def search_jobinfo(jobinfo):
            """
            Find value of given item in domjobinfo

            :param jobinfo: cmdResult object
            :raise: test.fail if not found
            """
            for item in jobinfo.stdout.splitlines():
                if item.count(jobinfo_item):
                    groups = re.findall(r'[0-9.]+', item.strip())
                    logging.debug("In '%s' search '%s'\n", item, groups[0])
                    if (math.fabs(float(groups[0]) - float(compare_to_value)) //
                       float(compare_to_value) > diff_rate):
                        test.fail("{} {} has too much difference from "
                                  "{}".format(jobinfo_item,
                                              groups[0],
                                              compare_to_value))
                break

        jobinfo_item = params.get("jobinfo_item")
        compare_to_value = params.get("compare_to_value")
        logging.debug("compare_to_value:%s", compare_to_value)
        diff_rate = float(params.get("diff_rate", "0"))
        if not jobinfo_item or not compare_to_value:
            return
        vm_ref = '{}{}'.format(vm_name, option)
        jobinfo = virsh.domjobinfo(vm_ref, **virsh_args)
        search_jobinfo(jobinfo)

        check_domjobinfo_remote = params.get("check_domjobinfo_remote")
        if check_domjobinfo_remote:
            remote_virsh_session = virsh.VirshPersistent(**remote_virsh_dargs)
            jobinfo = remote_virsh_session.domjobinfo(vm_ref, **virsh_args)
            search_jobinfo(jobinfo)
            remote_virsh_session.close_session()

    def check_maxdowntime(params):
        """
        Set/get migration maxdowntime

        :param params: the parameters used
        :raise: test.fail if maxdowntime set does not take effect
        """
        expected_value = int(float(params.get("migrate_maxdowntime", '0.3')) * 1000)
        virsh_args.update({"ignore_status": False})
        old_value = int(virsh.migrate_getmaxdowntime(vm_name).stdout.strip())
        logging.debug("Current migration maxdowntime is %d ms", old_value)
        logging.debug("Set migration maxdowntime to %d ms", expected_value)
        virsh.migrate_setmaxdowntime(vm_name, expected_value, **virsh_args)
        actual_value = int(virsh.migrate_getmaxdowntime(vm_name).stdout.strip())
        logging.debug("New migration maxdowntime is %d ms", actual_value)
        if actual_value != expected_value:
            test.fail("Migration maxdowntime is expected to be '%d ms', but '%d ms' "
                      "found" % (expected_value, actual_value))
        params.update({'compare_to_value': actual_value})

    def do_actions_during_migrate(params):
        """
        The entry point to execute action list during migration

        :param params: the parameters used
        """
        actions_during_migration = params.get("actions_during_migration")
        if not actions_during_migration:
            return
        for action in actions_during_migration.split(","):
            if action == 'setspeed':
                check_setspeed(params)
            elif action == 'domjobinfo':
                check_domjobinfo(params)
            elif action == 'setmaxdowntime':
                check_maxdowntime(params)
            time.sleep(3)

    def attach_channel_xml():
        """
        Create channel xml and attach it to guest configuration
        """
        # Check if pty channel exists already
        for elem in new_xml.devices.by_device_tag('channel'):
            if elem.type_name == channel_type_name:
                logging.debug("{0} channel already exists in guest. "
                              "No need to add new one".format(channel_type_name))
                return

        params = {'channel_type_name': channel_type_name,
                  'target_type': target_type,
                  'target_name': target_name}
        channel_xml = libvirt.create_channel_xml(params)
        virsh.attach_device(domain_opt=vm_name, file_opt=channel_xml.xml,
                            flagstr="--config", ignore_status=False)
        logging.debug("New VMXML with channel:\n%s", virsh.dumpxml(vm_name))

    def check_timeout_postcopy(params):
        """
        Check the vm state on target host after timeout
        when --postcopy and --timeout-postcopy are used.
        The vm state is expected as running.

        :param params: the parameters used
        """
        timeout = int(params.get("timeout_postcopy", 10))
        time.sleep(timeout + 1)
        remote_virsh_session = virsh.VirshPersistent(**remote_virsh_dargs)
        vm_state = results_stdout_52lts(remote_virsh_session.domstate(vm_name)).strip()
        if vm_state != "running":
            remote_virsh_session.close_session()
            test.fail("After timeout '%s' seconds, "
                      "the vm state on target host should "
                      "be 'running', but '%s' found",
                      timeout, vm_state)
        remote_virsh_session.close_session()

    def get_usable_compress_cache(pagesize):
        """
        Get a number which is bigger than pagesize and is power of two.

        :param pagesize: the given integer
        :return: an integer satisfying the criteria
        """
        def calculate(num):
            result = num & (num - 1)
            return (result == 0)

        item = pagesize
        found = False
        while (not found):
            item += 1
            found = calculate(item)
        logging.debug("%d is smallest one that is bigger than '%s' and "
                      "is power of 2", item, pagesize)
        return item

    def check_migration_res(result):
        """
        Check if the migration result is as expected

        :param result: the output of migration
        :raise: test.fail if test is failed
        """
        logging.info("Migration out: %s", results_stdout_52lts(result).strip())
        logging.info("Migration error: %s", results_stderr_52lts(result).strip())

        if status_error:  # Migration should fail
            if err_msg:   # Special error messages are expected
                if not re.search(err_msg, results_stderr_52lts(result).strip()):
                    test.fail("Can not find the expected patterns '%s' in "
                              "output '%s'" % (err_msg,
                                               results_stderr_52lts(result).strip()))
                else:
                    logging.debug("It is the expected error message")
            else:
                if int(result.exit_status) != 0:
                    logging.debug("Migration failure is expected result")
                else:
                    test.fail("Migration success is unexpected result")
        else:
            if int(result.exit_status) != 0:
                test.fail(results_stderr_52lts(result).strip())

    check_parameters(test, params)

    # Params for NFS shared storage
    shared_storage = params.get("migrate_shared_storage", "")
    if shared_storage == "":
        default_guest_asset = defaults.get_default_guest_os_info()['asset']
        default_guest_asset = "%s.qcow2" % default_guest_asset
        shared_storage = os.path.join(params.get("nfs_mount_dir"),
                                      default_guest_asset)
        logging.debug("shared_storage:%s", shared_storage)

    # params for migration connection
    params["virsh_migrate_desturi"] = libvirt_vm.complete_uri(
                                       params.get("migrate_dest_host"))
    # Params to update disk using shared storage
    params["disk_type"] = "file"
    params["disk_source_protocol"] = "netfs"
    params["mnt_path_name"] = params.get("nfs_mount_dir")

    # Local variables
    virsh_args = {"debug": True}
    virsh_opt = params.get("virsh_opt", "")
    server_ip = params.get("server_ip")
    server_user = params.get("server_user", "root")
    server_pwd = params.get("server_pwd")
    extra = params.get("virsh_migrate_extra")
    options = params.get("virsh_migrate_options")
    src_uri = params.get("virsh_migrate_connect_uri")
    dest_uri = params.get("virsh_migrate_desturi")
    log_file = params.get("libvirt_log", "/var/log/libvirt/libvirtd.log")
    check_complete_job = "yes" == params.get("check_complete_job", "no")
    config_libvirtd = "yes" == params.get("config_libvirtd", "no")
    contrl_index = params.get("new_contrl_index", None)
    asynch_migration = "yes" == params.get("asynch_migrate", "no")
    grep_str_remote_log = params.get("grep_str_remote_log", "")
    grep_str_local_log = params.get("grep_str_local_log", "")
    disable_verify_peer = "yes" == params.get("disable_verify_peer", "no")
    status_error = "yes" == params.get("status_error", "no")
    stress_in_vm = "yes" == params.get("stress_in_vm", "no")
    low_speed = params.get("low_speed", None)
    remote_virsh_dargs = {'remote_ip': server_ip, 'remote_user': server_user,
                          'remote_pwd': server_pwd, 'unprivileged_user': None,
                          'ssh_remote_auth': True}

    hpt_resize = params.get("hpt_resize", None)
    htm_state = params.get("htm_state", None)

    # For pty channel test
    add_channel = "yes" == params.get("add_channel", "no")
    channel_type_name = params.get("channel_type_name", None)
    target_type = params.get("target_type", None)
    target_name = params.get("target_name", None)
    cmd_run_in_remote_guest = params.get("cmd_run_in_remote_guest", None)
    cmd_run_in_remote_guest_1 = params.get("cmd_run_in_remote_guest_1", None)
    cmd_run_in_remote_host = params.get("cmd_run_in_remote_host", None)
    cmd_run_in_remote_host_1 = params.get("cmd_run_in_remote_host_1", None)
    cmd_run_in_remote_host_2 = params.get("cmd_run_in_remote_host_2", None)

    # For qemu command line checking
    qemu_check = params.get("qemu_check", None)

    xml_check_after_mig = params.get("guest_xml_check_after_mig", None)

    # params for cache matrix test
    cache = params.get("cache")
    remove_cache = "yes" == params.get("remove_cache", "no")
    err_msg = params.get("err_msg")

    arch = platform.machine()
    if any([hpt_resize, contrl_index, htm_state]) and 'ppc64' not in arch:
        test.cancel("The case is PPC only.")

    # For TLS
    tls_recovery = params.get("tls_auto_recovery", "yes")
    # qemu config
    qemu_conf_dict = None
    # libvirtd config
    libvirtd_conf_dict = None

    remote_virsh_session = None
    vm = None
    vm_session = None
    libvirtd_conf = None
    qemu_conf = None
    mig_result = None
    test_exception = None
    is_TestError = False
    is_TestFail = False
    is_TestSkip = False

    # Objects to be cleaned up in the end
    objs_list = []
    tls_obj = None

    # Local variables
    vm_name = params.get("migrate_main_vm")
    vm = env.get_vm(vm_name)
    vm.verify_alive()

    # For safety reasons, we'd better back up  xmlfile.
    new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    orig_config_xml = new_xml.copy()
    if not orig_config_xml:
        test.error("Backing up xmlfile failed.")

    try:
        # Create a remote runner for later use
        runner_on_target = remote.RemoteRunner(host=server_ip,
                                               username=server_user,
                                               password=server_pwd)

        # Change the configuration files if needed before starting guest
        # For qemu.conf
        if extra.count("--tls"):
            # Setup TLS
            tls_obj = TLSConnection(params)
            if tls_recovery == "yes":
                objs_list.append(tls_obj)
                tls_obj.auto_recover = True
                tls_obj.conn_setup()
            if not disable_verify_peer:
                qemu_conf_dict = {"migrate_tls_x509_verify": "1"}
                # Setup qemu configure
                logging.debug("Configure the qemu")
                cleanup_libvirtd_log(log_file)
                qemu_conf = libvirt.customize_libvirt_config(qemu_conf_dict,
                                                             config_type="qemu",
                                                             remote_host=True,
                                                             extra_params=params)
        # Setup libvirtd
        if config_libvirtd:
            logging.debug("Configure the libvirtd")
            cleanup_libvirtd_log(log_file)
            libvirtd_conf_dict = setup_libvirtd_conf_dict(params)
            libvirtd_conf = libvirt.customize_libvirt_config(libvirtd_conf_dict,
                                                             remote_host=True,
                                                             extra_params=params)
        # Prepare required guest xml before starting guest
        if contrl_index:
            new_xml.remove_all_device_by_type('controller')
            logging.debug("After removing controllers, current XML:\n%s\n", new_xml)
            add_ctrls(new_xml, dev_index=contrl_index)

        if add_channel:
            attach_channel_xml()

        if hpt_resize:
            set_feature(new_xml, 'hpt', hpt_resize)

        if htm_state:
            set_feature(new_xml, 'htm', htm_state)

        if cache:
            params["driver_cache"] = cache
        if remove_cache:
            params["enable_cache"] = "no"

        # Change the disk of the vm to shared disk and then start VM
        libvirt.set_vm_disk(vm, params)

        if not vm.is_alive():
            vm.start()

        logging.debug("Guest xml after starting:\n%s", vm_xml.VMXML.new_from_dumpxml(vm_name))

        # Check qemu command line after guest is started
        if qemu_check:
            check_content = qemu_check
            if hpt_resize:
                check_content = "%s%s" % (qemu_check, hpt_resize)
            if htm_state:
                check_content = "%s%s" % (qemu_check, htm_state)
            libvirt.check_qemu_cmd_line(check_content)

        # Check local guest network connection before migration
        vm_session = vm.wait_for_login()
        check_vm_network_accessed()

        # Preparation for the running guest before migration
        if hpt_resize and hpt_resize != 'disabled':
            trigger_hpt_resize(vm_session)

        if low_speed:
            control_migrate_speed(int(low_speed))

        if stress_in_vm:
            pkg_name = 'stress'
            logging.debug("Check if stress tool is installed")
            pkg_mgr = utils_package.package_manager(vm_session, pkg_name)
            if not pkg_mgr.is_installed(pkg_name):
                logging.debug("Stress tool will be installed")
                if not pkg_mgr.install():
                    test.error("Package '%s' installation fails" % pkg_name)

            stress_thread = threading.Thread(target=run_stress_in_vm,
                                             args=())
            stress_thread.start()

        if extra.count("timeout-postcopy"):
            func_name = check_timeout_postcopy
        if params.get("actions_during_migration"):
            func_name = do_actions_during_migrate
        if extra.count("comp-xbzrle-cache"):
            cache = get_usable_compress_cache(memory.get_page_size())
            extra = "%s %s" % (extra, cache)

        # For --postcopy enable
        postcopy_options = params.get("postcopy_options")
        if postcopy_options:
            extra = "%s %s" % (extra, postcopy_options)

        # Execute migration process
        if not asynch_migration:
            mig_result = do_migration(vm, dest_uri, options, extra)
        else:
            migration_test = libvirt.MigrationTest()

            logging.debug("vm.connect_uri=%s", vm.connect_uri)
            vms = [vm]
            try:
                migration_test.do_migration(vms, None, dest_uri, 'orderly',
                                            options, thread_timeout=900,
                                            ignore_status=True, virsh_opt=virsh_opt,
                                            func=func_name, extra_opts=extra,
                                            func_params=params)
                mig_result = migration_test.ret
            except exceptions.TestFail as fail_detail:
                test.fail(fail_detail)
            except exceptions.TestSkipError as skip_detail:
                test.cancel(skip_detail)
            except exceptions.TestError as error_detail:
                test.error(error_detail)
            except Exception as details:
                mig_result = migration_test.ret
                logging.error(details)

        check_migration_res(mig_result)

        if add_channel:
            # Get the channel device source path of remote guest
            if not remote_virsh_session:
                remote_virsh_session = virsh.VirshPersistent(**remote_virsh_dargs)
            file_path = tempfile.mktemp(dir=data_dir.get_tmp_dir())
            remote_virsh_session.dumpxml(vm_name, to_file=file_path,
                                         debug=True,
                                         ignore_status=True)
            local_vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            local_vmxml.xmltreefile = xml_utils.XMLTreeFile(file_path)
            for elem in local_vmxml.devices.by_device_tag('channel'):
                logging.debug("Found channel device {}".format(elem))
                if elem.type_name == channel_type_name:
                    host_source = elem.source.get('path')
                    logging.debug("Remote guest uses {} for channel device".format(host_source))
                    break
            remote_virsh_session.close_session()
            if not host_source:
                test.fail("Can not find source for %s channel on remote host" % channel_type_name)

            # Prepare to wait for message on remote host from the channel
            cmd_parms = {'server_ip': server_ip, 'server_user': server_user, 'server_pwd': server_pwd}
            cmd_result = remote.run_remote_cmd(cmd_run_in_remote_host % host_source,
                                               cmd_parms,
                                               runner_on_target)

            # Send message from remote guest to the channel file
            remote_vm_obj = utils_test.RemoteVMManager(cmd_parms)
            vm_ip = vm.get_address()
            vm_pwd = params.get("password")
            remote_vm_obj.setup_ssh_auth(vm_ip, vm_pwd)
            cmd_result = remote_vm_obj.run_command(vm_ip, cmd_run_in_remote_guest_1)
            remote_vm_obj.run_command(vm_ip, cmd_run_in_remote_guest % results_stdout_52lts(cmd_result).strip())
            logging.debug("Sending message is done")

            # Check message on remote host from the channel
            remote.run_remote_cmd(cmd_run_in_remote_host_1, cmd_parms, runner_on_target)
            logging.debug("Receiving message is done")
            remote.run_remote_cmd(cmd_run_in_remote_host_2, cmd_parms, runner_on_target)

        if check_complete_job:
            opts = " --completed"
            check_virsh_command_and_option("domjobinfo", opts)
            if extra.count("comp-xbzrle-cache"):
                params.update({'compare_to_value': cache // 1024})
            check_domjobinfo(params, option=opts)

        if grep_str_local_log:
            cmd = "grep -E '%s' %s" % (grep_str_local_log, log_file)
            cmdRes = process.run(cmd, shell=True, ignore_status=True)
            if cmdRes.exit_status:
                test.fail(results_stderr_52lts(cmdRes).strip())
        if grep_str_remote_log:
            cmd = "grep -E '%s' %s" % (grep_str_remote_log, log_file)
            cmd_parms = {'server_ip': server_ip, 'server_user': server_user, 'server_pwd': server_pwd}
            remote.run_remote_cmd(cmd, cmd_parms, runner_on_target)

        if xml_check_after_mig:
            if not remote_virsh_session:
                remote_virsh_session = virsh.VirshPersistent(**remote_virsh_dargs)
            target_guest_dumpxml = results_stdout_52lts(
                remote_virsh_session.dumpxml(vm_name,
                                             debug=True,
                                             ignore_status=True)).strip()
            if hpt_resize:
                check_str = hpt_resize
            elif htm_state:
                check_str = htm_state
            if hpt_resize or htm_state:
                xml_check_after_mig = "%s'%s'" % (xml_check_after_mig, check_str)
                if not re.search(xml_check_after_mig, target_guest_dumpxml):
                    remote_virsh_session.close_session()
                    test.fail("Fail to search '%s' in target guest XML:\n%s"
                              % (xml_check_after_mig, target_guest_dumpxml))

            if contrl_index:
                all_ctrls = re.findall(xml_check_after_mig, target_guest_dumpxml)
                if len(all_ctrls) != int(contrl_index) + 1:
                    remote_virsh_session.close_session()
                    test.fail("%s pci-root controllers are expected in guest XML, "
                              "but found %s" % (int(contrl_index) + 1, len(all_ctrls)))
            remote_virsh_session.close_session()

        if int(mig_result.exit_status) == 0:
            server_session = remote.wait_for_login('ssh', server_ip, '22',
                                                   server_user, server_pwd,
                                                   r"[\#\$]\s*$")
            check_vm_network_accessed(server_session)
            server_session.close()
    except exceptions.TestFail as details:
        is_TestFail = True
        test_exception = details
    except exceptions.TestSkipError as details:
        is_TestSkip = True
        test_exception = details
    except exceptions.TestError as details:
        is_TestError = True
        test_exception = details
    except Exception as details:
        test_exception = details
    finally:
        logging.debug("Recover test environment")
        try:
            # Clean VM on destination
            vm.connect_uri = dest_uri
            cleanup_dest(vm)
            vm.connect_uri = src_uri

            logging.info("Recovery VM XML configration")
            orig_config_xml.sync()
            logging.debug("The current VM XML:\n%s", orig_config_xml.xmltreefile)

            if remote_virsh_session:
                remote_virsh_session.close_session()

            if extra.count("--tls") and not disable_verify_peer:
                logging.debug("Recover the qemu configuration")
                libvirt.customize_libvirt_config(None,
                                                 config_type="qemu",
                                                 remote_host=True,
                                                 extra_params=params,
                                                 is_recover=True,
                                                 config_object=qemu_conf)

            if config_libvirtd:
                logging.debug("Recover the libvirtd configuration")
                libvirt.customize_libvirt_config(None,
                                                 remote_host=True,
                                                 extra_params=params,
                                                 is_recover=True,
                                                 config_object=libvirtd_conf)

            logging.info("Remove local NFS image")
            source_file = params.get("source_file")
            libvirt.delete_local_disk("file", path=source_file)

            if objs_list:
                for obj in objs_list:
                    logging.debug("Clean up local objs")
                    del obj

        except Exception as exception_detail:
            if (not test_exception and not is_TestError and
               not is_TestFail and not is_TestSkip):
                raise exception_detail
            else:
                # if any of above exceptions has been raised, only print
                # error log here to avoid of hiding the original issue
                logging.error(exception_detail)
    # Check result
    if is_TestFail:
        test.fail(test_exception)
    if is_TestSkip:
        test.cancel(test_exception)
    if is_TestError:
        test.error(test_exception)
    if not test_exception:
        logging.info("Case execution is done.")
    else:
        test.error(test_exception)
Ejemplo n.º 57
0
    def create(self, params, ignore_errors=False):
        """
        Create an image using qemu_img or dd.

        :param params: Dictionary containing the test parameters.
        :param ignore_errors: Whether to ignore errors on the image creation
                              cmd.

        :note: params should contain:

               image_name
                   name of the image file, without extension
               image_format
                   format of the image (qcow2, raw etc)
               image_cluster_size (optional)
                   cluster size for the image
               image_size
                   requested size of the image (a string qemu-img can
                   understand, such as '10G')
               create_with_dd
                   use dd to create the image (raw format only)
               base_image(optional)
                   the base image name when create snapshot
               base_format(optional)
                   the format of base image
               encrypted(optional)
                   if the image is encrypted, allowed values: on and off.
                   Default is "off"
               preallocated(optional)
                   if preallocation when create image, allowed values: off,
                   metadata. Default is "off"

        :return: tuple (path to the image created, process.CmdResult object
                 containing the result of the creation command).
        """
        if params.get(
                "create_with_dd") == "yes" and self.image_format == "raw":
            # maps K,M,G,T => (count, bs)
            human = {'K': (1, 1),
                     'M': (1, 1024),
                     'G': (1024, 1024),
                     'T': (1024, 1048576),
                     }
            if self.size[-1] in human:
                block_size = human[self.size[-1]][1]
                size = int(self.size[:-1]) * human[self.size[-1]][0]
            qemu_img_cmd = ("dd if=/dev/zero of=%s count=%s bs=%sK"
                            % (self.image_filename, size, block_size))
        else:
            qemu_img_cmd = self.image_cmd
            qemu_img_cmd += " create"

            qemu_img_cmd += " -f %s" % self.image_format

            image_cluster_size = params.get("image_cluster_size", None)
            preallocated = params.get("preallocated", "off")
            encrypted = params.get("encrypted", "off")
            image_extra_params = params.get("image_extra_params", "")
            has_backing_file = params.get('has_backing_file')

            qemu_img_cmd += " -o "
            if self.image_format == "qcow2":
                if preallocated != "off":
                    qemu_img_cmd += "preallocation=%s," % preallocated

                if encrypted != "off":
                    qemu_img_cmd += "encryption=%s," % encrypted

                if image_cluster_size:
                    qemu_img_cmd += "cluster_size=%s," % image_cluster_size

                if has_backing_file == "yes":
                    backing_param = params.object_params("backing_file")
                    backing_file = storage.get_image_filename(backing_param,
                                                              self.root_dir)
                    backing_fmt = backing_param.get("image_format")
                    qemu_img_cmd += "backing_file=%s," % backing_file

                    qemu_img_cmd += "backing_fmt=%s," % backing_fmt

            if image_extra_params:
                qemu_img_cmd += "%s," % image_extra_params

            qemu_img_cmd = qemu_img_cmd.rstrip(" -o")
            qemu_img_cmd = qemu_img_cmd.rstrip(",")

            if self.base_tag:
                qemu_img_cmd += " -b %s" % self.base_image_filename
                if self.base_format:
                    qemu_img_cmd += " -F %s" % self.base_format

            qemu_img_cmd += " %s" % self.image_filename

            qemu_img_cmd += " %s" % self.size

        if (params.get("image_backend", "filesystem") == "filesystem"):
            image_dirname = os.path.dirname(self.image_filename)
            if image_dirname and not os.path.isdir(image_dirname):
                e_msg = ("Parent directory of the image file %s does "
                         "not exist" % self.image_filename)
                logging.error(e_msg)
                logging.error("This usually means a serious setup exceptions.")
                logging.error("Please verify if your data dir contains the "
                              "expected directory structure")
                logging.error("Backing data dir: %s",
                              data_dir.get_backing_data_dir())
                logging.error("Directory structure:")
                for root, _, _ in os.walk(data_dir.get_backing_data_dir()):
                    logging.error(root)

                logging.warning("We'll try to proceed by creating the dir. "
                                "Other errors may ensue")
                os.makedirs(image_dirname)

        msg = "Create image by command: %s" % qemu_img_cmd
        error_context.context(msg, logging.info)
        cmd_result = process.run(
            qemu_img_cmd, shell=True, verbose=False, ignore_status=True)
        if cmd_result.exit_status != 0 and not ignore_errors:
            raise exceptions.TestError("Failed to create image %s" %
                                       self.image_filename)
        cmd_result.stdout = results_stdout_52lts(cmd_result)
        cmd_result.stderr = results_stderr_52lts(cmd_result)
        return self.image_filename, cmd_result