Add: * 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 Modify: replace virsh commands to calling api in test function * repos/domain/blkstats.py * repos/domain/domain_blkinfo.py --- cases/basic_blockjob.conf | 87 ++++++++++++++++++++++ repos/domain/blkstats.py | 2 - repos/domain/blkstatsflags.py | 63 ++++++++++++++++ repos/domain/block_iotune.py | 118 +++++++++++++++++++++++++++++ repos/domain/block_peek.py | 69 +++++++++++++++++ repos/domain/block_resize.py | 88 ++++++++++++++++++++++ repos/domain/domain_blkinfo.py | 87 ++++++++++++---------- repos/domain/domain_blkio.py | 165 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 639 insertions(+), 40 deletions(-) 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..65af2c3 --- /dev/null +++ b/cases/basic_blockjob.conf @@ -0,0 +1,87 @@ +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 + diskpath + /var/lib/libvirt/images/libvirt-test-api + disksize + 1G + +domain:blkstats + guestname + $defaultname + +domain:blkstatsflags + guestname + $defaultname + flags + 0 + +domain:domain_blkinfo + guestname + $defaultname + blockdev + /var/lib/libvirt/images/libvirt-test-api + +domain:domain_blkio + guestname + $defaultname + weight + 500 + +domain:undefine + guestname + $defaultname + +options cleanup=enable diff --git a/repos/domain/blkstats.py b/repos/domain/blkstats.py index 0254922..27c2a46 100644 --- a/repos/domain/blkstats.py +++ b/repos/domain/blkstats.py @@ -1,8 +1,6 @@ #!/usr/bin/evn python # To test domain block device statistics -import os -import sys import time import libxml2 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..f92eaf6 --- /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 \ No newline at end of file diff --git a/repos/domain/block_peek.py b/repos/domain/block_peek.py new file mode 100644 index 0000000..f159f48 --- /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 \ No newline at end of file diff --git a/repos/domain/block_resize.py b/repos/domain/block_resize.py new file mode 100644 index 0000000..1dc4b45 --- /dev/null +++ b/repos/domain/block_resize.py @@ -0,0 +1,88 @@ +#!/usr/bin/evn python +# To test domain block device resize + +import time +import libvirt +from libvirt import libvirtError + +from src import sharedmod +from utils import utils + +required_params = ('guestname', 'diskpath', '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'] + diskpath = params['diskpath'] + 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) + + # 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 + \ No newline at end of file diff --git a/repos/domain/domain_blkinfo.py b/repos/domain/domain_blkinfo.py index b6051aa..4978c32 100644 --- a/repos/domain/domain_blkinfo.py +++ b/repos/domain/domain_blkinfo.py @@ -1,9 +1,6 @@ #!/usr/bin/env python -# To test "virsh domblkinfo" command +# To test domain's blockkinfo API -import os -import sys -import re import commands import libvirt @@ -11,10 +8,8 @@ from libvirt import libvirtError from src import sharedmod -GET_DOMBLKINFO_MAC = "virsh domblkinfo %s %s | awk '{print $2}'" GET_CAPACITY = "du -b %s | awk '{print $1}'" GET_PHYSICAL_K = " du -B K %s | awk '{print $1}'" -VIRSH_DOMBLKINFO = "virsh domblkinfo %s %s" required_params = ('guestname', 'blockdev',) optional_params = {} @@ -32,8 +27,8 @@ def check_domain_exists(conn, guestname, logger): """ check if the domain exists, may or may not be active """ guest_names = [] ids = conn.listDomainsID() - for id in ids: - obj = conn.lookupByID(id) + for domain_id in ids: + obj = conn.lookupByID(domain_id) guest_names.append(obj.name()) guest_names += conn.listDefinedDomains() @@ -43,18 +38,28 @@ def check_domain_exists(conn, guestname, logger): return False else: return True + +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_block_data(blockdev, blkdata, logger): """ check data about capacity,allocation,physical """ status, apparent_size = get_output(GET_CAPACITY % blockdev, logger) if not status: - if apparent_size == blkdata[0]: - logger.info("the capacity of '%s' is %s, checking succeeded" % \ - (blockdev, apparent_size)) + if apparent_size == str(blkdata[0]): + logger.info("the capacity of '%s' is %s, checking succeeded" + % (blockdev, apparent_size)) else: - logger.error("apparent-size from 'du' is %s, \n\ - but from 'domblkinfo' is %s, checking failed" % \ - (apparent_size, blkdata[0])) + logger.error("apparent-size from 'du' is %s" % apparent_size) + logger.error("but from 'domain blockinfo' is %d, checking failed" + % blkdata[0]) return 1 else: return 1 @@ -64,14 +69,15 @@ def check_block_data(blockdev, blkdata, logger): block_size_b = int(block_size_k[:-1]) * 1024 # Temporarily, we only test the default case, assuming # Allocation value is equal to Physical value - if str(block_size_b) == blkdata[1] and str(block_size_b) == blkdata[2]: - logger.info("the block size of '%s' is %s, same with \n\ - Allocation and Physical value, checking succeeded" % \ - (blockdev, block_size_b)) + if block_size_b == blkdata[1] and block_size_b == blkdata[2]: + logger.info("the block size of '%s' is %s" + % (blockdev, block_size_b)) + logger.info("Allocation and Physical value's checking succeeded") else: - logger.error("the block size from 'du' is %s, \n\ - the Allocation value is %s, Physical value is %s, \n\ - checking failed" % (block_size_b, blkdata[1], blkdata[2])) + logger.error("the block size from 'du' is %d" % block_size_b) + logger.error("the Allocation value is %d, Physical value is %d" + % (blkdata[1], blkdata[2])) + logger.error("checking failed") return 1 return 0 @@ -79,7 +85,7 @@ def check_block_data(blockdev, blkdata, logger): def domain_blkinfo(params): """ using du command to check the data - in the output of virsh domblkinfo + in the output of API blockinfo """ logger = params['logger'] guestname = params.get('guestname') @@ -93,24 +99,29 @@ def domain_blkinfo(params): if not check_domain_exists(conn, guestname, logger): logger.error("need a defined guest") return 1 - - logger.info("the output of virsh domblkinfo is:") - status, output = get_output(VIRSH_DOMBLKINFO % (guestname, blockdev), logger) - if not status: - logger.info("\n" + output) - else: + + domobj = conn.lookupByName(guestname) + + if not check_guest_status(domobj): + logger.error("guest is not started.") return 1 - - status, data_str = get_output(GET_DOMBLKINFO_MAC % (guestname, blockdev), logger) - if not status: - blkdata = data_str.rstrip().split('\n') - logger.info("capacity,allocation,physical list: %s" % blkdata) - else: + + try: + logger.info("the output of domain blockinfo is:") + block_info = domobj.blockInfo(blockdev, 0) + logger.info("Capacity : %d " % block_info[0]) + logger.info("Allocation: %d " % block_info[1]) + logger.info("Physical : %d " % block_info[2]) + + except libvirtError, e: + logger.error("API error message: %s, error code is %s" + % (e.message, e.get_error_code())) return 1 - - if check_block_data(blockdev, blkdata, logger): - logger.error("checking domblkinfo data FAILED") + + if check_block_data(blockdev, block_info, logger): + logger.error("checking domain blockinfo data FAILED") return 1 else: - logger.info("checking domblkinfo data SUCCEEDED") + logger.info("checking domain blockinfo data SUCCEEDED") + return 0 diff --git a/repos/domain/domain_blkio.py b/repos/domain/domain_blkio.py new file mode 100644 index 0000000..2603113 --- /dev/null +++ b/repos/domain/domain_blkio.py @@ -0,0 +1,165 @@ +#!/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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list