[libvirt] [test-API][PATCH v2] Add 2 vcpupin cases cover config and live flags

Guannan Ren gren at redhat.com
Fri Dec 14 07:13:46 UTC 2012


On 12/14/2012 11:57 AM, Wayne Sun wrote:
> v1: add 2 vcpupin cases
> * use pinVcpuFlags to pin domain vcpu to host cpu
> * 2 cases cover config and live flags
> * cpulist with '^', '-' and ',' is supported to give multiple
>    host cpus
> * vcpus and vcpuPinInfo are used as part of the checking
> * a sample conf is added
>
> v2: move format cpulist functions to utils
> * the format cpulist functions could be reused for cases need
>    parse param with '-', '^' and ','.
>
> Signed-off-by: Wayne Sun <gsun at redhat.com>
> ---
>   cases/vcpupin.conf               |   67 +++++++++++++++++++++++
>   repos/setVcpus/vcpupin_config.py |  109 ++++++++++++++++++++++++++++++++++++++
>   repos/setVcpus/vcpupin_live.py   |  101 +++++++++++++++++++++++++++++++++++
>   utils/utils.py                   |   71 ++++++++++++++++++++++++
>   4 files changed, 348 insertions(+), 0 deletions(-)
>   create mode 100644 cases/vcpupin.conf
>   create mode 100644 repos/setVcpus/vcpupin_config.py
>   create mode 100644 repos/setVcpus/vcpupin_live.py
>
> diff --git a/cases/vcpupin.conf b/cases/vcpupin.conf
> new file mode 100644
> index 0000000..880247f
> --- /dev/null
> +++ b/cases/vcpupin.conf
> @@ -0,0 +1,67 @@
> +domain:install_linux_cdrom
> +    guestname
> +        $defaultname
> +    guestos
> +        $defaultos
> +    guestarch
> +        $defaultarch
> +    vcpu
> +        4
> +    memory
> +        $defaultmem
> +    hddriver
> +        $defaulthd
> +    nicdriver
> +        $defaultnic
> +    imageformat
> +        qcow2
> +
> +setVcpus:vcpupin_live
> +    guestname
> +        $defaultname
> +    vcpu
> +        0
> +    cpulist
> +        2,4-6,^4
> +
> +setVcpus:vcpupin_live
> +    guestname
> +        $defaultname
> +    vcpu
> +        1
> +    cpulist
> +        3
> +
> +domain:destroy
> +    guestname
> +        $defaultname
> +
> +setVcpus:vcpupin_config
> +    guestname
> +        $defaultname
> +    vcpu
> +        2
> +    cpulist
> +        0-8,^1
> +
> +setVcpus:vcpupin_config
> +    guestname
> +        $defaultname
> +    vcpu
> +        3
> +    cpulist
> +        ^2,0-8
> +
> +domain:start
> +    guestname
> +        $defaultname
> +
> +domain:destroy
> +    guestname
> +        $defaultname
> +
> +domain:undefine
> +    guestname
> +        $defaultname
> +
> +options cleanup=enable
> diff --git a/repos/setVcpus/vcpupin_config.py b/repos/setVcpus/vcpupin_config.py
> new file mode 100644
> index 0000000..80df659
> --- /dev/null
> +++ b/repos/setVcpus/vcpupin_config.py
> @@ -0,0 +1,109 @@
> +#!/usr/bin/env python
> +# Test domain vcpu pin with flag VIR_DOMAIN_AFFECT_CONFIG, check
> +# domain config xml with vcpupin configuration.
> +
> +import re
> +from xml.dom import minidom
> +
> +import libvirt
> +from libvirt import libvirtError
> +
> +from src import sharedmod
> +from utils import utils
> +
> +required_params = ('guestname', 'vcpu', 'cpulist',)
> +optional_params = {}
> +
> +def vcpupin_check(domobj, vcpu, cpumap):
> +    """check domain config xml with vcpupin element
> +    """
> +    guestxml = domobj.XMLDesc(2)
> +    logger.debug("domain %s xml :\n%s" %(domobj.name(), guestxml))
> +
> +    doc = minidom.parseString(guestxml)
> +    vcpupin = doc.getElementsByTagName('vcpupin')
> +    if not vcpupin:
> +        logger.error("no vcpupin element in domain xml")
> +        return 1
> +
> +    for i in range(len(vcpupin)):
> +        if vcpupin[i].hasAttribute('vcpu') and \
> +           vcpupin[i].hasAttribute('cpuset'):
> +            vcpu_attr = vcpupin[i].getAttributeNode('vcpu')
> +            cpu_attr = vcpupin[i].getAttributeNode('cpuset')
> +            if int(vcpu_attr.nodeValue) == vcpu:
> +                cpulist = cpu_attr.nodeValue
> +                if cpulist == '':
> +                    cpumap_tmp = ()
> +                    for i in range(maxcpu):
> +                        cpumap_tmp += (False,)
> +                else:
> +                    cpumap_tmp = utils.param_to_tuple(cpulist, maxcpu)
> +
> +                if cpumap_tmp == cpumap:
> +                    logger.info("cpuset is as expected in domain xml")
> +                    return 0
> +                else:
> +                    logger.error("cpuset is not as expected in domain xml")
> +                    return 1
> +
> +        if i == len(vcpupin) - 1:
> +            logger.error("the vcpupin element with given vcpu is not found")
> +            return 1
> +
> +def vcpupin_config(params):
> +    """pin domain vcpu to host cpu with config flag
> +    """
> +    global logger
> +    logger = params['logger']
> +    params.pop('logger')
> +    guestname = params['guestname']
> +    vcpu = int(params['vcpu'])
> +    cpulist = params['cpulist']
> +
> +    logger.info("the name of virtual machine is %s" % guestname)
> +    logger.info("the given vcpu is %s" % vcpu)
> +    logger.info("the given cpulist is %s" % cpulist)
> +
> +    global maxcpu
> +    maxcpu = utils.get_host_cpus()
> +    logger.info("%s physical cpu on host" % maxcpu)
> +
> +    conn = sharedmod.libvirtobj['conn']
> +
> +    try:
> +        domobj = conn.lookupByName(guestname)
> +        cpumap = utils.param_to_tuple(cpulist, maxcpu)
> +
> +        if not cpumap:
> +            logger.error("cpulist: Invalid format")
> +            return 1
> +
> +        logger.debug("cpumap for vcpu pin is:")
> +        logger.debug(cpumap)
> +
> +        logger.info("pin domain vcpu %s to host cpulist %s with flag: %s" %
> +                    (vcpu, cpulist, libvirt.VIR_DOMAIN_AFFECT_CONFIG))
> +        domobj.pinVcpuFlags(vcpu, cpumap, libvirt.VIR_DOMAIN_AFFECT_CONFIG)
> +
> +        logger.info("check vcpu pin info")
> +        ret = domobj.vcpuPinInfo(libvirt.VIR_DOMAIN_AFFECT_CONFIG)
> +        logger.debug("vcpu pin info is:")
> +        logger.debug(ret)
> +        if ret[vcpu] == cpumap:
> +            logger.info("vcpu pin info is expected")
> +        else:
> +            logger.error("vcpu pin info is not expected")
> +            return 1
> +    except libvirtError, e:
> +        logger.error("libvirt call failed: " + str(e))
> +        return 1
> +
> +    logger.info("check domain vcpupin configuration in xml")
> +    ret = vcpupin_check(domobj, vcpu, cpumap)
> +    if ret:
> +        logger.error("domain vcpu pin check failed")
> +        return 1
> +    else:
> +        logger.info("domain vcpu pin check succeed")
> +        return 0
> diff --git a/repos/setVcpus/vcpupin_live.py b/repos/setVcpus/vcpupin_live.py
> new file mode 100644
> index 0000000..c3dfe8e
> --- /dev/null
> +++ b/repos/setVcpus/vcpupin_live.py
> @@ -0,0 +1,101 @@
> +#!/usr/bin/env python
> +# Test domain vcpu pin with flag VIR_DOMAIN_AFFECT_LIVE, check
> +# vcpu subprocess status under domain task list on host.
> +
> +import re
> +
> +import libvirt
> +from libvirt import libvirtError
> +
> +from src import sharedmod
> +from utils import utils
> +
> +required_params = ('guestname', 'vcpu', 'cpulist',)
> +optional_params = {}
> +
> +def vcpupin_check(guestname, vcpu, cpumap):
> +    """check vcpu subprocess status of the running virtual machine
> +       grep Cpus_allowed_list /proc/PID/task/*/status
> +    """
> +    tmp_str = ''
> +    cmd = "cat /var/run/libvirt/qemu/%s.pid" % guestname
> +    status, pid = utils.exec_cmd(cmd, shell=True)
> +    if status:
> +        logger.error("failed to get the pid of domain %s" % guestname)
> +        return 1
> +
> +    cmd = "grep Cpus_allowed_list /proc/%s/task/*/status" % pid[0]
> +    status, output = utils.exec_cmd(cmd, shell=True)
> +    logger.debug("command '%s' output is:" % cmd)
> +    for i in range(len(output)):
> +        tmp_str += ''.join(output[i]) + '\n'
> +    logger.debug(tmp_str)
> +
> +    task_list = output[1:]
> +    vcpu_task = task_list[int(vcpu)]
> +    cpulist = vcpu_task.split('\t')[1]
> +    ret = utils.param_to_tuple(cpulist, maxcpu)
> +
> +    if ret == cpumap:
> +        logger.info("vcpu process cpus allowed list is expected")
> +        return 0
> +    else:
> +        logger.error("vcpu process cpus allowed list is not expected")
> +        return 1
> +
> +def vcpupin_live(params):
> +    """pin domain vcpu to host cpu with live flag
> +    """
> +    global logger
> +    logger = params['logger']
> +    params.pop('logger')
> +    guestname = params['guestname']
> +    vcpu = int(params['vcpu'])
> +    cpulist = params['cpulist']
> +
> +    logger.info("the name of virtual machine is %s" % guestname)
> +    logger.info("the given vcpu is %s" % vcpu)
> +    logger.info("the given cpulist is %s" % cpulist)
> +
> +    global maxcpu
> +    maxcpu = utils.get_host_cpus()
> +    logger.info("%s physical cpu on host" % maxcpu)
> +
> +    conn = sharedmod.libvirtobj['conn']
> +
> +    try:
> +        domobj = conn.lookupByName(guestname)
> +        cpumap = utils.param_to_tuple(cpulist, maxcpu)
> +        if not cpumap:
> +            logger.error("cpulist: Invalid format")
> +            return 1
> +
> +        logger.debug("cpumap for vcpu pin is:")
> +        logger.debug(cpumap)
> +
> +        logger.info("pin domain vcpu %s to host cpu %s with flag: %s" %
> +                    (vcpu, cpulist, libvirt.VIR_DOMAIN_AFFECT_LIVE))
> +        domobj.pinVcpuFlags(vcpu, cpumap, libvirt.VIR_DOMAIN_AFFECT_LIVE)
> +
> +        logger.info("check vcpus info")
> +        ret = domobj.vcpus()
> +        logger.debug("vcpus info is:")
> +        logger.debug(ret)
> +        if ret[1][vcpu] == cpumap:
> +            logger.info("vcpus info is expected")
> +        else:
> +            logger.error("vcpus info is not expected")
> +            return 1
> +
> +    except libvirtError, e:
> +        logger.error("libvirt call failed: " + str(e))
> +        return 1
> +
> +    logger.info("check vcpu pin status on host")
> +    ret = vcpupin_check(guestname, vcpu, cpumap)
> +    if ret:
> +        logger.error("domain vcpu pin failed")
> +        return 1
> +    else:
> +        logger.info("domain vcpu pin succeed")
> +        return 0
> diff --git a/utils/utils.py b/utils/utils.py
> index e242847..36171cf 100644
> --- a/utils/utils.py
> +++ b/utils/utils.py
> @@ -645,6 +645,77 @@ def run_mount_app(hostname, username, password,
>           print "mount fail"
>           return 1
>   
> +def format_parammap(paramlist, map_test, length):
> +    """paramlist contains numbers which can be divided by '-', '^' and
> +       ',', map_test is a tuple for getting it's content (True or False)
> +       and form the new tuple base on numbers in paramlist, length is
> +       the length of the return tuple
> +    """
> +    parammap = ()
> +
> +    try:
> +        if re.match('\^', paramlist):
> +            unuse = int(re.split('\^', paramlist)[1])
> +            for i in range(length):
> +                if i == unuse:
> +                    parammap += (False,)
> +                else:
> +                    parammap += (map_test[i],)
> +
> +        elif '-' in paramlist:
> +            param = re.split('-', paramlist)
> +            if not len(param) == 2:
> +                return False
> +            if not int(param[1]) < length:
> +                print "paramlist: out of max range"
> +                return False
> +            if int(param[1]) < int(param[0]):
> +                return False
> +
> +            for i in range(length):
> +                if i in range(int(param[0]), int(param[1])+1):
> +                    parammap += (True,)
> +                else:
> +                    parammap += (map_test[i],)
> +
> +        else:
> +            for i in range(length):
> +                if i == int(paramlist):
> +                    parammap += (True,)
> +                else:
> +                    parammap += (map_test[i],)
> +
> +        return parammap
> +    except ValueError, e:
> +        print "ValueError: " + str(e)
> +        return False
> +
> +def param_to_tuple(paramlist, length):
> +    """paramlist contains numbers which can be divided by '-', '^' and
> +       ',', length is the length of the return tuple, return tuple only
> +       have True or False value
> +    """
> +    map_test = ()
> +    for i in range(length):
> +        map_test += (False,)
> +
> +    if ',' in paramlist:
> +        param = re.split(',', paramlist)
> +        for i in range(len(param)):
> +            parammap = format_parammap(param[i], map_test, length)
> +            if parammap:
> +                map_test = parammap
> +            else:
> +                return False
> +        return parammap
> +
> +    else:
> +        parammap = format_parammap(paramlist, map_test, length)
> +        if parammap:
> +            return parammap
> +        else:
> +            return False
> +
>   def run_wget_app(hostname, username, password, file_url, logger):
>       """Simple test for wget app on specified host"""
>       cmd_line = "wget -P /tmp %s -o /tmp/wget.log" % (file_url)

    ACK and pushed.
    Thanks

    Guannan




More information about the libvir-list mailing list