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

Wayne Sun gsun at redhat.com
Fri Dec 14 03:57:43 UTC 2012


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)
-- 
1.7.1




More information about the libvir-list mailing list