* 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
Signed-off-by: Wayne Sun <gsun(a)redhat.com>
---
cases/vcpupin.conf | 67 +++++++++++++++
repos/setVcpus/vcpupin_config.py | 174 ++++++++++++++++++++++++++++++++++++++
repos/setVcpus/vcpupin_live.py | 166 ++++++++++++++++++++++++++++++++++++
3 files changed, 407 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..12d9598
--- /dev/null
+++ b/repos/setVcpus/vcpupin_config.py
@@ -0,0 +1,174 @@
+#!/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 = get_cpumap(cpulist)
+
+ 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 format_cpumap(cpulist, cpumap_test):
+ """ format cpumap base on cpulist
+ """
+ cpumap = ()
+
+ try:
+ if re.match('\^', cpulist):
+ unuse = int(re.split('\^', cpulist)[1])
+ for i in range(maxcpu):
+ if i == unuse:
+ cpumap += (False,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ elif '-' in cpulist:
+ cpu_list = re.split('-', cpulist)
+ if not len(cpu_list) == 2:
+ return False
+ if not int(cpu_list[1]) < maxcpu:
+ logger.error("cpulist: out of host cpu range")
+ return False
+ if int(cpu_list[1]) < int(cpu_list[0]):
+ return False
+
+ for i in range(maxcpu):
+ if i in range(int(cpu_list[0]), int(cpu_list[1])+1):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ else:
+ for i in range(maxcpu):
+ if i == int(cpulist):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ return cpumap
+ except ValueError, e:
+ logger.error("ValueError: " + str(e))
+ return False
+
+def get_cpumap(cpulist):
+ """get cpumap base on given cpulist
+ """
+ cpumap_test = ()
+ for i in range(maxcpu):
+ cpumap_test += (False,)
+
+ if ',' in cpulist:
+ cpu_list = re.split(',', cpulist)
+ for i in range(len(cpu_list)):
+ cpumap = format_cpumap(cpu_list[i], cpumap_test)
+ if cpumap:
+ cpumap_test = cpumap
+ else:
+ return False
+ return cpumap
+
+ else:
+ cpumap = format_cpumap(cpulist, cpumap_test)
+ if cpumap:
+ return cpumap
+ else:
+ return False
+
+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 = get_cpumap(cpulist)
+ 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..09744a5
--- /dev/null
+++ b/repos/setVcpus/vcpupin_live.py
@@ -0,0 +1,166 @@
+#!/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 = get_cpumap(cpulist)
+ 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 format_cpumap(cpulist, cpumap_test):
+ """ format cpumap base on cpulist
+ """
+ cpumap = ()
+
+ try:
+ if re.match('\^', cpulist):
+ unuse = int(re.split('\^', cpulist)[1])
+ for i in range(maxcpu):
+ if i == unuse:
+ cpumap += (False,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ elif '-' in cpulist:
+ cpu_list = re.split('-', cpulist)
+ if not len(cpu_list) == 2:
+ return False
+ if not int(cpu_list[1]) < maxcpu:
+ logger.error("cpulist: out of host cpu range")
+ return False
+ if int(cpu_list[1]) < int(cpu_list[0]):
+ return False
+
+ for i in range(maxcpu):
+ if i in range(int(cpu_list[0]), int(cpu_list[1])+1):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ else:
+ for i in range(maxcpu):
+ if i == int(cpulist):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ return cpumap
+ except ValueError, e:
+ logger.error("ValueError: " + str(e))
+ return False
+
+def get_cpumap(cpulist):
+ """get cpumap base on given cpulist
+ """
+ cpumap_test = ()
+ for i in range(maxcpu):
+ cpumap_test += (False,)
+
+ if ',' in cpulist:
+ cpu_list = re.split(',', cpulist)
+ for i in range(len(cpu_list)):
+ cpumap = format_cpumap(cpu_list[i], cpumap_test)
+ if cpumap:
+ cpumap_test = cpumap
+ else:
+ return False
+ return cpumap
+
+ else:
+ cpumap = format_cpumap(cpulist, cpumap_test)
+ if cpumap:
+ return cpumap
+ else:
+ return False
+
+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 = get_cpumap(cpulist)
+ 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
--
1.7.1