[libvirt] [test-API][PATCH V2] Add blockjob related test functions and cases

* repos/domain/blkstatsflags.py * repos/domain/block_iotune.py * repos/domain/block_peek.py * repos/domain/block_resize.py * repos/domain/domain_blkio.py * cases/basic_blockjob.conf V1->V2: Removed diskpath params for block_resize, this hard code disk device is not convenient for users. --- cases/basic_blockjob.conf | 83 +++++++++++++++++++++ repos/domain/blkstatsflags.py | 63 ++++++++++++++++ repos/domain/block_iotune.py | 118 ++++++++++++++++++++++++++++++ repos/domain/block_peek.py | 69 ++++++++++++++++++ repos/domain/block_resize.py | 94 ++++++++++++++++++++++++ repos/domain/domain_blkio.py | 163 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 590 insertions(+) create mode 100644 cases/basic_blockjob.conf create mode 100644 repos/domain/blkstatsflags.py create mode 100644 repos/domain/block_iotune.py create mode 100644 repos/domain/block_peek.py create mode 100644 repos/domain/block_resize.py create mode 100644 repos/domain/domain_blkio.py diff --git a/cases/basic_blockjob.conf b/cases/basic_blockjob.conf new file mode 100644 index 0000000..21332dc --- /dev/null +++ b/cases/basic_blockjob.conf @@ -0,0 +1,83 @@ +domain:install_linux_cdrom + guestname + $defaultname + guestos + $defaultos + guestarch + $defaultarch + vcpu + $defaultvcpu + memory + $defaultmem + hddriver + $defaulthd + nicdriver + $defaultnic + macaddr + 54:52:00:45:c3:8a + +domain:install_linux_check + guestname + $defaultname + virt_type + $defaulthv + hddriver + $defaulthd + nicdriver + $defaultnic + +domain:block_iotune + guestname + $defaultname + bytes_sec + 100000 + iops_sec + 0 + +domain:block_iotune + guestname + $defaultname + bytes_sec + 0 + iops_sec + 1000 + +domain:block_peek + guestname + $defaultname + +domain:block_peek + guestname + $defaultname + +domain:block_resize + guestname + $defaultname + disksize + 1G + +domain:blkstats + guestname + $defaultname + +domain:blkstatsflags + guestname + $defaultname + flags + 0 + +domain:domain_blkinfo + guestname + $defaultname + +domain:domain_blkio + guestname + $defaultname + weight + 500 + +domain:undefine + guestname + $defaultname + +options cleanup=enable diff --git a/repos/domain/blkstatsflags.py b/repos/domain/blkstatsflags.py new file mode 100644 index 0000000..4c84a18 --- /dev/null +++ b/repos/domain/blkstatsflags.py @@ -0,0 +1,63 @@ +#!/usr/bin/evn python +# To test domain block device statistics with flags + +import time +import libxml2 + +import libvirt +from libvirt import libvirtError + +from src import sharedmod + +required_params = ('guestname', 'flags') +optional_params = {} + +def check_guest_status(domobj): + """Check guest current status""" + state = domobj.info()[0] + if state == libvirt.VIR_DOMAIN_SHUTOFF or state == libvirt.VIR_DOMAIN_SHUTDOWN: + # add check function + return False + else: + return True + +def check_blkstats(): + """Check block device statistic result""" + pass + +def blkstatsflags(params): + """Domain block device statistic""" + logger = params['logger'] + guestname = params['guestname'] + flags = int(params['flags']) + + conn = sharedmod.libvirtobj['conn'] + + domobj = conn.lookupByName(guestname) + + # Check domain block status + if check_guest_status(domobj): + pass + else: + domobj.create() + time.sleep(90) + try: + xml = domobj.XMLDesc(0) + doc = libxml2.parseDoc(xml) + cont = doc.xpathNewContext() + devs = cont.xpathEval("/domain/devices/disk/target/@dev") + + for dev in devs: + path = dev.content + blkstats = domobj.blockStatsFlags(path, flags) + # check_blkstats() + logger.debug(blkstats) + for entry in blkstats.keys(): + logger.info("%s %s %s" %(path, entry, blkstats[entry])) + + except libvirtError, e: + logger.error("API error message: %s, error code is %s" + % (e.message, e.get_error_code())) + return 1 + + return 0 diff --git a/repos/domain/block_iotune.py b/repos/domain/block_iotune.py new file mode 100644 index 0000000..26e4823 --- /dev/null +++ b/repos/domain/block_iotune.py @@ -0,0 +1,118 @@ +#!/usr/bin/evn python +# To test domain block device iotune + +import time +import libxml2 +import libvirt +from libvirt import libvirtError + +from src import sharedmod + +required_params = ('guestname', 'bytes_sec', 'iops_sec') +optional_params = {} + +def check_guest_status(domobj): + """Check guest current status""" + state = domobj.info()[0] + if state == libvirt.VIR_DOMAIN_SHUTOFF or \ + state == libvirt.VIR_DOMAIN_SHUTDOWN: + # add check function + return False + else: + return True + +def prepare_block_iotune(param, wbs, rbs, tbs, wis, ris, tis, logger): + """prepare the block iotune parameter + """ + logger.info("write_bytes_sec : %s" % wbs) + param['write_bytes_sec'] = wbs + logger.info("read_bytes_sec : %s" % rbs) + param['read_bytes_sec'] = rbs + logger.info("total_bytes_sec : %s" % tbs) + param['total_bytes_sec'] = tbs + logger.info("write_iops_sec : %s" % wis) + param['write_iops_sec'] = wis + logger.info("read_iops_sec : %s" % ris) + param['read_iops_sec'] = ris + logger.info("total_iops_sec : %s\n" % tis) + param['total_iops_sec'] = tis + return 0 + +def check_iotune(expected_param, result_param): + """check block iotune configuration + """ + for k in expected_param.keys(): + if expected_param[k] != result_param[k]: + return 1 + return 0 + +def block_iotune(params): + """Domain block device iotune""" + logger = params['logger'] + guestname = params['guestname'] + bytes_sec = int(params['bytes_sec']) + iops_sec = int(params['iops_sec']) + flag = 0 + + conn = sharedmod.libvirtobj['conn'] + + domobj = conn.lookupByName(guestname) + + # Check domain block status + if check_guest_status(domobj): + pass + else: + domobj.create() + time.sleep(90) + + try: + xml = domobj.XMLDesc(0) + doc = libxml2.parseDoc(xml) + cont = doc.xpathNewContext() + vdevs = cont.xpathEval("/domain/devices/disk/target/@dev") + vdev = vdevs[0].content + + iotune_para = {'write_bytes_sec': 0L, + 'total_iops_sec': 0L, + 'read_iops_sec': 0L, + 'read_bytes_sec': 0L, + 'write_iops_sec': 0L, + 'total_bytes_sec': 0L + } + + logger.info("prepare block iotune:") + prepare_block_iotune(iotune_para, bytes_sec, bytes_sec, 0, + iops_sec, iops_sec, 0, logger) + + logger.info("start to set block iotune:") + domobj.setBlockIoTune(vdev, iotune_para, flag) + + res = domobj.blockIoTune(vdev, flag) + ret = check_iotune(iotune_para, res) + if not ret: + logger.info("set pass") + else: + logger.error("fails to set") + return 1 + + logger.info("prepare block iotune:") + prepare_block_iotune(iotune_para, 0, 0, bytes_sec, + 0, 0, iops_sec, logger) + + logger.info("start to set block iotune:") + domobj.setBlockIoTune(vdev, iotune_para, flag) + + res = domobj.blockIoTune(vdev, flag) + ret = check_iotune(iotune_para, res) + if not ret: + logger.info("set pass") + else: + logger.error("fails to set") + return 1 + + except libvirtError, e: + logger.error("API error message: %s, error code is %s" + % (e.message, e.get_error_code())) + return 1 + + return 0 diff --git a/repos/domain/block_peek.py b/repos/domain/block_peek.py new file mode 100644 index 0000000..b88668a --- /dev/null +++ b/repos/domain/block_peek.py @@ -0,0 +1,69 @@ +#!/usr/bin/evn python +# To test domain block device peek + +import time +import libxml2 +import libvirt +from libvirt import libvirtError + +from src import sharedmod + +required_params = ('guestname',) +optional_params = {} + +def check_guest_status(domobj): + """Check guest current status""" + state = domobj.info()[0] + if state == libvirt.VIR_DOMAIN_SHUTOFF or \ + state == libvirt.VIR_DOMAIN_SHUTDOWN: + # add check function + return False + else: + return True + +def block_peek(params): + """domain block peek test function + """ + logger = params['logger'] + guestname = params['guestname'] + flag = 0 + + conn = sharedmod.libvirtobj['conn'] + + domobj = conn.lookupByName(guestname) + + # Check domain block status + if check_guest_status(domobj): + pass + else: + domobj.create() + time.sleep(90) + + try: + xml = domobj.XMLDesc(0) + doc = libxml2.parseDoc(xml) + cont = doc.xpathNewContext() + vdevs = cont.xpathEval("/domain/devices/disk/target/@dev") + vdev = vdevs[0].content + + logger.info("start to test block_peek.") + logger.info("get the MBR's last byte of domain %s %s is:" + % (guestname, vdev)) + + last_byte = domobj.blockPeek(vdev, 511, 1, flag) + logger.info(last_byte) + + # compare with '\xaa' + if last_byte == '\xaa': + logger.info("Pass: the last byte is \\xaa") + else: + logger.error("Failed: the last byte is not \\xaa") + logger.error("please make sure the guest is bootable") + return 1 + + except libvirtError, e: + logger.error("API error message: %s, error code is %s" + % (e.message, e.get_error_code())) + return 1 + + return 0 diff --git a/repos/domain/block_resize.py b/repos/domain/block_resize.py new file mode 100644 index 0000000..6070c22 --- /dev/null +++ b/repos/domain/block_resize.py @@ -0,0 +1,94 @@ +#!/usr/bin/evn python +# To test domain block device resize + +import time +import libxml2 +import libvirt +from libvirt import libvirtError + +from src import sharedmod +from utils import utils + +required_params = ('guestname', 'disksize',) +optional_params = {} + +def check_guest_status(domobj): + """Check guest current status""" + state = domobj.info()[0] + if state == libvirt.VIR_DOMAIN_SHUTOFF or \ + state == libvirt.VIR_DOMAIN_SHUTDOWN: + # add check function + return False + else: + return True + +def block_resize(params): + """domain block resize test function + """ + logger = params['logger'] + guestname = params['guestname'] + disksize = params['disksize'] + flag = 0 + + out = utils.get_capacity_suffix_size(disksize) + if len(out) == 0: + logger.error("disksize parse error: \'%s\'" % disksize) + logger.error("disksize should be a number with capacity suffix") + return 1 + + if out['suffix'] == 'K': + flag = 0 + disksize = long(out['capacity']) + elif out['suffix'] == 'B': + flag = 1 + disksize = long(out['capacity_byte']) + elif out['suffix'] == 'M': + flag = 0 + disksize = long(out['capacity']) * 1024 + elif out['suffix'] == 'G': + flag = 0 + disksize = long(out['capacity']) * 1024 * 1024 + else: + logger.error("disksize parse error: with a unsupported suffix \'%s\'" + % out['suffix']) + logger.error("the available disksize suffix of block_resize is: ") + logger.error("B, K, M, G, T") + return 1 + + conn = sharedmod.libvirtobj['conn'] + + domobj = conn.lookupByName(guestname) + + xml = domobj.XMLDesc(0) + doc = libxml2.parseDoc(xml) + cont = doc.xpathNewContext() + vdevs = cont.xpathEval("/domain/devices/disk/source/@file") + diskpath = vdevs[0].content + logger.info("the disk is %s" % diskpath) + + # Check domain block status + if check_guest_status(domobj): + pass + else: + domobj.create() + time.sleep(90) + + try: + logger.info("resize domain disk to %s" % disksize) + domobj.blockResize(diskpath, disksize, flag) + + # Currently, the units of disksize which get from blockInfo is byte. + block_info = domobj.blockInfo(diskpath, 0) + + if block_info[0] == disksize * (1 + 1023 * (1 - flag)): + logger.info("domain disk resize success") + else: + logger.error("error: domain disk change into %s" % block_info[0]) + return 1 + + except libvirtError, e: + logger.error("API error message: %s, error code is %s" + % (e.message, e.get_error_code())) + return 1 + + return 0 diff --git a/repos/domain/domain_blkio.py b/repos/domain/domain_blkio.py new file mode 100644 index 0000000..f1c637d --- /dev/null +++ b/repos/domain/domain_blkio.py @@ -0,0 +1,163 @@ +#!/usr/bin/evn python +# To test domain blkio parameters + +import os +import time +import libxml2 +import libvirt +import commands +from libvirt import libvirtError + +from src import sharedmod + +CGROUP_PATH = "/cgroup" +BLKIO_PATH1 = "%s/blkio/libvirt/qemu/%s" +BLKIO_PATH2 = "/sys/fs%s/blkio/machine/%s.libvirt-qemu" +GET_PARTITION = "df -P %s | tail -1 | awk {'print $1'}" + +required_params = ('guestname', 'weight',) +optional_params = {} + +def get_output(command, logger): + """execute shell command + """ + status, ret = commands.getstatusoutput(command) + if status: + logger.error("executing "+ "\"" + command + "\"" + " failed") + logger.error(ret) + return status, ret + +def get_device(domobj, logger): + """get the disk device which domain image stored in + """ + xml = domobj.XMLDesc(0) + doc = libxml2.parseDoc(xml) + cont = doc.xpathNewContext() + devs = cont.xpathEval("/domain/devices/disk/source/@file") + image_file = devs[0].content + + status, output = get_output(GET_PARTITION % image_file, logger) + if not status: + return output[:-1] + else: + logger.error("get device error: ") + logger.error(GET_PARTITION % image_file) + return "" + +def check_blkio_paras(domain_blkio_path, domainname, blkio_paras, logger): + """check blkio parameters according to cgroup filesystem + """ + logger.info("checking blkio parameters from cgroup") + if 'weight' in blkio_paras: + expected_weight = blkio_paras['weight'] + status, output = get_output("cat %s/blkio.weight" + % domain_blkio_path, logger) + if not status: + logger.info("%s/blkio.weight is \"%s\"" + % (domain_blkio_path, output)) + else: + return 1 + + if int(output) == expected_weight: + logger.info("the weight matches with cgroup blkio.weight") + return 0 + else: + logger.error("the weight mismatches with cgroup blkio.weight") + return 1 + + if 'device_weight' in blkio_paras: + expected_device_weight = blkio_paras['device_weight'] + status, output = get_output("cat %s/blkio.weight_device" + % domain_blkio_path, logger) + if not status: + logger.info("%s/blkio.weight_device is \"%s\"" + % (domain_blkio_path, output)) + else: + return 1 + + if output.split(' ')[1] == expected_device_weight.split(',')[1]: + logger.info("the device_weight matches with cgroup \ + blkio.weight_device") + return 0 + else: + logger.error("the device_weight mismatches with cgroup \ + blkio.weight_device") + return 1 + + return 0 + +def check_guest_status(domobj): + """Check guest current status""" + state = domobj.info()[0] + if state == libvirt.VIR_DOMAIN_SHUTOFF or \ + state == libvirt.VIR_DOMAIN_SHUTDOWN: + # add check function + return False + else: + return True + +def domain_blkio(params): + """domain blkio parameters test function""" + logger = params['logger'] + guestname = params['guestname'] + expected_weight = params['weight'] + flag = 0 + + conn = sharedmod.libvirtobj['conn'] + + domobj = conn.lookupByName(guestname) + + # Check domain block status + if check_guest_status(domobj): + pass + else: + domobj.create() + time.sleep(90) + + if os.path.exists(CGROUP_PATH): + blkio_path = BLKIO_PATH1 % (CGROUP_PATH, guestname) + else: + blkio_path = BLKIO_PATH2 % (CGROUP_PATH, guestname) + + try: + blkio_paras = domobj.blkioParameters(flag) + + logger.info("the blkio weight of %s is: %d" + % (guestname, blkio_paras['weight'])) + + status = check_blkio_paras(blkio_path, guestname, blkio_paras, + logger) + if status != 0: + return 1 + + logger.info("start to set param weight to %s" % expected_weight) + blkio_paras = {'weight':int(expected_weight)} + status = domobj.setBlkioParameters(blkio_paras, flag) + if status != 0: + return 1 + + status = check_blkio_paras(blkio_path, guestname, blkio_paras, + logger) + if status != 0: + return 1 + + device = get_device(domobj, logger) + device_weight = "%s,%s" % (device, expected_weight) + logger.info("start to set param device_weight to %s" + % device_weight) + blkio_paras = {'device_weight':device_weight} + status = domobj.setBlkioParameters(blkio_paras, flag) + if status != 0: + return 1 + + status = check_blkio_paras(blkio_path, guestname, blkio_paras, + logger) + if status != 0: + return 1 + + except libvirtError, e: + logger.error("API error message: %s, error code is %s" + % (e.message, e.get_error_code())) + return 1 + + return 0 -- 1.8.3.1

On 2013年11月27日 10:56, Jincheng Miao wrote:
* repos/domain/blkstatsflags.py * repos/domain/block_iotune.py * repos/domain/block_peek.py * repos/domain/block_resize.py * repos/domain/domain_blkio.py * cases/basic_blockjob.conf
V1->V2: Removed diskpath params for block_resize, this hard code disk device is not convenient for users.
--- cases/basic_blockjob.conf | 83 +++++++++++++++++++++ repos/domain/blkstatsflags.py | 63 ++++++++++++++++ repos/domain/block_iotune.py | 118 ++++++++++++++++++++++++++++++ repos/domain/block_peek.py | 69 ++++++++++++++++++ repos/domain/block_resize.py | 94 ++++++++++++++++++++++++ repos/domain/domain_blkio.py | 163 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 590 insertions(+) create mode 100644 cases/basic_blockjob.conf create mode 100644 repos/domain/blkstatsflags.py create mode 100644 repos/domain/block_iotune.py create mode 100644 repos/domain/block_peek.py create mode 100644 repos/domain/block_resize.py create mode 100644 repos/domain/domain_blkio.py
diff --git a/cases/basic_blockjob.conf b/cases/basic_blockjob.conf new file mode 100644 index 0000000..21332dc --- /dev/null +++ b/cases/basic_blockjob.conf @@ -0,0 +1,83 @@ +domain:install_linux_cdrom + guestname + $defaultname + guestos + $defaultos + guestarch + $defaultarch + vcpu + $defaultvcpu + memory + $defaultmem + hddriver + $defaulthd + nicdriver + $defaultnic + macaddr + 54:52:00:45:c3:8a + +domain:install_linux_check + guestname + $defaultname + virt_type + $defaulthv + hddriver + $defaulthd + nicdriver + $defaultnic + +domain:block_iotune + guestname + $defaultname + bytes_sec + 100000 + iops_sec + 0 + +domain:block_iotune + guestname + $defaultname + bytes_sec + 0 + iops_sec + 1000 + +domain:block_peek + guestname + $defaultname + +domain:block_peek + guestname + $defaultname + +domain:block_resize + guestname + $defaultname + disksize + 1G + +domain:blkstats + guestname + $defaultname + +domain:blkstatsflags + guestname + $defaultname + flags + 0 + +domain:domain_blkinfo + guestname + $defaultname
The domain:domain_blkinfo testcase failed to be run. error is: Parameter blockdev is required Guannan

On 2013年11月28日 13:25, Guannan Ren wrote:
On 2013年11月27日 10:56, Jincheng Miao wrote:
* repos/domain/blkstatsflags.py * repos/domain/block_iotune.py * repos/domain/block_peek.py * repos/domain/block_resize.py * repos/domain/domain_blkio.py * cases/basic_blockjob.conf
V1->V2: Removed diskpath params for block_resize, this hard code disk device is not convenient for users.
--- cases/basic_blockjob.conf | 83 +++++++++++++++++++++ repos/domain/blkstatsflags.py | 63 ++++++++++++++++ repos/domain/block_iotune.py | 118 ++++++++++++++++++++++++++++++ repos/domain/block_peek.py | 69 ++++++++++++++++++ repos/domain/block_resize.py | 94 ++++++++++++++++++++++++ repos/domain/domain_blkio.py | 163 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 590 insertions(+) create mode 100644 cases/basic_blockjob.conf create mode 100644 repos/domain/blkstatsflags.py create mode 100644 repos/domain/block_iotune.py create mode 100644 repos/domain/block_peek.py create mode 100644 repos/domain/block_resize.py create mode 100644 repos/domain/domain_blkio.py
diff --git a/cases/basic_blockjob.conf b/cases/basic_blockjob.conf new file mode 100644 index 0000000..21332dc --- /dev/null +++ b/cases/basic_blockjob.conf @@ -0,0 +1,83 @@ +domain:install_linux_cdrom + guestname + $defaultname + guestos + $defaultos + guestarch + $defaultarch + vcpu + $defaultvcpu + memory + $defaultmem + hddriver + $defaulthd + nicdriver + $defaultnic + macaddr + 54:52:00:45:c3:8a + +domain:install_linux_check + guestname + $defaultname + virt_type + $defaulthv + hddriver + $defaulthd + nicdriver + $defaultnic + +domain:block_iotune + guestname + $defaultname + bytes_sec + 100000 + iops_sec + 0 + +domain:block_iotune + guestname + $defaultname + bytes_sec + 0 + iops_sec + 1000 + +domain:block_peek + guestname + $defaultname + +domain:block_peek + guestname + $defaultname + +domain:block_resize + guestname + $defaultname + disksize + 1G + +domain:blkstats + guestname + $defaultname + +domain:blkstatsflags + guestname + $defaultname + flags + 0 + +domain:domain_blkinfo + guestname + $defaultname
The domain:domain_blkinfo testcase failed to be run. error is: Parameter blockdev is require
I know the reason, the fix to the issue can be found in another patch. One thing you should notice, every patch should not break the running of existed testcases. If this patch is based on other patch. you should send the two patches in a set. Guannan

----- Original Message -----
I know the reason, the fix to the issue can be found in another patch. One thing you should notice, every patch should not break the running of existed testcases. If this patch is based on other patch. you should send the two patches in a set.
OK, I will send a V3 patch set includes these two patches. Thanks for your review.
Guannan
participants (2)
-
Guannan Ren
-
Jincheng Miao