[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