numa_consistency.py 4.8 KB
Newer Older
1
import logging
2
import resource
3

X
Xu Han 已提交
4
from avocado.utils import process
5

6
from virttest import cpu
7
from virttest import env_process
X
Xu Han 已提交
8
from virttest import error_context
9 10 11
from virttest import utils_misc
from virttest import utils_test
from virttest.staging import utils_memory
12

L
Lucas Meneghel Rodrigues 已提交
13

X
Xu Han 已提交
14
@error_context.context_aware
15
def run(test, params, env):
16 17 18 19 20 21 22 23 24 25 26
    """
    Qemu numa consistency test:
    1) Get host numa topological structure
    2) Start a guest with the same node as the host, each node has one cpu
    3) Get the vcpu thread used cpu id in host and the cpu belongs which node
    4) Allocate memory inside guest and bind the allocate process to one of
       its vcpu.
    5) The memory used in host should increase in the same node if the vcpu
       thread is not switch to other node.
    6) Repeat step 3~5 for each vcpu thread of the guest.

L
Lucas Meneghel Rodrigues 已提交
27 28 29
    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
30 31
    """
    def get_vcpu_used_node(numa_node_info, vcpu_thread):
32
        cpu_used_host = cpu.get_thread_cpu(vcpu_thread)[0]
33 34 35 36
        node_used_host = ([_ for _ in node_list if cpu_used_host
                           in numa_node_info.nodes[_].cpus][0])
        return node_used_host

X
Xu Han 已提交
37
    error_context.context("Get host numa topological structure", logging.info)
38 39 40 41
    timeout = float(params.get("login_timeout", 240))
    host_numa_node = utils_misc.NumaInfo()
    node_list = host_numa_node.online_nodes
    if len(node_list) < 2:
X
Xu Han 已提交
42
        test.cancel("This host only has one NUMA node, skipping test...")
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
    node_list.sort()
    params['smp'] = len(node_list)
    params['vcpu_cores'] = 1
    params['vcpu_threads'] = 1
    params['vcpu_sockets'] = params['smp']
    params['guest_numa_nodes'] = ""
    for node_id in range(len(node_list)):
        params['guest_numa_nodes'] += " node%d" % node_id
    params['start_vm'] = 'yes'

    utils_memory.drop_caches()
    vm = params['main_vm']
    env_process.preprocess_vm(test, params, env, vm)
    vm = env.get_vm(vm)
    vm.verify_alive()
    vcpu_threads = vm.vcpu_threads
    session = vm.wait_for_login(timeout=timeout)
60
    threshold = params.get_numeric("threshold", target_type=float)
61 62 63 64 65 66 67 68 69 70 71 72

    dd_size = 256
    if dd_size * len(vcpu_threads) > int(params['mem']):
        dd_size = int(int(params['mem']) / 2 / len(vcpu_threads))

    mount_size = dd_size * len(vcpu_threads)

    mount_cmd = "mount -o size=%dM -t tmpfs none /tmp" % mount_size

    qemu_pid = vm.get_pid()
    drop = 0
    for cpuid in range(len(vcpu_threads)):
X
Xu Han 已提交
73 74
        error_context.context("Get vcpu %s used numa node." % cpuid,
                              logging.info)
75
        memory_status, _ = utils_test.qemu.get_numa_status(host_numa_node,
76 77 78
                                                           qemu_pid)
        node_used_host = get_vcpu_used_node(host_numa_node,
                                            vcpu_threads[cpuid])
79 80
        node_used_host_index = node_list.index(node_used_host)
        memory_used_before = memory_status[node_used_host_index]
X
Xu Han 已提交
81
        error_context.context("Allocate memory in guest", logging.info)
82 83 84 85 86
        session.cmd(mount_cmd)
        binded_dd_cmd = "taskset %s" % str(2 ** int(cpuid))
        binded_dd_cmd += " dd if=/dev/urandom of=/tmp/%s" % cpuid
        binded_dd_cmd += " bs=1M count=%s" % dd_size
        session.cmd(binded_dd_cmd)
X
Xu Han 已提交
87 88
        error_context.context("Check qemu process memory use status",
                              logging.info)
89 90 91 92 93 94
        node_after = get_vcpu_used_node(host_numa_node, vcpu_threads[cpuid])
        if node_after != node_used_host:
            logging.warn("Node used by vcpu thread changed. So drop the"
                         " results in this round.")
            drop += 1
            continue
95
        memory_status, _ = utils_test.qemu.get_numa_status(host_numa_node,
96
                                                           qemu_pid)
97
        memory_used_after = memory_status[node_used_host_index]
98 99 100
        page_size = resource.getpagesize() / 1024
        memory_allocated = (memory_used_after -
                            memory_used_before) * page_size / 1024
101
        if 1 - float(memory_allocated) / float(dd_size) > threshold:
102 103
            numa_hardware_cmd = params.get("numa_hardware_cmd")
            if numa_hardware_cmd:
X
Xu Han 已提交
104
                numa_info = process.system_output(numa_hardware_cmd,
X
Xu Han 已提交
105 106
                                                  ignore_status=True,
                                                  shell=True)
107 108 109 110
            msg = "Expect malloc %sM memory in node %s," % (dd_size,
                                                            node_used_host)
            msg += "but only malloc %sM \n" % memory_allocated
            msg += "Please check more details of the numa node: %s" % numa_info
X
Xu Han 已提交
111
            test.fail(msg)
112 113 114
    session.close()

    if drop == len(vcpu_threads):
X
Xu Han 已提交
115
        test.error("All test rounds are dropped. Please test it again.")