* 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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list