cpu_hotplug.py 4.5 KB
Newer Older
1 2
import os, logging, re
from autotest.client.shared import error
3
from virttest import utils_test
4 5 6 7 8 9 10 11 12 13 14 15 16 17


@error.context_aware
def run_cpu_hotplug(test, params, env):
    """
    Runs CPU hotplug test:

    1) Pick up a living guest
    2) Send the monitor command cpu_set [cpu id] for each cpu we wish to have
    3) Verify if guest has the additional CPUs showing up under
        /sys/devices/system/cpu
    4) Try to bring them online by writing 1 to the 'online' file inside that dir
    5) Run the CPU Hotplug test suite shipped with autotest inside guest

18
    @param test: QEMU test object.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
    @param params: Dictionary with test parameters.
    @param env: Dictionary with the test environment.
    """
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = int(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=timeout)

    n_cpus_add = int(params.get("n_cpus_add", 1))
    current_cpus = int(params.get("smp", 1))
    onoff_iterations = int(params.get("onoff_iterations", 20))
    total_cpus = current_cpus + n_cpus_add

    error.context("cleaning guest dmesg before addition")
    session.cmd("dmesg -c")

    error.context("Adding %d CPUs to guest" % n_cpus_add)
    for i in range(total_cpus):
        vm.monitor.cmd("cpu_set %s online" % i)

    output = vm.monitor.cmd("info cpus")
    logging.debug("Output of info cpus:\n%s", output)

    cpu_regexp = re.compile("CPU #(\d+)")
    total_cpus_monitor = len(cpu_regexp.findall(output))
    if total_cpus_monitor != total_cpus:
        raise error.TestFail("Monitor reports %s CPUs, when VM should have %s" %
                             (total_cpus_monitor, total_cpus))

    dmesg_after = session.cmd("dmesg")
    logging.debug("Guest dmesg output after CPU add:\n%s" % dmesg_after)

    # Verify whether the new cpus are showing up on /sys
    error.context("verifying if new CPUs are showing on guest's /sys dir")
    n_cmd = 'find /sys/devices/system/cpu/cpu[0-99] -maxdepth 0 -type d | wc -l'
    output = session.cmd(n_cmd)
    logging.debug("List of cpus on /sys:\n%s" % output)
    try:
        cpus_after_addition = int(output)
    except ValueError:
        logging.error("Output of '%s': %s", n_cmd, output)
        raise error.TestFail("Unable to get CPU count after CPU addition")

    if cpus_after_addition != total_cpus:
        raise error.TestFail("%s CPUs are showing up under "
                             "/sys/devices/system/cpu, was expecting %s" %
                             (cpus_after_addition, total_cpus))

    error.context("locating online files for guest's new CPUs")
    r_cmd = 'find /sys/devices/system/cpu/cpu[1-99]/online -maxdepth 0 -type f'
    online_files = session.cmd(r_cmd)
    logging.debug("CPU online files detected: %s", online_files)
    online_files = online_files.split().sort()

    if not online_files:
        raise error.TestFail("Could not find CPUs that can be "
                             "enabled/disabled on guest")

    for online_file in online_files:
        cpu_regexp = re.compile("cpu(\d+)", re.IGNORECASE)
        cpu_id = cpu_regexp.findall(online_file)[0]
        error.context("changing online status for CPU %s" % cpu_id)
        check_online_status = session.cmd("cat %s" % online_file)
        try:
            check_online_status = int(check_online_status)
        except ValueError:
            raise error.TestFail("Unable to get online status from CPU %s" %
                                 cpu_id)
        assert(check_online_status in [0, 1])
        if check_online_status == 0:
            error.context("Bringing CPU %s online" % cpu_id)
            session.cmd("echo 1 > %s" % online_file)

    # Now that all CPUs were onlined, let's execute the
    # autotest CPU Hotplug test
    control_path = os.path.join(test.virtdir, "autotest_control",
                                "cpu_hotplug.control")

    timeout = int(params.get("cpu_hotplug_timeout"), 300)
    error.context("running cpu_hotplug autotest after cpu addition")
    utils_test.run_autotest(vm, session, control_path, timeout,
                                 test.outputdir, params)

    # Last, but not least, let's offline/online the CPUs in the guest
    # several times
    irq = 15
    irq_mask = "f0"
    for i in xrange(onoff_iterations):
        session.cmd("echo %s > /proc/irq/%s/smp_affinity" % (irq_mask, irq))
        for online_file in online_files:
            session.cmd("echo 0 > %s" % online_file)
        for online_file in online_files:
            session.cmd("echo 1 > %s" % online_file)