Example #1
0
def prepare_vm(guest_xml, params):
    """
    Configure guest xml before the test.

    :param guest_xml: the guest xml
    :param params: the dict the cases use
    """
    logging.debug("Begin to prepare vm xml")
    iothread_id = params.get("iothread_id")
    vm_name = params.get("main_vm")
    vcpu_attrs = eval(params.get('vcpu_attrs', '{}'))
    if vcpu_attrs:
        guest_xml.setup_attrs(**vcpu_attrs)

    if guest_xml.xmltreefile.find('cputune'):
        guest_xml.del_cputune()

    cputune = vm_xml.VMCPUTuneXML()
    cputune_attrs = params.get('cputune_attrs')
    if cputune_attrs and cputune_attrs.count("%s"):
        cputune_attrs = cputune_attrs % params.get('cpulist', '0')
    if cputune_attrs:
        cputune_attrs = eval(cputune_attrs)
        cputune.setup_attrs(**cputune_attrs)
        guest_xml.cputune = cputune

    guest_xml.sync()
    if iothread_id:
        virsh.iothreadadd(vm_name, iothread_id, '--config',
                          ignore_status=False, debug=True)
Example #2
0
    def update_iothread_xml(define_error=False):
        """
        Update xml for test
        """
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
        del vmxml.cputune
        del vmxml.iothreadids
        del vmxml.iothreads

        vm_is_active = vm.is_alive()

        # Set iothreads first
        if iothread_ids:
            ids_xml = vm_xml.VMIothreadidsXML()
            ids_xml.iothread = iothread_ids.split()
            vmxml.iothreadids = ids_xml
        # Set cputune
        if any([iothreadpins, iothreadscheds, iothread_quota,
                iothread_period]):
            cputune_xml = vm_xml.VMCPUTuneXML()
            if iothreadpins:
                io_pins = []
                for pins in iothreadpins.split():
                    thread, cpuset = pins.split(':')
                    io_pins.append({"iothread": thread, "cpuset": cpuset})
                cputune_xml.iothreadpins = io_pins
            if iothreadscheds:
                io_scheds = []
                for sched in iothreadscheds.split():
                    thread, scheduler = sched.split(":")
                    io_scheds.append({
                        "iothreads": thread,
                        "scheduler": scheduler
                    })
                cputune_xml.iothreadscheds = io_scheds
            if iothread_period:
                cputune_xml.iothread_period = int(iothread_period)
            if iothread_quota:
                cputune_xml.iothread_quota = int(iothread_quota)

            vmxml.cputune = cputune_xml

        # Set iothread
        if iothread_num:
            vmxml.iothreads = int(iothread_num)

        logging.debug("Pre-test xml is %s", vmxml)
        if not define_error:
            vmxml.sync()
            if vm_is_active:
                vm.start()
                vm.wait_for_login().close()
        else:
            result = virsh.define(vmxml.xml, debug=True)
            libvirt.check_exit_status(result, True)
            if err_msg:
                libvirt.check_result(result, err_msg)
Example #3
0
 def offline_pin_and_check(vm, vcpu, cpu_list):
     """
     Edit domain xml to pin vcpu and check the result.
     """
     cputune = vm_xml.VMCPUTuneXML()
     cputune.vcpupins = [{'vcpu': str(vcpu), 'cpuset': cpu_list}]
     vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name)
     vmxml.cputune = cputune
     vmxml.sync()
     utils_misc.wait_for(lambda: vm.state() == "shut off", 10)
     cmdResult = virsh.start(vm.name, debug=True)
     libvirt.check_exit_status(cmdResult, status_error)
     pid = vm.get_pid()
     vcpu_pid = vm.get_vcpus_pid()[vcpu]
     check_vcpupin(vm.name, vcpu, cpu_list, pid, vcpu_pid)
Example #4
0
def add_emulatorpin_xml(params, cpulist, test):
    """
    Add emulatorpin configuration to the guest xml

    :param params: the parameter dictionary
    :param cpulist: host cpu list to be set for emulatorpin
    :param test: the test object
    :return: None
    """
    vm_name = params.get("main_vm")
    guest_xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
    try:
        cputune = guest_xml.cputune
    except xcepts.LibvirtXMLNotFoundError:
        cputune = vm_xml.VMCPUTuneXML()

    cputune.emulatorpin = int(cpulist)
    guest_xml.cputune = cputune
    guest_xml.sync()
    logging.debug("After adding emulatorpin, "
                  "vm xml is:%s\n", vm_xml.VMXML.new_from_dumpxml(vm_name))
Example #5
0
def run(test, params, env):
    """
    Test command: virsh iothread.

    The command can change the number of iothread.
    1.Prepare test environment,destroy or suspend a VM.
    2.Perform virsh iothreadadd operation.
    3.Recover test environment.
    4.Confirm the test result.
    """

    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    pre_vm_state = params.get("iothread_pre_vm_state")
    command = params.get("iothread_command", "iothread")
    options = params.get("iothread_options")
    vm_ref = params.get("iothread_vm_ref", "name")
    iothreads = params.get("iothreads", 4)
    iothread_id = params.get("iothread_id", "6")
    cpuset = params.get("cpuset", "1")
    status_error = "yes" == params.get("status_error")
    iothreadids = params.get("iothreadids")
    iothreadpins = params.get("iothreadpins")
    try:
        iothreads = int(iothreads)
    except ValueError:
        # 'iothreads' may not invalid number in negative tests
        logging.debug("Can't convert %s to integer type", iothreads)

    # Save original configuration
    vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    orig_config_xml = vmxml.copy()

    try:
        if vm.is_alive():
            vm.destroy()

        option_list = options.split(" ")
        for item in option_list:
            if virsh.has_command_help_match(command, item) is None:
                raise exceptions.TestSkipError("The current libvirt version"
                                               " doesn't support '%s' option" %
                                               item)
        # Set iothreads first
        if iothreadids:
            ids_xml = vm_xml.VMIothreadidsXML()
            ids_xml.iothread = iothreadids.split()
            vmxml.iothreadids = ids_xml
        if iothreadpins:
            cputune_xml = vm_xml.VMCPUTuneXML()
            io_pins = []
            for pins in iothreadpins.split():
                thread, cpu = pins.split(':')
                io_pins.append({"iothread": thread, "cpuset": cpu})
            cputune_xml.iothreadpins = io_pins
            vmxml.cputune = cputune_xml
        vmxml.iothreads = iothreads
        logging.debug("Pre-test xml is %s", vmxml)
        vmxml.sync()

        # Restart, unless that's not our test
        if not vm.is_alive():
            vm.start()
        vm.wait_for_login()

        domid = vm.get_id()  # only valid for running
        domuuid = vm.get_uuid()

        if pre_vm_state == "shut off" and vm.is_alive():
            vm.destroy()

        # Run test
        if vm_ref == "name":
            dom_option = vm_name
        elif vm_ref == "id":
            dom_option = domid
        elif vm_ref == "uuid":
            dom_option = domuuid
        else:
            dom_option = vm_ref

        virsh_dargs = {"debug": True, "ignore_status": True}
        if "yes" == params.get("readonly", "no"):
            virsh_dargs.update({"readonly": True})
        ret = virsh.iothreadpin(dom_option, iothread_id, cpuset, options,
                                **virsh_dargs)
        libvirt.check_exit_status(ret, status_error)

        if not status_error:
            # Check domainxml
            iothread_info = get_xmlinfo(vm_name, options)
            logging.debug("iothreadinfo: %s", iothread_info)
            for info in iothread_info:
                if info["iothread"] == iothread_id and info["cpuset"] == cpuset:
                    # Find the iothreadpins in domain xml
                    break
                elif iothread_info.index(info) == (len(iothread_info) - 1):
                    # Can not find the iothreadpins at last
                    raise exceptions.TestFail(
                        "Failed to add iothread %s in domain xml", iothread_id)

            # Check iothreadinfo by virsh command
            iothread_info = libvirt.get_iothreadsinfo(dom_option, options)
            logging.debug("iothreadinfo: %s", iothread_info)
            if (iothread_id not in iothread_info
                    or iothread_info[iothread_id] != cpuset):
                raise exceptions.TestFail("Failed to add iothreadpins %s",
                                          iothread_id)

    finally:
        # Cleanup
        if vm.is_alive():
            vm.destroy()
        orig_config_xml.sync()
Example #6
0
def run(test, params, env):
    """
    Test:<memorytune>
    1. Check virsh capabilities report right MBA info
    2  Mount resctrl
    3. Check host MBA info from virsh capabilities output
    4. Add memory bandwidth in domain XML and start vm
    5. check resctrl dir and verify libvirt set right values
    """

    vm_name = params.get("main_vm", "avocado-vt-vm1")
    test_vm = env.get_vm(vm_name)
    schemata_file1 = params.get("schemata_file1", "")
    schemata_file2 = params.get("schemata_file2", "")
    mb_value1 = params.get("mb_value1", "")
    mb_value2 = params.get("mb_value2", "")
    vcpu_max_num = int(params.get("vcpu_max_num"))
    vcpu_current_num = int(params.get("vcpu_current_num"))
    topology_correction = "yes" == params.get("topology_correction", "no")
    cachetune_items = params.get("cachetune_items")
    test_memtune = params.get("test_memtune", 'no') == 'yes'
    memorytune_item_list, node_item_list, mem_monitor_item_list = None, None, None
    vcpupins = params.get("vcpupins")
    placement = params.get('placement')
    iothreads = params.get('iothreads')
    vcpuscheds = params.get('vcpuscheds')
    emulatorsched = params.get('emulatorsched')
    check_policy = params.get('check_policy')

    if test_memtune:
        check_host(test)
        (memorytune_item_list, node_item_list,
         mem_monitor_item_list) = assemble_memorytune(params)

    vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    backup_xml = vmxml.copy()

    try:
        # change the vcpu number from 2 to 5
        vmxml.set_vm_vcpus(vm_name,
                           vcpu_max_num,
                           vcpu_current_num,
                           topology_correction=topology_correction)
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
        if placement:
            vmxml.placement = placement
        if iothreads:
            vmxml.iothreads = int(iothreads)
        cputunexml = vm_xml.VMCPUTuneXML()

        if memorytune_item_list:
            cputunexml = update_with_memorytune(cputunexml,
                                                memorytune_item_list,
                                                node_item_list,
                                                mem_monitor_item_list)

        if cachetune_items:
            cputunexml = update_with_cachetune(cputunexml, params)
        if vcpupins:
            cputunexml.vcpupins = eval(vcpupins)
        if vcpuscheds:
            cputunexml.vcpuscheds = eval(vcpuscheds)
        if emulatorsched:
            cputunexml.emulatorsched = emulatorsched
        logging.debug("cputunexml: %s" % cputunexml)
        vmxml.cputune = cputunexml
        logging.debug("vm xml: %s", vmxml)
        vmxml.sync()
        test_vm.start()
        logging.debug("VM xml after starting:\n%s",
                      vm_xml.VMXML.new_from_dumpxml(vm_name))
        if test_memtune:
            # 5.Check resctrl dir and verify libvirt set right values
            check_membind_value(test, schemata_file1, mb_value1)
            check_membind_value(test, schemata_file2, mb_value2)
            found_mb = verify_membind_value(schemata_file1, mb_value1)
            if not found_mb:
                test.fail("The first schemata %s for vcpus is not set valid" %
                          schemata_file1)

            found_mb = verify_membind_value(schemata_file2, mb_value2)
            if not found_mb:
                test.fail("The second schemata %s for vcpus is not set valid" %
                          schemata_file2)

            # 6. Check domstats memory
            if libvirt_version.version_compare(6, 0, 0):
                result = virsh.domstats(vm_name,
                                        "--memory",
                                        ignore_status=True,
                                        debug=True)
                libvirt.check_exit_status(result)
                output = result.stdout.strip()
                logging.debug("domstats output is %s", output)

            # 7. Destroy the vm and verify the libvirt dir exist
            test_vm.destroy(gracefully=False)
            if os.path.exists(schemata_file1) or os.path.exists(
                    schemata_file2):
                test.fail(
                    "The schemata file should be deleted after vm destroy")
        if check_policy:
            check_scheduler_policy(eval(check_policy), test)

    finally:
        if test_vm.is_alive():
            test_vm.destroy(gracefully=False)
        if test_memtune:
            process.run("umount /sys/fs/resctrl", verbose=True, shell=True)
        backup_xml.sync()
Example #7
0
def run(test, params, env):
    """
    Test command: virsh schedinfo.

    This version provide base test of virsh schedinfo command:
    virsh schedinfo <vm> [--set<set_ref>]
    TODO: to support more parameters.

    1) Get parameters and prepare vm's state
    2) Prepare test options.
    3) Run schedinfo command to set or get parameters.
    4) Get schedinfo in cgroup
    5) Recover environment like vm's state
    6) Check result.
    """
    def get_parameter_in_cgroup(vm, cgroup_type, parameter):
        """
        Get vm's cgroup value.

        :Param vm: the vm object
        :Param cgroup_type: type of cgroup we want, vcpu or emulator.
        :Param parameter: the cgroup parameter of vm which we need to get.
        :return: False if expected controller is not mounted.
                 else return value's result object.
        """
        cgroup_path = \
            utils_cgroup.resolve_task_cgroup_path(vm.get_pid(), "cpu")

        if not cgroup_type == "emulator":
            # When a VM has an 'emulator' child cgroup present, we must
            # strip off that suffix when detecting the cgroup for a machine
            if os.path.basename(cgroup_path) == "emulator":
                cgroup_path = os.path.dirname(cgroup_path)
            cgroup_file = os.path.join(cgroup_path, parameter)
        else:
            cgroup_file = os.path.join(cgroup_path, parameter)

        cg_file = None
        try:
            try:
                cg_file = open(cgroup_file)
                result = cg_file.read()
            except IOError:
                raise error.TestError("Failed to open cgroup file %s"
                                      % cgroup_file)
        finally:
            if cg_file is not None:
                cg_file.close()
        return result.strip()

    def schedinfo_output_analyse(result, set_ref, scheduler="posix"):
        """
        Get the value of set_ref.

        :param result: CmdResult struct
        :param set_ref: the parameter has been set
        :param scheduler: the scheduler of qemu(default is posix)
        """
        output = result.stdout.strip()
        if not re.search("Scheduler", output):
            raise error.TestFail("Output is not standard:\n%s" % output)

        result_lines = output.splitlines()
        set_value = None
        for line in result_lines:
            key_value = line.split(":")
            key = key_value[0].strip()
            value = key_value[1].strip()
            if key == "Scheduler":
                if value != scheduler:
                    raise error.TestNAError("This test do not support"
                                            " %s scheduler." % scheduler)
            elif key == set_ref:
                set_value = value
                break
        return set_value

    # Prepare test options
    vm_ref = params.get("schedinfo_vm_ref", "domname")
    options_ref = params.get("schedinfo_options_ref", "")
    options_suffix = params.get("schedinfo_options_suffix", "")
    schedinfo_param = params.get("schedinfo_param", "vcpu")
    set_ref = params.get("schedinfo_set_ref", "")
    cgroup_ref = params.get("schedinfo_cgroup_ref", "cpu.shares")
    set_value = params.get("schedinfo_set_value", "")
    set_method = params.get("schedinfo_set_method", "cmd")
    set_value_expected = params.get("schedinfo_set_value_expected", "")
    # The default scheduler on qemu/kvm is posix
    scheduler_value = "posix"
    status_error = params.get("status_error", "no")

    # Prepare vm test environment
    vm_name = params.get("main_vm")
    
    # Back up xml file.Xen host has no guest xml file to define a guset.
    backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    
    if set_ref == "none":
        options_ref = "--set"
        set_ref = None
    elif set_ref:
        if set_method == 'cmd':
            if set_value:
                options_ref = "--set %s=%s" % (set_ref, set_value)
            else:
                options_ref = "--set %s" % set_ref
        elif set_method == 'xml':
            xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            try:
                cputune = xml.cputune
            except xcepts.LibvirtXMLNotFoundError:
                cputune = vm_xml.VMCPUTuneXML()
            name_map = {
                'cpu_shares': 'shares',
                'vcpu_period': 'period',
                'vcpu_quota': 'quota',
                'emulator_period': 'emulator_period',
                'emulator_quota': 'emulator_quota',
            }
            cputune[name_map[set_ref]] = int(set_value)
            xml.cputune = cputune
            xml.sync()

    vm = env.get_vm(vm_name)
    if vm.is_dead():
        vm.start()
    domid = vm.get_id()
    domuuid = vm.get_uuid()

    if vm_ref == "domid":
        vm_ref = domid
    elif vm_ref == "domname":
        vm_ref = vm_name
    elif vm_ref == "domuuid":
        vm_ref = domuuid
    elif vm_ref == "hex_id":
        if domid == '-':
            vm_ref = domid
        else:
            vm_ref = hex(int(domid))

    options_ref += " %s " % options_suffix
    
    try:
        # Run command
        result = virsh.schedinfo(vm_ref, options_ref,
                                 ignore_status=True, debug=True)
        status = result.exit_status

        # VM must be running to get cgroup parameters.
        if not vm.is_alive():
          vm.start()

        if options_ref.count("config"):
          vm.destroy()
          time.sleep(1)
          vm.start()

        set_value_of_cgroup = get_parameter_in_cgroup(vm, cgroup_type=schedinfo_param,
                                                      parameter=cgroup_ref)
        vm.destroy()

        if set_ref:
          set_value_of_output = schedinfo_output_analyse(result, set_ref,
                                                         scheduler_value)
    finally:
        backup_xml.sync()

    # Check result
    if status_error == "no":
        if status:
          raise error.TestFail("Run failed with right command.")
        else:
          if set_ref and set_value_expected:
              logging.info("value will be set:%s\n"
                           "set value in output:%s\n"
                           "set value in cgroup:%s\n"
                           "expected value:%s" % (
                               set_value, set_value_of_output,
                               set_value_of_cgroup, set_value_expected))
              if set_value_of_output is None:
                  raise error.TestFail("Get parameter %s failed." % set_ref)
              # Value in output of virsh schedinfo is not guaranteed 'correct'
              # when we use --config.
              # This is my attempt to fix it
              # http://www.redhat.com/archives/libvir-list/2014-May/msg00466.html.
              # But this patch did not go into upstream of libvirt.
              # Libvirt just guarantee that the value is correct in next boot
              # when we use --config. So skip checking of output in this case.
              if (not (set_value_expected == set_value_of_output) and
                      not (options_ref.count("config"))):
                  raise error.TestFail("Run successful but value "
                                       "in output is not expected.")
              if not (set_value_expected == set_value_of_cgroup):
                  raise error.TestFail("Run successful but value "
                                       "in cgroup is not expected.")
    else:
        if not status:
            raise error.TestFail("Run successfully with wrong command.")
Example #8
0
def run(test, params, env):
    """
    Test:<memorytune>
    1. Check virsh capabilities report right MBA info
    2  Mount resctrl
    3. Check host MBA info from virsh capabilities output
    4. Add memory bandwidth in domain XML and start vm
    5. check resctrl dir and verify libvirt set right values
    """

    vm_name = params.get("main_vm", "avocado-vt-vm1")
    test_vm = env.get_vm(vm_name)
    schemata_file1 = params.get("schemata_file1", "")
    schemata_file2 = params.get("schemata_file2", "")
    mb_value1 = params.get("mb_value1", "")
    mb_value2 = params.get("mb_value2", "")
    vcpu_max_num = int(params.get("vcpu_max_num"))
    vcpu_current_num = int(params.get("vcpu_current_num"))
    topology_correction = "yes" == params.get("topology_correction", "no")

    # 1.Check virsh capabilities
    if not utils_misc.get_cpu_info()['Flags'].find('mba '):
        test.cancel("This machine doesn't support cpu 'mba' flag")

    # 2.Mount resctrl
    process.run("mount -t resctrl resctrl /sys/fs/resctrl",
                verbose=True, shell=True)
    process.run("echo 'L3:0=0ff;1=0ff' > /sys/fs/resctrl/schemata",
                verbose=True, shell=True)

    # 3.Check host MBA info from virsh capabilities output
    cmd = "virsh capabilities | awk '/<memory_bandwidth>/,\
           /<\/memory_bandwidth>/'"
    out = ""
    out = process.run(cmd, shell=True).stdout_text

    if not re.search('node', out):
        test.fail("There is no memory_bandwidth info in capablities")

    # 4.Add memory bandwidth in domain XML
    memorytune_item_list = [ast.literal_eval(x)
                            for x in params.get("memorytune_items",
                                                "").split(';')]
    node_item_list1 = [ast.literal_eval(x)
                       for x in params.get("node_items1",
                                           "").split(';')]
    node_item_list2 = [ast.literal_eval(x)
                       for x in params.get("node_items2",
                                           "").split(';')]
    node_item_list = []
    node_item_list.append(node_item_list1)
    node_item_list.append(node_item_list2)
    cachetune_items = params.get("cachetune_items")

    vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    backup_xml = vmxml.copy()

    try:
        # change the vcpu number from 2 to 5
        vmxml.set_vm_vcpus(vm_name, vcpu_max_num, vcpu_current_num,
                           topology_correction=topology_correction)
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

        cputunexml = vm_xml.VMCPUTuneXML()
        logging.debug("cputunexml: %s" % cputunexml)

        if memorytune_item_list:
            for mitem in range(len(memorytune_item_list)):
                logging.debug("node %d " % mitem)
                memorytunexml = vm_xml.MemoryTuneXML()

                memorytunexml.vcpus = memorytune_item_list[mitem]['vcpus']
                for node in node_item_list[mitem]:
                    nodexml = memorytunexml.NodeXML()
                    nodexml.id = node['id']
                    nodexml.bandwidth = node['bandwidth']
                    memorytunexml.set_node(nodexml)

                logging.debug("memorytunexml.xml %s" % memorytunexml.xml)

                cputunexml.set_memorytune(memorytunexml)
                logging.debug("cputunexml.xml %s" % cputunexml.xml)

        if cachetune_items:
            cachetune_item_list = [ast.literal_eval(x)
                                   for x in params.get("cachetune_items",
                                                       "").split(';')]
            cache_item_list = [ast.literal_eval(x)
                               for x in params.get("cache_items",
                                                   "").split(';')]
            monitor_item_list = [ast.literal_eval(x)
                                 for x in params.get("monitor_items",
                                                     "").split(';')]
            for citem in range(len(cachetune_item_list)):
                logging.debug("cache %d " % citem)
                cachetunexml = vm_xml.CacheTuneXML()
                logging.debug("cachetunexml: %s" % cachetunexml)
                cachetunexml.vcpus = cachetune_item_list[citem]['vcpus']
                for cache in cache_item_list:
                    cachexml = cachetunexml.CacheXML()
                    cachexml.id = cache['id']
                    cachexml.level = cache['level']
                    cachexml.type = cache['type']
                    cachexml.size = cache['size']
                    cachexml.unit = cache['unit']
                    cachetunexml.set_cache(cachexml)

                for monitor in monitor_item_list:
                    monitorxml = cachetunexml.MonitorXML()
                    monitorxml.level = monitor['level']
                    monitorxml.vcpus = monitor['vcpus']
                    cachetunexml.set_monitor(monitorxml)
                cputunexml.set_cachetune(cachetunexml)

        vmxml.cputune = cputunexml
        logging.debug("vm xml: %s", vmxml)

        vmxml.sync()
        test_vm.start()

        # 5.Check resctrl dir and verify libvirt set right values
        check_membind_value(test, schemata_file1, mb_value1)
        check_membind_value(test, schemata_file2, mb_value2)
        found_mb = verify_membind_value(schemata_file1, mb_value1)
        if not found_mb:
            test.fail("The first schemata %s for vcpus is not set valid" %
                      schemata_file1)

        found_mb = verify_membind_value(schemata_file2, mb_value2)
        if not found_mb:
            test.fail("The second schemata %s for vcpus is not set valid" %
                      schemata_file2)

        # 6. Destroy the vm and verify the libvirt dir exist
        test_vm.destroy(gracefully=False)
        if os.path.exists(schemata_file1) or os.path.exists(schemata_file2):
            test.fail("The schemata file should be deleted after vm destroy")

    finally:
        if test_vm.is_alive():
            test_vm.destroy(gracefully=False)
        process.run("umount /sys/fs/resctrl",
                    verbose=True, shell=True)
        backup_xml.sync()
Example #9
0
def run(test, params, env):
    """
    Test vcpu affinity feature as follows:
    positive test:
        1. use vcpu cpuset in xml to define vcpu affinity
        2. use cputune cpuset in xml to define vcpu affinity
        3. use offline-to-online host cpu as cpuset to run virsh vcpupin
        4. set vcpu placement in xml to auto and check xml result
        5. set vcpu cpuset in xml without placement defined and check xml result
        6. specify vcpu affinity for inactive vcpu
    negative test:
        1. use outrange cpuset as vcpu cpuset in xml to define vcpu affinity
        2. use outrange cpuset as cputune cpuset in xml to define vcpu affinity
        3. use invalid cpuset as cputune cpuset in xml to define vcpu affinity
        4. use duplicate vcpu in xml to define vcpu affinity
        5. use offline host cpu as cputune cpuset to run virsh vcpupin
        6. set vcpu affinity for none exists vcpu and check xml result
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    cpuset_mask = params.get("cpuset_mask", "")
    vcpu = params.get("vcpu", "0")
    setvcpus_option = params.get("setvcpus_option", "")
    setvcpus_count = params.get("setvcpus_count", "0")
    vcpupin_option = params.get("vcpupin_option", "")
    maxvcpu = params.get("maxvcpu", "8")
    current_vcpu = params.get("current_vcpu", "3")
    check = params.get("check", "")
    config_xml = params.get("config_xml", "")

    status_error = "yes" == params.get("status_error", "no")
    define_fail = "yes" == params.get("define_fail", "no")
    start_fail = "yes" == params.get("start_fail", "no")
    runtime_fail = "yes" == params.get("runtime_fail", "no")
    hotplug_vcpu = "yes" == params.get("hotplug_vcpu", "no")

    vcpu_cpuset = params.get("vcpu_cpuset", "")
    cputune_cpuset = params.get("cputune_cpuset", "")
    vcpu_placement = params.get("vcpu_placement", "static")
    err_msg = params.get("err_msg", "")
    start_timeout = int(params.get("start_timeout", "180"))
    offline_hostcpus = params.get("offline_hostcpus", "")
    machine_cpuset_path = params.get("machine_cpuset_path", "")

    vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
    vmxml_backup = vmxml.copy()

    def check_vcpu_affinity():
        """
        check vcpu affinity defined by vcpu cpuset or cputune cpuset
        """
        affinity = vcpu_cpuset if not cputune_cpuset else cputune_cpuset
        affinity = {vcpu: affinity}
        virsh.vcpuinfo(vm_name, debug=True)
        host_cpu_count = cpuutil.total_cpus_count()

        vmxml_live = vm_xml.VMXML.new_from_dumpxml(vm_name)
        logging.debug(vmxml_live)

        # if vcpu >= maxvcpu, the cputune should not exist in xml
        if int(vcpu) >= int(maxvcpu):
            try:
                if hasattr(vmxml_live, 'cputune'):
                    test.fail("cputune tag is set when vcpu >= maxvcpu")
            except xcepts.LibvirtXMLError:
                pass
        elif "config" in vcpupin_option:
            vcpu_affinity = cpu.affinity_from_vcpupin(vm, vcpu, vcpupin_option)
            affinity = cpu.cpus_string_to_affinity_list(
                str(affinity[vcpu]), host_cpu_count)
            logging.debug("vcpu_affinity {}".format(vcpu_affinity))
            logging.debug("affinity {}".format(affinity))
            if vcpu_affinity[int(vcpu)] != affinity:
                test.fail("vcpu affinity check fail")
        # check the expected vcpu affinity with the one got from running vm
        elif not cpu.check_affinity(vm, affinity):
            test.fail("vcpu affinity check fail")

    try:
        hostcpu_num = int(cpuutil.total_cpus_count())
        if hostcpu_num < 8:
            test.cancel("The host should have at least 8 CPUs for this test.")

        # online all host cpus
        for x in range(1, hostcpu_num):
            if cpuutil.online(x):
                test.fail("fail to online cpu{}".format(x))

        # use vcpu cpuset or/and cputune cpuset to define xml
        del vmxml.cputune
        del vmxml.vcpus
        del vmxml.placement
        vmxml.vcpu = int(maxvcpu)
        vmxml.current_vcpu = current_vcpu

        # Remove cpu topology to avoid that it doesn't match vcpu count
        if vmxml.get_cpu_topology():
            new_cpu = vmxml.cpu
            del new_cpu.topology
            vmxml.cpu = new_cpu

        # config vcpu cpuset for cpuset range test
        num = 1 if not status_error else 0
        cpuset_new = "0-{},^{}".format(hostcpu_num-num, cpuset_mask)
        if (config_xml == "vcpu" and check.endswith("range_cpuset")):
            vcpu_cpuset = cpuset_new
        vmxml.cpuset = vcpu_cpuset

        if vcpu_placement:
            vmxml.placement = vcpu_placement

            # Remove numatune node since it will be automatically set
            # under 'auto' state
            if vcpu_placement == 'auto':
                vmxml.xmltreefile.remove_by_xpath('/numatune', remove_all=True)
                vmxml.xmltreefile.write()

        if config_xml == "cputune":
            cputune = vm_xml.VMCPUTuneXML()
            if check.endswith("range_cpuset"):
                cputune_cpuset = cpuset_new
            if check.endswith("duplicate_vcpu"):
                cputune.vcpupins = [{'vcpu': vcpu, 'cpuset': "2"}, {'vcpu': vcpu, 'cpuset': "3"}]
            else:
                cputune.vcpupins = [{'vcpu': vcpu, 'cpuset': cputune_cpuset}]
            vmxml.cputune = cputune

        logging.debug(vmxml)
        if status_error and define_fail:
            result_to_check = virsh.define(vmxml.xml, debug=True)
        else:
            vmxml.sync()

        # test vcpu cpuset in offline/online host cpu scenario
        if check.endswith("offline_hostcpu"):
            for x in offline_hostcpus.split(','):
                if cpuutil.offline(x):
                    test.fail("fail to offline cpu{}".format(x))
                logging.debug("offline host cpu {}".format(x))

        # start the vm
        if status_error and start_fail:
            result_to_check = virsh.start(vm_name, debug=True)

        if (not status_error) or runtime_fail:
            vm.start()
            vm.wait_for_login(timeout=start_timeout).close()

            # test vcpu cpuset in offline/online host cpu scenario
            if check.endswith("offline_hostcpu") and not status_error:
                # online host cpu
                if cpuutil.online(cputune_cpuset):
                    test.fail("fail to online cpu{}".format(cputune_cpuset))

            # run virsh vcpupin to config vcpu affinity
            if check.startswith("cputune") and (not config_xml):
                result_to_check = virsh.vcpupin(vm_name, vcpu, cputune_cpuset, vcpupin_option, debug=True)

            # hotplug vcpu test scenario
            if hotplug_vcpu:
                virsh.setvcpus(vm_name, setvcpus_count, setvcpus_option, debug=True, ignore_status=False)

            libvirtd_restart = False
            while True:
                if check == "vcpu_placement":
                    check_vcpu_placement(test, params)
                elif not status_error:
                    check_vcpu_affinity()
                if libvirtd_restart:
                    break
                # restart libvirtd and check vcpu affinity again
                utils_libvirtd.Libvirtd().restart()
                libvirtd_restart = True

        if 'result_to_check' in locals():
            if err_msg:
                err_msg = err_msg.split(";")
            libvirt.check_result(result_to_check, err_msg)

    finally:
        vmxml_backup.sync()

        # recovery the host cpu env
        for x in range(1, hostcpu_num):
            cpuutil.online(x)
        cmd = "echo '0-{}' > {}".format(hostcpu_num-1, machine_cpuset_path)
        process.run(cmd, shell=True)
Example #10
0
def run(test, params, env):
    """
    Test command: virsh schedinfo.

    This version provide base test of virsh schedinfo command:
    virsh schedinfo <vm> [--set<set_ref>]
    TODO: to support more parameters.

    1) Get parameters and prepare vm's state
    2) Prepare test options.
    3) Run schedinfo command to set or get parameters.
    4) Get schedinfo in cgroup
    5) Recover environment like vm's state
    6) Check result.
    """
    def get_parameter_in_cgroup(vm, cgroup_type, parameter):
        """
        Get vm's cgroup value.

        :Param vm: the vm object
        :Param cgroup_type: type of cgroup we want, vcpu or emulator.
        :Param parameter: the cgroup parameter of vm which we need to get.
        :return: the value of parameter in cgroup.
        """
        vm_pid = vm.get_pid()
        cgtest = libvirt_cgroup.CgroupTest(vm_pid)
        cgroup_info = cgtest.get_standardized_cgroup_info("schedinfo")

        logging.debug("cgroup_info is %s" % cgroup_info)
        if parameter in ["cpu.cfs_period_us", "cpu.cfs_quota_us"]:
            if cgroup_type == "emulator":
                parameter = "%s/%s" % (cgroup_type, parameter)
            elif cgroup_type in ["vcpu", "iothread"]:
                parameter = "<%sX>/%s" % (cgroup_type, parameter)
        for key, value in libvirt_cgroup.CGROUP_V1_SCHEDINFO_FILE_MAPPING.items():
            if value == parameter:
                cgroup_ref_key = key
                break
        if 'cgroup_ref_key' not in locals():
            test.error("{} is not found in CGROUP_V1_SCHEDINFO_FILE_MAPPING."
                       .format(parameter))
        return cgroup_info[cgroup_ref_key]

    def analyse_schedinfo_output(result, set_ref):
        """
        Get the value of set_ref.

        :param result: CmdResult struct
        :param set_ref: the parameter has been set
        :return: the value of the parameter.
        """
        cg_obj = libvirt_cgroup.CgroupTest(None)
        output_dict = cg_obj.convert_virsh_output_to_dict(result)
        result_info = cg_obj.get_standardized_virsh_info("schedinfo", output_dict)
        set_value_list = []
        for set_ref_node in set_ref.split(","):
            if result_info.get(set_ref_node):
                set_value_list.append(result_info.get(set_ref_node))

        return set_value_list

    def get_current_value():
        """
        Get the current schedinfo value and return
        """
        current_result = virsh.schedinfo(vm_ref, " --current",
                                         ignore_status=True, debug=True)
        current_value = analyse_schedinfo_output(current_result, set_ref)
        return current_value

    # Prepare test options
    vm_ref = params.get("schedinfo_vm_ref", "domname")
    options_ref = params.get("schedinfo_options_ref", "")
    options_suffix = params.get("schedinfo_options_suffix", "")
    schedinfo_param = params.get("schedinfo_param", "vcpu")
    set_ref = params.get("schedinfo_set_ref", "")
    cgroup_ref = params.get("schedinfo_cgroup_ref", "cpu.shares")
    set_value = params.get("schedinfo_set_value", "")
    set_method = params.get("schedinfo_set_method", "cmd")
    set_value_expected = params.get("schedinfo_set_value_expected", "")
    # Libvirt version where function begins to change
    libvirt_ver_function_changed = eval(params.get(
        "libvirt_ver_function_changed", '[]'))
    # The default scheduler on qemu/kvm is posix
    scheduler_value = "posix"
    status_error = params.get("status_error", "no")
    start_vm = ("yes" == params.get("start_vm"))
    readonly = ("yes" == params.get("schedinfo_readonly", "no"))
    expect_msg = params.get("schedinfo_err_msg", "")

    if libvirt_cgroup.CgroupTest(None).is_cgroup_v2_enabled():
        if params.get("schedinfo_set_value_cgroupv2"):
            set_value = params.get("schedinfo_set_value_cgroupv2")
        if params.get("schedinfo_set_value_expected_cgroupv2"):
            set_value_expected = params.get(
                "schedinfo_set_value_expected_cgroupv2")
        if params.get("cgroup_v2_unsupported_reason"):
            test.cancel(params.get('cgroup_v2_unsupported_reason'))

    if libvirt_ver_function_changed:
        if not libvirt_version.version_compare(*libvirt_ver_function_changed):
            set_value = params.get("schedinfo_set_value_bk")
            set_value_expected = params.get("schedinfo_set_value_expected_bk")

    # Prepare vm test environment
    vm_name = params.get("main_vm")

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

    if set_ref == "none":
        options_ref = "--set"
        set_ref = None
    elif set_ref:
        # Prepare vm xml for iothread test
        if schedinfo_param == 'iothread':
            virsh.iothreadadd(vm_name, '1', ignore_status=False, debug=True)
        if set_method == 'cmd':
            if set_value:
                set_ref_list = set_ref.split(",")
                set_value_list = set_value.split(",")
                for i in range(0, len(set_ref_list)):
                    if "--set" in options_ref:
                        options_ref += " %s=%s" % (set_ref_list[i], set_value_list[i])
                    else:
                        options_ref = "--set %s=%s" % (set_ref_list[i], set_value_list[i])
            else:
                options_ref = "--set %s" % set_ref
        elif set_method == 'xml':
            xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            try:
                cputune = xml.cputune
            except xcepts.LibvirtXMLNotFoundError:
                cputune = vm_xml.VMCPUTuneXML()
            name_map = {
                'cpu_shares': 'shares',
                'vcpu_period': 'period',
                'vcpu_quota': 'quota',
                'emulator_period': 'emulator_period',
                'emulator_quota': 'emulator_quota',
                'global_period': 'global_period',
                'global_quota': 'global_quota',
                'iothread_period': 'iothread_period',
                'iothread_quota': 'iothread_quota'
            }
            cputune[name_map[set_ref]] = int(set_value)
            xml.cputune = cputune
            xml.sync()
            logging.debug("After setting xml, VM XML:\n%s",
                          vm_xml.VMXML.new_from_dumpxml(vm_name))

    vm = env.get_vm(vm_name)
    if vm.is_dead() and start_vm:
        try:
            vm.start()
        except Exception as detail:
            orig_config_xml.sync()
            test.error(detail)

    domid = vm.get_id()
    domuuid = vm.get_uuid()

    if vm_ref == "domid":
        vm_ref = domid
    elif vm_ref == "domname":
        vm_ref = vm_name
    elif vm_ref == "domuuid":
        vm_ref = domuuid
    elif vm_ref == "hex_id":
        if domid == '-':
            vm_ref = domid
        else:
            vm_ref = hex(int(domid))

    options_ref += " %s " % options_suffix

    # Get schedinfo with --current parameter
    if set_ref and options_ref.count("config") and start_vm:
        bef_current_value = get_current_value()

    try:
        # Run command
        result = virsh.schedinfo(vm_ref, options_ref,
                                 ignore_status=True, debug=True, readonly=readonly)
        status = result.exit_status

        # VM must be running to get cgroup parameters.
        if not vm.is_alive():
            vm.start()

        if options_ref.count("config") and start_vm:
            # Get schedinfo with --current parameter
            aft_current_value = get_current_value()
            if bef_current_value != aft_current_value:
                test.fail("--config change the current %s" % set_ref)

            vm.destroy()
            vm.start()
            vm_ref = vm.get_id()

        if set_ref:
            start_current_value = get_current_value()

        set_value_of_cgroup = get_parameter_in_cgroup(vm, cgroup_type=schedinfo_param,
                                                      parameter=cgroup_ref)
        vm.destroy(gracefully=False)

        if set_ref:
            set_value_of_output = analyse_schedinfo_output(result, set_ref)

        # Check result
        if status_error == "no":
            if status:
                test.fail("Run failed with right command. Error: {}"
                          .format(result.stderr.strip()))
            else:
                if set_ref and set_value_expected:
                    logging.info("value will be set:%s\n"
                                 "set value in output:%s\n"
                                 "set value in cgroup:%s\n"
                                 "expected value:%s" % (
                                     set_value, set_value_of_output,
                                     set_value_of_cgroup, set_value_expected))
                    if set_value_of_output is None:
                        test.fail("Get parameter %s failed." % set_ref)
                    # Value in output of virsh schedinfo is not guaranteed 'correct'
                    # when we use --config.
                    # This is my attempt to fix it
                    # http://www.redhat.com/archives/libvir-list/2014-May/msg00466.html.
                    # But this patch did not go into upstream of libvirt.
                    # Libvirt just guarantee that the value is correct in next boot
                    # when we use --config. So skip checking of output in this case.
                    expected_value_list = sorted(set_value_expected.split(','))
                    if (not (expected_value_list == sorted(set_value_of_output)) and
                            not (options_ref.count("config"))):
                        test.fail("Run successful but value "
                                  "in output is not expected.")
                    if len(set_value_expected.split(',')) == 1:
                        if not (set_value_expected == set_value_of_cgroup):
                            test.fail("Run successful but value "
                                      "in cgroup is not expected.")
                        if not (expected_value_list == sorted(start_current_value)):
                            test.fail("Run successful but current "
                                      "value is not expected.")
        else:
            if not status:
                test.fail("Run successfully with wrong command. Output: {}"
                          .format(result.stdout_text.strip()))
            if not re.search(expect_msg, result.stderr_text.strip()):
                test.fail("Fail to get expect err msg! "
                          "Expected: {} Actual: {}"
                          .format(expect_msg, result.stderr_text.strip()))
    finally:
        orig_config_xml.sync()
Example #11
0
def run(test, params, env):
    """
    Test command: virsh schedinfo.

    This version provide base test of virsh schedinfo command:
    virsh schedinfo <vm> [--set<set_ref>]
    TODO: to support more parameters.

    1) Get parameters and prepare vm's state
    2) Prepare test options.
    3) Run schedinfo command to set or get parameters.
    4) Get schedinfo in cgroup
    5) Recover environment like vm's state
    6) Check result.
    """
    def get_parameter_in_cgroup(vm, cgroup_type, parameter):
        """
        Get vm's cgroup value.

        :Param vm: the vm object
        :Param cgroup_type: type of cgroup we want, vcpu or emulator.
        :Param parameter: the cgroup parameter of vm which we need to get.
        :return: False if expected controller is not mounted.
                 else return value's result object.
        """
        cgroup_path = \
            utils_cgroup.resolve_task_cgroup_path(vm.get_pid(), "cpu")
        logging.debug("cgroup_path=%s", cgroup_path)
        if not cgroup_type == "emulator":
            # When a VM has an 'emulator' child cgroup present, we must
            # strip off that suffix when detecting the cgroup for a machine
            if os.path.basename(cgroup_path) == "emulator":
                cgroup_path = os.path.dirname(cgroup_path)
            if cgroup_type == 'iothread':
                parameter = 'iothread1/%s' % parameter
            if cgroup_type == 'vcpu' and parameter != 'cpu.shares':
                parameter = 'vcpu0/%s' % parameter
            if parameter == 'cpu.shares' and libvirt_version.version_compare(
                    7, 0, 0):
                cgroup_path = os.path.dirname(cgroup_path)
            logging.debug("cgroup_path is updated to '%s'", cgroup_path)
        cgroup_file = os.path.join(cgroup_path, parameter)
        logging.debug("cgroup_file=%s", cgroup_file)

        cg_file = None
        try:
            try:
                cg_file = open(cgroup_file)
                result = cg_file.read()
            except IOError:
                test.error("Failed to open cgroup file %s" % cgroup_file)
        finally:
            if cg_file is not None:
                cg_file.close()
        return result.strip()

    def schedinfo_output_analyse(result, set_ref, scheduler="posix"):
        """
        Get the value of set_ref.

        :param result: CmdResult struct
        :param set_ref: the parameter has been set
        :param scheduler: the scheduler of qemu(default is posix)
        """
        output = result.stdout.strip()
        if not re.search("Scheduler", output):
            test.fail("Output is not standard:\n%s" % output)

        result_lines = output.splitlines()
        set_value_list = []
        for set_ref_node in set_ref.split(","):
            for line in result_lines:
                key_value = line.split(":")
                key = key_value[0].strip()
                value = key_value[1].strip()
                if key == "Scheduler":
                    if value != scheduler:
                        test.cancel("This test do not support"
                                    " %s scheduler." % scheduler)
                elif key == set_ref_node:
                    set_value_list.append(value)
                    break
        return set_value_list

    def get_current_value():
        """
        Get the current schedinfo value and return
        """
        current_result = virsh.schedinfo(vm_ref,
                                         " --current",
                                         ignore_status=True,
                                         debug=True)
        current_value = schedinfo_output_analyse(current_result, set_ref,
                                                 scheduler_value)
        return current_value

    # Prepare test options
    vm_ref = params.get("schedinfo_vm_ref", "domname")
    options_ref = params.get("schedinfo_options_ref", "")
    options_suffix = params.get("schedinfo_options_suffix", "")
    schedinfo_param = params.get("schedinfo_param", "vcpu")
    set_ref = params.get("schedinfo_set_ref", "")
    cgroup_ref = params.get("schedinfo_cgroup_ref", "cpu.shares")
    set_value = params.get("schedinfo_set_value", "")
    set_method = params.get("schedinfo_set_method", "cmd")
    set_value_expected = params.get("schedinfo_set_value_expected", "")
    # Libvirt version where function begins to change
    libvirt_ver_function_changed = eval(
        params.get("libvirt_ver_function_changed", '[]'))
    # The default scheduler on qemu/kvm is posix
    scheduler_value = "posix"
    status_error = params.get("status_error", "no")
    start_vm = ("yes" == params.get("start_vm"))
    readonly = ("yes" == params.get("schedinfo_readonly", "no"))
    expect_msg = params.get("schedinfo_err_msg", "")

    if libvirt_ver_function_changed:
        if not libvirt_version.version_compare(*libvirt_ver_function_changed):
            set_value = params.get("schedinfo_set_value_bk")
            set_value_expected = params.get("schedinfo_set_value_expected_bk")

    # Prepare vm test environment
    vm_name = params.get("main_vm")

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

    if set_ref == "none":
        options_ref = "--set"
        set_ref = None
    elif set_ref:
        # Prepare vm xml for iothread test
        if schedinfo_param == 'iothread':
            virsh.iothreadadd(vm_name, '1', ignore_status=False, debug=True)
        if set_method == 'cmd':
            if set_value:
                set_ref_list = set_ref.split(",")
                set_value_list = set_value.split(",")
                for i in range(0, len(set_ref_list)):
                    if "--set" in options_ref:
                        options_ref += " %s=%s" % (set_ref_list[i],
                                                   set_value_list[i])
                    else:
                        options_ref = "--set %s=%s" % (set_ref_list[i],
                                                       set_value_list[i])
            else:
                options_ref = "--set %s" % set_ref
        elif set_method == 'xml':
            xml = vm_xml.VMXML.new_from_dumpxml(vm_name)
            try:
                cputune = xml.cputune
            except xcepts.LibvirtXMLNotFoundError:
                cputune = vm_xml.VMCPUTuneXML()
            name_map = {
                'cpu_shares': 'shares',
                'vcpu_period': 'period',
                'vcpu_quota': 'quota',
                'emulator_period': 'emulator_period',
                'emulator_quota': 'emulator_quota',
                'global_period': 'global_period',
                'global_quota': 'global_quota',
                'iothread_period': 'iothread_period',
                'iothread_quota': 'iothread_quota'
            }
            cputune[name_map[set_ref]] = int(set_value)
            xml.cputune = cputune
            xml.sync()
            logging.debug("After setting xml, VM XML:\n%s",
                          vm_xml.VMXML.new_from_dumpxml(vm_name))

    vm = env.get_vm(vm_name)
    if vm.is_dead() and start_vm:
        vm.start()
    domid = vm.get_id()
    domuuid = vm.get_uuid()

    if vm_ref == "domid":
        vm_ref = domid
    elif vm_ref == "domname":
        vm_ref = vm_name
    elif vm_ref == "domuuid":
        vm_ref = domuuid
    elif vm_ref == "hex_id":
        if domid == '-':
            vm_ref = domid
        else:
            vm_ref = hex(int(domid))

    options_ref += " %s " % options_suffix

    # Get schedinfo with --current parameter
    if set_ref and options_ref.count("config") and start_vm:
        bef_current_value = get_current_value()

    try:
        # Run command
        result = virsh.schedinfo(vm_ref,
                                 options_ref,
                                 ignore_status=True,
                                 debug=True,
                                 readonly=readonly)
        status = result.exit_status

        # VM must be running to get cgroup parameters.
        if not vm.is_alive():
            vm.start()

        if options_ref.count("config") and start_vm:
            # Get schedinfo with --current parameter
            aft_current_value = get_current_value()
            if bef_current_value != aft_current_value:
                test.fail("--config change the current %s" % set_ref)

            vm.destroy()
            vm.start()
            vm_ref = vm.get_id()

        if set_ref:
            start_current_value = get_current_value()

        set_value_of_cgroup = get_parameter_in_cgroup(
            vm, cgroup_type=schedinfo_param, parameter=cgroup_ref)
        vm.destroy(gracefully=False)

        if set_ref:
            set_value_of_output = schedinfo_output_analyse(
                result, set_ref, scheduler_value)

        # Check result
        if status_error == "no":
            if status:
                test.fail("Run failed with right command. Error: {}".format(
                    result.stderr.strip()))
            else:
                if set_ref and set_value_expected:
                    logging.info("value will be set:%s\n"
                                 "set value in output:%s\n"
                                 "set value in cgroup:%s\n"
                                 "expected value:%s" %
                                 (set_value, set_value_of_output,
                                  set_value_of_cgroup, set_value_expected))
                    if set_value_of_output is None:
                        test.fail("Get parameter %s failed." % set_ref)
                    # Value in output of virsh schedinfo is not guaranteed 'correct'
                    # when we use --config.
                    # This is my attempt to fix it
                    # http://www.redhat.com/archives/libvir-list/2014-May/msg00466.html.
                    # But this patch did not go into upstream of libvirt.
                    # Libvirt just guarantee that the value is correct in next boot
                    # when we use --config. So skip checking of output in this case.
                    expected_value_list = sorted(set_value_expected.split(','))
                    if (not (expected_value_list
                             == sorted(set_value_of_output))
                            and not (options_ref.count("config"))):
                        test.fail("Run successful but value "
                                  "in output is not expected.")
                    if len(set_value_expected.split(',')) == 1:
                        if not (set_value_expected == set_value_of_cgroup):
                            test.fail("Run successful but value "
                                      "in cgroup is not expected.")
                        if not (expected_value_list
                                == sorted(start_current_value)):
                            test.fail("Run successful but current "
                                      "value is not expected.")
        else:
            if not status:
                test.fail(
                    "Run successfully with wrong command. Output: {}".format(
                        result.stdout.strip()))
            if readonly:
                if not re.search(expect_msg, result.stderr.strip()):
                    test.fail("Fail to get expect err msg! "
                              "Expected: {} Actual: {}".foramt(
                                  expect_msg, result.stderr.strip()))
    finally:
        orig_config_xml.sync()
Example #12
0
def run(test, params, env):
    """
    Test vcpu affinity feature as follows:
    positive test:
        1. use vcpu cpuset in xml to define vcpu affinity
        2. use cputune cpuset in xml to define vcpu affinity
        3. use offline-to-online host cpu as cpuset to run virsh vcpupin
        4. set vcpu placement in xml to auto and check xml result
        5. set vcpu cpuset in xml without placement defined and check xml result
    negative test:
        1. use outrange cpuset as vcpu cpuset in xml to define vcpu affinity
        2. use outrange cpuset as cputune cpuset in xml to define vcpu affinity
        3. use invalid cpuset as cputune cpuset in xml to define vcpu affinity
        4. use duplicate vcpu in xml to define vcpu affinity
        5. use offline host cpu as cputune cpuset to run virsh vcpupin
    """
    vm_name = params.get("main_vm")
    vm = env.get_vm(vm_name)
    cpuset_mask = params.get("cpuset_mask", "")
    vcpu = params.get("vcpu", "0")
    maxvcpu = params.get("maxvcpu", "8")
    current_vcpu = params.get("current_vcpu", "3")
    check = params.get("check", "")
    config_xml = params.get("config_xml", "")

    status_error = "yes" == params.get("status_error", "no")
    define_fail = "yes" == params.get("define_fail", "no")
    start_fail = "yes" == params.get("start_fail", "no")
    runtime_fail = "yes" == params.get("runtime_fail", "no")
    vm_down = "yes" == params.get("vm_down", "no")

    vcpu_cpuset = params.get("vcpu_cpuset", "")
    cputune_cpuset = params.get("cputune_cpuset", "")
    vcpu_placement = params.get("vcpu_placement", "static")
    err_msg = params.get("err_msg", "")
    start_timeout = int(params.get("start_timeout", "60"))
    offline_hostcpus = params.get("offline_hostcpus", "")
    machine_cpuset_path = params.get("machine_cpuset_path", "")

    vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
    vmxml_backup = vmxml.copy()

    def check_vcpu_affinity():
        """
        check vcpu affinity defined by vcpu cpuset or cputune cpuset
        """
        affinity = vcpu_cpuset if not cputune_cpuset else cputune_cpuset
        affinity = {vcpu: affinity}
        virsh.vcpuinfo(vm_name, debug=True)
        # check the expected vcpu affinity with the one got from running vm
        if not utils_hotplug.check_affinity(vm, affinity):
            test.fail("vcpu affinity check fail")

    try:
        hostcpu_num = int(cpu.total_cpus_count())

        # online all host cpus
        for x in range(hostcpu_num):
            if cpu.online(x):
                test.fail("fail to online cpu{}".format(x))

        # use vcpu cpuset or/and cputune cpuset to define xml
        del vmxml.cputune
        del vmxml.vcpus
        del vmxml.placement
        vmxml.vcpu = int(maxvcpu)
        vmxml.current_vcpu = current_vcpu

        # config vcpu cpuset for cpuset range test
        num = 1 if not status_error else 0
        cpuset_new = "0-{},^{}".format(hostcpu_num - num, cpuset_mask)
        if (config_xml == "vcpu" and check.endswith("range_cpuset")):
            vcpu_cpuset = cpuset_new
        vmxml.cpuset = vcpu_cpuset

        if vcpu_placement:
            vmxml.placement = vcpu_placement

        if config_xml == "cputune":
            cputune = vm_xml.VMCPUTuneXML()
            if check.endswith("range_cpuset"):
                cputune_cpuset = cpuset_new
            if check.endswith("duplicate_vcpu"):
                cputune.vcpupins = [{
                    'vcpu': vcpu,
                    'cpuset': "2"
                }, {
                    'vcpu': vcpu,
                    'cpuset': "3"
                }]
            else:
                cputune.vcpupins = [{'vcpu': vcpu, 'cpuset': cputune_cpuset}]
            vmxml.cputune = cputune

        logging.debug(vmxml)
        if status_error and define_fail:
            result_to_check = virsh.define(vmxml.xml, debug=True)
        else:
            vmxml.sync()

        # start the vm
        if status_error and start_fail:
            result_to_check = virsh.start(vm_name, debug=True)

        if (not status_error) or runtime_fail:
            result_to_check = virsh.start(vm_name,
                                          debug=True,
                                          ignore_status=False)
            vm.wait_for_login(timeout=start_timeout).close()

            # test vcpu cpuset in offline/online  host cpu scenario
            if check.endswith("offline_hostcpu"):
                if vm_down:
                    vm.shutdown()
                for x in offline_hostcpus.split(','):
                    if cpu.offline(x):
                        test.fail("fail to offline cpu{}".format(x))
                    logging.debug("offline host cpu {}".format(x))
                if vm_down:
                    vm.start()
                    vm.wait_for_login(timeout=start_timeout).close()
                if not status_error:
                    # online host cpu
                    if cpu.online(cputune_cpuset):
                        test.fail(
                            "fail to online cpu{}".format(cputune_cpuset))

            # run virsh vcpupin to config vcpu affinity
            if check.startswith("cputune") and (not config_xml):
                result_to_check = virsh.vcpupin(vm_name,
                                                vcpu,
                                                cputune_cpuset,
                                                debug=True)

            if check == "vcpu_placement":
                check_vcpu_placement(test, params)
            elif not status_error:
                check_vcpu_affinity()

        if 'result_to_check' in locals():
            if err_msg:
                err_msg = err_msg.split(";")
            libvirt.check_result(result_to_check, err_msg)

    finally:
        vmxml_backup.sync()

        # recovery the host cpu env
        for x in range(hostcpu_num):
            cpu.online(x)
        cmd = "echo '0-{}' > {}".format(hostcpu_num - 1, machine_cpuset_path)
        process.run(cmd, shell=True)