Esempio n. 1
0
 def check_ksm(mem, stress=False):
     """
     :param mem: Boot guest with given memory, in KB
     :param stress: Load stress or not
     """
     params['mem'] = mem // 1024
     params['start_vm'] = 'yes'
     vm_name = params['main_vm']
     env_process.preprocess_vm(test, params, env, vm_name)
     vm = env.get_vm(vm_name)
     vm.wait_for_login()
     if stress:
         params['stress_args'] = ('--cpu 4 --io 4 --vm 2 --vm-bytes %sM' %
                                  (int(params['mem']) // 2))
         stress_test = VMStress(vm, "stress", params)
         stress_test.load_stress_tool()
         time.sleep(30)
     qemu_pid = vm.get_pid()
     qemu_used_page = utils_misc.normalize_data_size(process.getoutput(
         params['cmd_get_qemu_used_mem'] % qemu_pid, shell=True) + 'K', 'B')
     pagesize = utils_memory.getpagesize()
     qemu_used_mem = int(float(qemu_used_page)) * pagesize
     free_mem_host = utils_memory.freememtotal()
     ksm_status = process.getoutput(params['cmd_check_ksm_status'])
     vm.destroy()
     logging.info('The ksm threshold is %s, the memory allocated by qemu is'
                  ' %s, and the total free memory on host is %s.' %
                  (ksm_thres, qemu_used_mem, free_mem_host))
     if free_mem_host >= ksm_thres:
         if ksm_status != '0':
             test.fail('Ksm should not start.')
         if stress:
             test.error('The host resource is not consumed as expected.')
     elif ksm_status == '0':
         test.fail('Ksm should start but it does not.')
Esempio n. 2
0
def get_memory_info(lvms):
    """
    Get memory information from host and guests in format:
    Host: memfree = XXXM; Guests memsh = {XXX,XXX,...}

    :params lvms: List of VM objects
    :return: String with memory info report
    """
    if not isinstance(lvms, list):
        raise error.TestError("Invalid list passed to get_stat: %s " % lvms)

    try:
        meminfo = "Host: memfree = "
        meminfo += str(int(utils_memory.freememtotal()) / 1024) + "M; "
        meminfo += "swapfree = "
        mf = int(utils_memory.read_from_meminfo("SwapFree")) / 1024
        meminfo += str(mf) + "M; "
    except Exception, e:
        raise error.TestFail("Could not fetch host free memory info, "
                             "reason: %s" % e)
Esempio n. 3
0
def get_memory_info(lvms):
    """
    Get memory information from host and guests in format:
    Host: memfree = XXXM; Guests memsh = {XXX,XXX,...}

    :params lvms: List of VM objects
    :return: String with memory info report
    """
    if not isinstance(lvms, list):
        raise error.TestError("Invalid list passed to get_stat: %s " % lvms)

    try:
        meminfo = "Host: memfree = "
        meminfo += str(int(utils_memory.freememtotal()) / 1024) + "M; "
        meminfo += "swapfree = "
        mf = int(utils_memory.read_from_meminfo("SwapFree")) / 1024
        meminfo += str(mf) + "M; "
    except Exception, e:
        raise error.TestFail("Could not fetch host free memory info, "
                             "reason: %s" % e)
Esempio n. 4
0
def run(test, params, env):
    """
    Qemu numa stress test:
    1) Boot up a guest and find the node it used
    2) Try to allocate memory in that node
    3) Run memory heavy stress inside guest
    4) Check the memory use status of qemu process
    5) Repeat step 2 ~ 4 several times


    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    host_numa_node = utils_misc.NumaInfo()
    if len(host_numa_node.online_nodes) < 2:
        raise error.TestNAError("Host only has one NUMA node, "
                                "skipping test...")

    timeout = float(params.get("login_timeout", 240))
    test_count = int(params.get("test_count", 4))
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=timeout)

    qemu_pid = vm.get_pid()

    if test_count < len(host_numa_node.online_nodes):
        test_count = len(host_numa_node.online_nodes)

    tmpfs_size = 0
    for node in host_numa_node.nodes:
        node_mem = int(host_numa_node.read_from_node_meminfo(node, "MemTotal"))
        if tmpfs_size < node_mem:
            tmpfs_size = node_mem
    tmpfs_path = params.get("tmpfs_path", "tmpfs_numa_test")
    tmpfs_path = utils_misc.get_path(data_dir.get_tmp_dir(), tmpfs_path)
    tmpfs_write_speed = int(params.get("tmpfs_write_speed", 10240))
    dd_timeout = tmpfs_size / tmpfs_write_speed * 1.5
    mount_fs_size = "size=%dK" % tmpfs_size
    memory_file = utils_misc.get_path(tmpfs_path, "test")
    dd_cmd = "dd if=/dev/urandom of=%s bs=1k count=%s" % (memory_file,
                                                          tmpfs_size)

    if not os.path.isdir(tmpfs_path):
        os.mkdir(tmpfs_path)

    numa_node_malloc = -1
    most_used_node, memory_used = max_mem_map_node(host_numa_node, qemu_pid)

    for test_round in range(test_count):
        if utils_memory.freememtotal() < tmpfs_size:
            raise error.TestError("Don't have enough memory to execute this "
                                  "test after %s round" % test_round)
        error.context("Executing stress test round: %s" % test_round,
                      logging.info)
        numa_node_malloc = most_used_node
        numa_dd_cmd = "numactl -m %s %s" % (numa_node_malloc, dd_cmd)
        error.context("Try to allocate memory in node %s" % numa_node_malloc,
                      logging.info)
        try:
            utils_misc.mount("none", tmpfs_path, "tmpfs", perm=mount_fs_size)
            funcatexit.register(env, params.get("type"), utils_misc.umount,
                                "none", tmpfs_path, "tmpfs")
            utils.system(numa_dd_cmd, timeout=dd_timeout)
        except Exception, error_msg:
            if "No space" in str(error_msg):
                pass
            else:
                raise error.TestFail("Can not allocate memory in node %s."
                                     " Error message:%s" % (numa_node_malloc,
                                                            str(error_msg)))
        error.context("Run memory heavy stress in guest", logging.info)
        autotest_control.run(test, params, env)
        error.context("Get the qemu process memory use status", logging.info)
        node_after, memory_after = max_mem_map_node(host_numa_node, qemu_pid)
        if node_after == most_used_node and memory_after >= memory_used:
            raise error.TestFail("Memory still stick in "
                                 "node %s" % numa_node_malloc)
        else:
            most_used_node = node_after
            memory_used = memory_after
        utils_misc.umount("none", tmpfs_path, "tmpfs")
        funcatexit.unregister(env, params.get("type"), utils_misc.umount,
                              "none", tmpfs_path, "tmpfs")
        session.cmd("sync; echo 3 > /proc/sys/vm/drop_caches")
        utils_memory.drop_caches()
Esempio n. 5
0
def run_virsh_nodememstats(test, params, env):
    """
    Test the command virsh nodememstats

    (1) Call the virsh nodememstats command
    (2) Get the output
    (3) Check the against /proc/meminfo output
    (4) Call the virsh nodememstats command with an unexpected option
    (5) Call the virsh nodememstats command with libvirtd service stop
    """

    # Initialize the variables
    expected = {}
    actual = {}
    deltas = []
    name_stats = ['total', 'free', 'buffers', 'cached']
    itr = int(params.get("itr"))

    def virsh_check_nodememtats(actual_stats, expected_stats, delta):
        """
        Check the nodememstats output value with /proc/meminfo value
        """

        delta_stats = {}
        for name in name_stats:
            delta_stats[name] = abs(actual_stats[name] - expected_stats[name])
            if 'total' in name:
                if not delta_stats[name] == 0:
                    raise error.TestFail("Command 'virsh nodememstats' not"
                                         " succeeded as the value for %s is "
                                         "deviated by %d\nThe total memory "
                                         "value is deviating-check"
                                         % (name, delta_stats[name]))
            else:
                if delta_stats[name] > delta:
                    raise error.TestFail("Command 'virsh nodememstats' not "
                                         "succeeded as the value for %s"
                                         " is deviated by %d"
                                         % (name, delta_stats[name]))
        return delta_stats

    # Prepare libvirtd service
    check_libvirtd = params.has_key("libvirtd")
    if check_libvirtd:
        libvirtd = params.get("libvirtd")
        if libvirtd == "off":
            utils_libvirtd.libvirtd_stop()

    # Get the option for the test case
    option = params.get("virsh_nodememstats_options")

    # Run test case for 10 iterations
    # (default can be changed in subtests.cfg file)
    # and print the final statistics
    for i in range(itr):
        output = virsh.nodememstats(option)

        # Get the status of the virsh command executed
        status = output.exit_status

        # Get status_error option for the test case
        status_error = params.get("status_error")
        if status_error == "yes":
            if status == 0:
                if libvirtd == "off":
                    utils_libvirtd.libvirtd_start()
                    raise error.TestFail("Command 'virsh nodememstats' "
                                         "succeeded with libvirtd service"
                                         " stopped, incorrect")
                else:
                    raise error.TestFail("Command 'virsh nodememstats %s' "
                                         "succeeded (incorrect command)"
                                         % option)

        elif status_error == "no":
            if status == 0:
                # From the beginning of a line, group 1 is one or
                # more word-characters, followed by zero or more
                # whitespace characters and a ':', then one or
                # more whitespace characters, followed by group 2,
                # which is one or more digit characters,
                # then one or more whitespace characters followed by
                # a literal 'kB' or 'KiB' sequence, e.g as below
                # total  :              3809340 kB
                # total  :              3809340 KiB
                # Normalise the value to MBs
                regex_obj = re.compile(r"^(\w+)\s*:\s+(\d+)\s\w+")
                expected = {}

                for line in output.stdout.split('\n'):
                    match_obj = regex_obj.search(line)
                    # Due to the extra space in the list
                    if match_obj is not None:
                        name = match_obj.group(1)
                        value = match_obj.group(2)
                        expected[name] = int(value) / 1024

                # Get the actual value from /proc/meminfo and normalise to MBs
                actual['total'] = int(utils_memory.memtotal()) / 1024
                actual['free'] = int(utils_memory.freememtotal()) / 1024
                actual['buffers'] = int(
                    utils_memory.read_from_meminfo('Buffers')) / 1024
                actual['cached'] = int(
                    utils_memory.read_from_meminfo('Cached')) / 1024

                # Currently the delta value is kept at 200 MB this can be
                # tuned based on the accuracy
                # Check subtests.cfg for more details
                delta = int(params.get("delta"))
                output = virsh_check_nodememtats(actual, expected, delta)
                deltas.append(output)

            else:
                raise error.TestFail("Command virsh nodememstats %s not "
                                     "succeeded:\n%s" % (option, status))

    # Recover libvirtd service start
    if libvirtd == "off":
        utils_libvirtd.libvirtd_start()

    # Print the deviated values for all iterations
    if status_error == "no":
        logging.debug("The following is the deviations from "
                      "the actual(/proc/meminfo) and expected"
                      " value(output of virsh nodememstats)")

        for i in range(itr):
            logging.debug("iteration %d:", i)
            for index, name in enumerate(name_stats):
                logging.debug("%19s : %d", name, deltas[i][name])
Esempio n. 6
0
def run(test, params, env):
    """
    Check KSM can be started automaticly when ksmtuned threshold is reached

    1. Get the memory of your host and the KSM_THRES_COEF
    2. Boot a guest with memory less than KSM_THRES_COEF threshold
    3. Get the memory used in host of process qemu-kvm
    4. Get the free memory in host
    5. If both the free memory size is not smaller than the threshold and guest
        used memory + threshold is not bigger than total memory in host. Check
        the ksm status in host. Ksm should not start in the host
    6. Repeat step 2~5 under it broke the rule in step 5

    :param test: kvm test object.
    :param params: Dictionary with test parameters.
    :param env: Dictionary with the test environment.
    """
    def check_ksm(mem, stress=False):
        """
        :param mem: Boot guest with given memory, in KB
        :param stress: Load stress or not
        """
        params['mem'] = mem // 1024
        params['start_vm'] = 'yes'
        vm_name = params['main_vm']
        env_process.preprocess_vm(test, params, env, vm_name)
        vm = env.get_vm(vm_name)
        vm.wait_for_login()
        if stress:
            params['stress_args'] = ('--cpu 4 --io 4 --vm 2 --vm-bytes %sM' %
                                     (int(params['mem']) // 2))
            stress_test = VMStress(vm, "stress", params)
            stress_test.load_stress_tool()
            time.sleep(30)
        qemu_pid = vm.get_pid()
        qemu_used_page = utils_misc.normalize_data_size(process.getoutput(
            params['cmd_get_qemu_used_mem'] % qemu_pid, shell=True) + 'K', 'B')
        pagesize = utils_memory.getpagesize()
        qemu_used_mem = int(float(qemu_used_page)) * pagesize
        free_mem_host = utils_memory.freememtotal()
        ksm_status = process.getoutput(params['cmd_check_ksm_status'])
        vm.destroy()
        logging.info('The ksm threshold is %s, the memory allocated by qemu is'
                     ' %s, and the total free memory on host is %s.' %
                     (ksm_thres, qemu_used_mem, free_mem_host))
        if free_mem_host >= ksm_thres:
            if ksm_status != '0':
                test.fail('Ksm should not start.')
            if stress:
                test.error('The host resource is not consumed as expected.')
        elif ksm_status == '0':
            test.fail('Ksm should start but it does not.')

    total_mem_host = utils_memory.memtotal()
    utils_memory.drop_caches()
    free_mem_host = utils_memory.freememtotal()
    ksm_thres = process.getoutput(params['cmd_get_thres'], shell=True)
    ksm_thres = int(total_mem_host *
                    (int(re.findall('\\d+', ksm_thres)[0]) / 100))
    guest_mem = (free_mem_host - ksm_thres) // 2
    if arch.ARCH in ('ppc64', 'ppc64le'):
        guest_mem = guest_mem - guest_mem % (256 * 1024)
    status_ksm_service = process.system(
        params['cmd_status_ksmtuned'], ignore_status=True)
    if status_ksm_service != 0:
        process.run(params['cmd_start_ksmtuned'])
    check_ksm(guest_mem)

    ksm_config_file = params['ksm_config_file']
    backup_file = ksm_config_file + '.backup'
    copyfile(ksm_config_file, backup_file)
    threshold = params.get_numeric('ksm_threshold')
    with open(ksm_config_file, "a+") as f:
        f.write('%s=%s' % (params['ksm_thres_conf'], threshold))
    process.run(params['cmd_restart_ksmtuned'])
    ksm_thres = total_mem_host * (threshold / 100)
    guest_mem = total_mem_host - ksm_thres // 2
    if arch.ARCH in ('ppc64', 'ppc64le'):
        guest_mem = guest_mem - guest_mem % (256 * 1024)
    try:
        check_ksm(guest_mem, stress=True)
    finally:
        copyfile(backup_file, ksm_config_file)
        os.remove(backup_file)
        if status_ksm_service != 0:
            process.run(params['cmd_stop_ksmtuned'])
        else:
            process.run(params['cmd_restart_ksmtuned'])
Esempio n. 7
0
def run(test, params, env):
    """
    Qemu numa stress test:
    1) Boot up a guest and find the node it used
    2) Try to allocate memory in that node
    3) Run memory heavy stress inside guest
    4) Check the memory use status of qemu process
    5) Repeat step 2 ~ 4 several times


    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    host_numa_node = utils_misc.NumaInfo()
    if len(host_numa_node.online_nodes) < 2:
        test.cancel("Host only has one NUMA node, skipping test...")

    timeout = float(params.get("login_timeout", 240))
    test_count = int(params.get("test_count", 4))
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=timeout)

    qemu_pid = vm.get_pid()

    if test_count < len(host_numa_node.online_nodes):
        test_count = len(host_numa_node.online_nodes)

    tmpfs_size = params.get_numeric("tmpfs_size")
    for node in host_numa_node.nodes:
        node_mem = int(host_numa_node.read_from_node_meminfo(node, "MemTotal"))
        if tmpfs_size == 0:
            tmpfs_size = node_mem
    tmpfs_path = params.get("tmpfs_path", "tmpfs_numa_test")
    tmpfs_path = utils_misc.get_path(data_dir.get_tmp_dir(), tmpfs_path)
    tmpfs_write_speed = get_tmpfs_write_speed()
    dd_timeout = tmpfs_size / tmpfs_write_speed * 1.5
    mount_fs_size = "size=%dK" % tmpfs_size
    memory_file = utils_misc.get_path(tmpfs_path, "test")
    dd_cmd = "dd if=/dev/urandom of=%s bs=1k count=%s" % (memory_file,
                                                          tmpfs_size)
    utils_memory.drop_caches()

    if utils_memory.freememtotal() < tmpfs_size:
        test.cancel("Host does not have enough free memory to run the test, "
                    "skipping test...")

    if not os.path.isdir(tmpfs_path):
        os.mkdir(tmpfs_path)

    test_mem = float(params.get("mem")) * float(params.get("mem_ratio", 0.8))
    stress_args = "--cpu 4 --io 4 --vm 2 --vm-bytes %sM" % int(test_mem / 2)
    most_used_node, memory_used = max_mem_map_node(host_numa_node, qemu_pid)

    for test_round in range(test_count):
        if os.path.exists(memory_file):
            os.remove(memory_file)
        utils_memory.drop_caches()
        if utils_memory.freememtotal() < tmpfs_size:
            test.error("Don't have enough memory to execute this "
                       "test after %s round" % test_round)
        error_context.context("Executing stress test round: %s" % test_round,
                              logging.info)
        numa_node_malloc = most_used_node
        numa_dd_cmd = "numactl -m %s %s" % (numa_node_malloc, dd_cmd)
        error_context.context(
            "Try to allocate memory in node %s" % numa_node_malloc,
            logging.info)
        try:
            utils_misc.mount("none", tmpfs_path, "tmpfs", perm=mount_fs_size)
            funcatexit.register(env, params.get("type"), utils_misc.umount,
                                "none", tmpfs_path, "tmpfs")
            process.system(numa_dd_cmd, timeout=dd_timeout, shell=True)
        except Exception as error_msg:
            if "No space" in str(error_msg):
                pass
            else:
                test.fail("Can not allocate memory in node %s."
                          " Error message:%s" %
                          (numa_node_malloc, str(error_msg)))
        error_context.context("Run memory heavy stress in guest", logging.info)
        stress_test = utils_test.VMStress(vm,
                                          "stress",
                                          params,
                                          stress_args=stress_args)
        stress_test.load_stress_tool()
        error_context.context("Get the qemu process memory use status",
                              logging.info)
        node_after, memory_after = max_mem_map_node(host_numa_node, qemu_pid)
        if node_after == most_used_node and memory_after >= memory_used:
            test.fail("Memory still stick in node %s" % numa_node_malloc)
        else:
            most_used_node = node_after
            memory_used = memory_after
        stress_test.unload_stress()
        stress_test.clean()
        utils_misc.umount("none", tmpfs_path, "tmpfs")
        funcatexit.unregister(env, params.get("type"), utils_misc.umount,
                              "none", tmpfs_path, "tmpfs")
        session.cmd("sync; echo 3 > /proc/sys/vm/drop_caches")
        utils_memory.drop_caches()

    session.close()
Esempio n. 8
0
def run(test, params, env):
    """
    Test the command virsh nodememstats

    (1) Call the virsh nodememstats command
    (2) Get the output
    (3) Check the against /proc/meminfo output
    (4) Call the virsh nodememstats command with an unexpected option
    (5) Call the virsh nodememstats command with libvirtd service stop
    """

    # Initialize the variables
    expected = {}
    actual = {}
    deltas = []
    name_stats = ['total', 'free', 'buffers', 'cached']
    itr = int(params.get("itr"))

    def virsh_check_nodememtats(actual_stats, expected_stats, delta):
        """
        Check the nodememstats output value with /proc/meminfo value
        """

        delta_stats = {}
        for name in name_stats:
            delta_stats[name] = abs(actual_stats[name] - expected_stats[name])
            if 'total' in name:
                if not delta_stats[name] == 0:
                    test.fail("Command 'virsh nodememstats' not"
                              " succeeded as the value for %s is "
                              "deviated by %d\nThe total memory "
                              "value is deviating-check" %
                              (name, delta_stats[name]))
            else:
                if delta_stats[name] > delta:
                    test.fail("Command 'virsh nodememstats' not "
                              "succeeded as the value for %s"
                              " is deviated by %d" % (name, delta_stats[name]))
        return delta_stats

    # Prepare libvirtd service
    check_libvirtd = "libvirtd" in params
    if check_libvirtd:
        libvirtd = params.get("libvirtd")
        if libvirtd == "off":
            utils_libvirtd.libvirtd_stop()

    # Get the option for the test case
    option = params.get("virsh_nodememstats_options")
    if option == "max":
        cell_dict = utils_test.libvirt.get_all_cells()
        option = len(list(cell_dict.keys()))

    # Run test case for 10 iterations
    # (default can be changed in subtests.cfg file)
    # and print the final statistics
    for i in range(itr):
        output = virsh.nodememstats(option)

        # Get the status of the virsh command executed
        status = output.exit_status

        # Get status_error option for the test case
        status_error = params.get("status_error")
        if status_error == "yes":
            if status == 0:
                if libvirtd == "off":
                    utils_libvirtd.libvirtd_start()
                    test.fail("Command 'virsh nodememstats' "
                              "succeeded with libvirtd service"
                              " stopped, incorrect")
                else:
                    test.fail("Command 'virsh nodememstats %s' "
                              "succeeded (incorrect command)" % option)

        elif status_error == "no":
            if status == 0:
                if option:
                    return
                # From the beginning of a line, group 1 is one or
                # more word-characters, followed by zero or more
                # whitespace characters and a ':', then one or
                # more whitespace characters, followed by group 2,
                # which is one or more digit characters,
                # then one or more whitespace characters followed by
                # a literal 'kB' or 'KiB' sequence, e.g as below
                # total  :              3809340 kB
                # total  :              3809340 KiB
                # Normalise the value to MBs
                regex_obj = re.compile(r"^(\w+)\s*:\s+(\d+)\s\w+")
                expected = {}

                for line in output.stdout.split('\n'):
                    match_obj = regex_obj.search(line)
                    # Due to the extra space in the list
                    if match_obj is not None:
                        name = match_obj.group(1)
                        value = match_obj.group(2)
                        expected[name] = int(value) // 1024

                # Get the actual value from /proc/meminfo and normalise to MBs
                actual['total'] = int(utils_memory.memtotal()) // 1024
                actual['free'] = int(utils_memory.freememtotal()) // 1024
                actual['buffers'] = int(
                    utils_memory.read_from_meminfo('Buffers')) // 1024
                actual['cached'] = int(
                    utils_memory.read_from_meminfo('Cached')) // 1024

                # Currently the delta value is kept at 200 MB this can be
                # tuned based on the accuracy
                # Check subtests.cfg for more details
                delta = int(params.get("delta"))
                output = virsh_check_nodememtats(actual, expected, delta)
                deltas.append(output)

            else:
                test.fail("Command virsh nodememstats %s not "
                          "succeeded:\n%s" % (option, status))

    # Recover libvirtd service start
    if libvirtd == "off":
        utils_libvirtd.libvirtd_start()

    # Print the deviated values for all iterations
    if status_error == "no":
        logging.debug("The following is the deviations from "
                      "the actual(/proc/meminfo) and expected"
                      " value(output of virsh nodememstats)")

        for i in range(itr):
            logging.debug("iteration %d:", i)
            for index, name in enumerate(name_stats):
                logging.debug("%19s : %d", name, deltas[i][name])
Esempio n. 9
0
    def check_ksm(mem, threshold_reached=False):
        """
        :param mem: Boot guest with given memory, in KB
        :ksmtuned_enabled: ksmtuned threshold is reached or not
        """
        def heavyload_install():
            if session.cmd_status(test_install_cmd) != 0:
                logging.warning("Could not find installed heavyload in guest, "
                                "will install it via winutils.iso ")
                winutil_drive = utils_misc.get_winutils_vol(session)
                if not winutil_drive:
                    test.cancel("WIN_UTILS CDROM not found.")
                install_cmd = params["install_cmd"] % winutil_drive
                session.cmd(install_cmd)

        def check_qemu_used_mem(qemu_pid, mem):
            qemu_used_page = process.getoutput(get_qemu_used_mem % qemu_pid,
                                               shell=True)
            qemu_used_mem = float(qemu_used_page) * pagesize
            if qemu_used_mem < mem * mem_thres:
                return False
            return True

        params['mem'] = mem // 1024
        params['start_vm'] = 'yes'
        vm_name = params['main_vm']
        env_process.preprocess_vm(test, params, env, vm_name)
        vm = env.get_vm(vm_name)
        session = vm.wait_for_login()
        qemu_pid = vm.get_pid()
        if params["os_type"] == "linux":
            params['stress_args'] = ('--cpu 4 --io 4 --vm 2 --vm-bytes %sM' %
                                     (int(params['mem']) // 2))
            stress_test = VMStress(vm, "stress", params)
            stress_test.load_stress_tool()
        else:
            install_path = params["install_path"]
            test_install_cmd = 'dir "%s" | findstr /I heavyload' % install_path
            heavyload_install()
            heavyload_bin = r'"%s\heavyload.exe" ' % install_path
            heavyload_options = ["/MEMORY 100", "/START"]
            start_cmd = heavyload_bin + " ".join(heavyload_options)
            stress_tool = BackgroundTest(
                session.cmd, (start_cmd, stress_timeout, stress_timeout))
            stress_tool.start()
            if not utils_misc.wait_for(stress_tool.is_alive, stress_timeout):
                test.error("Failed to start heavyload process")
        if not utils_misc.wait_for(lambda: check_qemu_used_mem(qemu_pid, mem),
                                   stress_timeout, 10, 10):
            test.error("QEMU used memory doesn't reach %s of guest mem %sM in "
                       "%ss" % (mem_thres, mem // 1024, stress_timeout))
        time.sleep(30)
        free_mem_host = utils_memory.freememtotal()
        ksm_status = process.getoutput(params['cmd_check_ksm_status'])
        vm.destroy()
        logging.info(
            "The ksm threshold is %sM, QEMU used memory is %sM, "
            "and the total free memory on host is %sM", ksm_thres // 1024,
            mem // 1024, free_mem_host // 1024)
        if threshold_reached:
            if free_mem_host > ksm_thres:
                test.error("Host memory is not consumed as much as expected")
            if ksm_status == '0':
                test.fail("KSM should be running")
        else:
            if free_mem_host < ksm_thres:
                test.error("Host memory is consumed too much more than "
                           "expected")
            if ksm_status != '0':
                test.fail("KSM should not be running")
Esempio n. 10
0
def run(test, params, env):
    """
    Check KSM can be started automaticly when ksmtuned threshold is reached

    1. Get the memory of your host and the KSM_THRES_COEF
    2. Boot a guest with memory less than KSM_THRES_COEF threshold
    3. Get the memory used in host of process qemu-kvm
    4. Get the free memory in host
    5. If both the free memory size is not smaller than the threshold and guest
        used memory + threshold is not bigger than total memory in host. Check
        the ksm status in host. Ksm should not start in the host
    6. Repeat step 2~5 under it broke the rule in step 5

    :param test: kvm test object.
    :param params: Dictionary with test parameters.
    :param env: Dictionary with the test environment.
    """
    def check_ksm(mem, threshold_reached=False):
        """
        :param mem: Boot guest with given memory, in KB
        :ksmtuned_enabled: ksmtuned threshold is reached or not
        """
        def heavyload_install():
            if session.cmd_status(test_install_cmd) != 0:
                logging.warning("Could not find installed heavyload in guest, "
                                "will install it via winutils.iso ")
                winutil_drive = utils_misc.get_winutils_vol(session)
                if not winutil_drive:
                    test.cancel("WIN_UTILS CDROM not found.")
                install_cmd = params["install_cmd"] % winutil_drive
                session.cmd(install_cmd)

        def check_qemu_used_mem(qemu_pid, mem):
            qemu_used_page = process.getoutput(get_qemu_used_mem % qemu_pid,
                                               shell=True)
            qemu_used_mem = float(qemu_used_page) * pagesize
            if qemu_used_mem < mem * mem_thres:
                return False
            return True

        params['mem'] = mem // 1024
        params['start_vm'] = 'yes'
        vm_name = params['main_vm']
        env_process.preprocess_vm(test, params, env, vm_name)
        vm = env.get_vm(vm_name)
        session = vm.wait_for_login()
        qemu_pid = vm.get_pid()
        if params["os_type"] == "linux":
            params['stress_args'] = ('--cpu 4 --io 4 --vm 2 --vm-bytes %sM' %
                                     (int(params['mem']) // 2))
            stress_test = VMStress(vm, "stress", params)
            stress_test.load_stress_tool()
        else:
            install_path = params["install_path"]
            test_install_cmd = 'dir "%s" | findstr /I heavyload' % install_path
            heavyload_install()
            heavyload_bin = r'"%s\heavyload.exe" ' % install_path
            heavyload_options = ["/MEMORY 100", "/START"]
            start_cmd = heavyload_bin + " ".join(heavyload_options)
            stress_tool = BackgroundTest(
                session.cmd, (start_cmd, stress_timeout, stress_timeout))
            stress_tool.start()
            if not utils_misc.wait_for(stress_tool.is_alive, stress_timeout):
                test.error("Failed to start heavyload process")
        if not utils_misc.wait_for(lambda: check_qemu_used_mem(qemu_pid, mem),
                                   stress_timeout, 10, 10):
            test.error("QEMU used memory doesn't reach %s of guest mem %sM in "
                       "%ss" % (mem_thres, mem // 1024, stress_timeout))
        time.sleep(30)
        free_mem_host = utils_memory.freememtotal()
        ksm_status = process.getoutput(params['cmd_check_ksm_status'])
        vm.destroy()
        logging.info(
            "The ksm threshold is %sM, QEMU used memory is %sM, "
            "and the total free memory on host is %sM", ksm_thres // 1024,
            mem // 1024, free_mem_host // 1024)
        if threshold_reached:
            if free_mem_host > ksm_thres:
                test.error("Host memory is not consumed as much as expected")
            if ksm_status == '0':
                test.fail("KSM should be running")
        else:
            if free_mem_host < ksm_thres:
                test.error("Host memory is consumed too much more than "
                           "expected")
            if ksm_status != '0':
                test.fail("KSM should not be running")

    total_mem_host = utils_memory.memtotal()
    utils_memory.drop_caches()
    free_mem_host = utils_memory.freememtotal()
    ksm_thres = process.getoutput(params['cmd_get_thres'], shell=True)
    ksm_thres = int(total_mem_host *
                    (int(re.findall('\\d+', ksm_thres)[0]) / 100))
    guest_mem = (free_mem_host - ksm_thres) // 2
    if arch.ARCH in ('ppc64', 'ppc64le'):
        guest_mem = guest_mem - guest_mem % (256 * 1024)
    status_ksm_service = process.system(params['cmd_status_ksmtuned'],
                                        ignore_status=True)
    if status_ksm_service != 0:
        process.run(params['cmd_start_ksmtuned'])
    stress_timeout = params.get("stress_timeout", 1800)
    mem_thres = float(params.get("mem_thres", 0.95))
    get_qemu_used_mem = params['cmd_get_qemu_used_mem']
    pagesize = utils_memory.getpagesize()
    check_ksm(guest_mem)

    ksm_config_file = params['ksm_config_file']
    backup_file = ksm_config_file + '.backup'
    copyfile(ksm_config_file, backup_file)
    threshold = params.get_numeric('ksm_threshold')
    with open(ksm_config_file, "a+") as f:
        f.write('%s=%s' % (params['ksm_thres_conf'], threshold))
    process.run(params['cmd_restart_ksmtuned'])
    ksm_thres = total_mem_host * (threshold / 100)
    guest_mem = total_mem_host - ksm_thres // 2
    if arch.ARCH in ('ppc64', 'ppc64le'):
        guest_mem = guest_mem - guest_mem % (256 * 1024)
    try:
        check_ksm(guest_mem, threshold_reached=True)
    finally:
        copyfile(backup_file, ksm_config_file)
        os.remove(backup_file)
        if status_ksm_service != 0:
            process.run(params['cmd_stop_ksmtuned'])
        else:
            process.run(params['cmd_restart_ksmtuned'])