[libvirt] [libvirt-test-API][PATCH 2/2] Add connection_getAllDomainStats test case

hongming honzhang at redhat.com
Wed Mar 11 09:14:25 UTC 2015


Hi jiahu

Please add the following api calling to your case, we can test them 
using the same checking methods .

def domainListGetStats(self, doms, stats=0, flags=0):
""" Query statistics for given domains.

Thanks
Hongming

On 03/05/2015 04:02 PM, jiahu wrote:
> The case will validate the getAllDomainStats API in class virConnect
> ---
>   repos/virconn/connection_getAllDomainStats.py | 528 ++++++++++++++++++++++++++
>   1 file changed, 528 insertions(+)
>   create mode 100644 repos/virconn/connection_getAllDomainStats.py
>
> diff --git a/repos/virconn/connection_getAllDomainStats.py b/repos/virconn/connection_getAllDomainStats.py
> new file mode 100644
> index 0000000..023564a
> --- /dev/null
> +++ b/repos/virconn/connection_getAllDomainStats.py
> @@ -0,0 +1,528 @@
> +#!/usr/bin/env python
> +# test getAllDomainStats() API for libvirt
> +
> +import libvirt
> +
> +from xml.dom import minidom
> +from libvirt import libvirtError
> +from src import sharedmod
> +from utils import utils
> +
> +required_params = ()
> +optional_params = {'stats': '','flags': ''}
> +
> +ds = {"state": libvirt.VIR_DOMAIN_STATS_STATE,
> +      "cpu": libvirt.VIR_DOMAIN_STATS_CPU_TOTAL,
> +      "balloon": libvirt.VIR_DOMAIN_STATS_BALLOON,
> +      "vcpu": libvirt.VIR_DOMAIN_STATS_VCPU,
> +      "interface": libvirt.VIR_DOMAIN_STATS_INTERFACE,
> +      "block": libvirt.VIR_DOMAIN_STATS_BLOCK}
> +
> +fg = {"active": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE,
> +      "inactive": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE,
> +      "persistent": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT,
> +      "transient": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT,
> +      "running": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_RUNNING,
> +      "paused": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_PAUSED,
> +      "shutoff": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_SHUTOFF,
> +      "other": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_OTHER,
> +      "backing": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING,
> +      "enforce": libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS}
> +
> +def filer_domains(logger, flags):
> +    """
> +       return a filtered domains set
> +    """
> +    a = set(active_domains(logger))
> +    d = set(defined_domains(logger))
> +    if flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT and \
> +       flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT:
> +        domains = a | d
> +    elif flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT:
> +        domains = d
> +    elif flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT:
> +        domains = a - d
> +    else:
> +        domains = a | d
> +    if flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE and \
> +       flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE:
> +        domains &= (a | d)
> +    elif flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE:
> +        domains &= a
> +    elif flags & libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE:
> +        domains &= (d - a)
> +    else:
> +        domains &= a | d
> +    return domains
> +
> +def active_domains(logger):
> +    """
> +       return active domains on current uri
> +    """
> +    NUM = "ls /run/libvirt/qemu|grep \".xml\""
> +    status, output = utils.exec_cmd(NUM, shell=True)
> +    output = [item.replace(".xml","") for item in output]
> +    if status == 0:
> +        logger.debug("Got active domains: %s" % output)
> +        return output
> +    else:
> +        logger.debug("Got active domains: %s" % output)
> +        return output
> +
> +def defined_domains(logger):
> +    """
> +       return defined domains on current uri
> +    """
> +    NUM = "ls /etc/libvirt/qemu|grep \".xml\""
> +    status, output = utils.exec_cmd(NUM, shell=True)
> +    output = [item.replace(".xml","") for item in output]
> +    if status == 0:
> +        logger.debug("Got defined domains: %s" % output)
> +        return output
> +    else:
> +        logger.debug("Got defined domains: %s" % output)
> +        return output
> +
> +def compare_value(logger,op1,op2):
> +    """
> +       compare 2 variables value
> +    """
> +    if op1 != op2:
> +        logger.debug("Check %s: Fail" % op2)
> +        return False
> +    else:
> +        logger.debug("Check %s: Pass" % op2)
> +        return True
> +
> +def check_vcpu(logger,dom_name,dom_active,dom_eles):
> +    """
> +       check vcpu info of given domain
> +    """
> +    iDOM_XML = "/etc/libvirt/qemu/" + dom_name +".xml"
> +    aDOM_XML = "/run/libvirt/qemu/" + dom_name +".xml"
> +    if dom_active:
> +        xml = minidom.parse(aDOM_XML)
> +        dom = xml.getElementsByTagName('domain')[0]
> +        vcpu = dom.getElementsByTagName('vcpu')[0]
> +        vcpu_max = int(vcpu.childNodes[0].data)
> +        if not vcpu.getAttribute('current'):
> +            vcpu_cur = vcpu_max
> +        else:
> +            vcpu_cur = int(vcpu.getAttribute('current'))
> +
> +        logger.debug("Checking vcpu.current: %d" \
> +                % dom_eles.get("vcpu.current"))
> +        if not compare_value(logger,vcpu_cur, \
> +                dom_eles.get("vcpu.current")):
> +            return False
> +        logger.debug("Checking vcpu.maximum: %d" \
> +                % dom_eles.get("vcpu.maximum"))
> +        if not compare_value(logger,vcpu_max, \
> +                dom_eles.get("vcpu.maximum")):
> +            return False
> +    else:
> +        xml = minidom.parse(iDOM_XML)
> +        vcpu = xml.getElementsByTagName('vcpu')[0]
> +        vcpu_max = int(vcpu.childNodes[0].data)
> +        logger.debug("Checking vcpu.maximum: %d" \
> +                % dom_eles.get("vcpu.maximum"))
> +        if not compare_value(logger,vcpu_max, \
> +                dom_eles.get("vcpu.maximum")):
> +            return False
> +    #for each vcpu.state field
> +    check_each_vcpu(logger,dom_name,dom_active,dom_eles)
> +    return True
> +
> +def check_each_vcpu(logger,dom_name,dom_active,dom_eles):
> +    """
> +       check each vcpu info, but ignore vcpu.*.time
> +    """
> +    iDOM_XML = "/etc/libvirt/qemu/" + dom_name +".xml"
> +    aDOM_XML = "/run/libvirt/qemu/" + dom_name +".xml"
> +    vcpu_index = 0
> +    if dom_active:
> +        vcpu_stat = 1
> +        xml = minidom.parse(aDOM_XML)
> +        dom = xml.getElementsByTagName('vcpus')[0]
> +        dom_pid = str(xml.getElementsByTagName("domstatus")[0].\
> +                getAttributeNode('pid').nodeValue)
> +        vcpu = dom.getElementsByTagName('vcpu')
> +        for vcpu_sub in vcpu:
> +            proc_path = "/proc/"
> +            vcpu_pre = "vcpu."+ str(vcpu_index) + "."
> +            attr1 = dom_eles.get(vcpu_pre +"state")
> +            logger.debug("Checking %sstate: %d" %(vcpu_pre, attr1))
> +            if not compare_value(logger,vcpu_stat, attr1):
> +                return False
> +            vcpu_index +=1
> +    else:
> +        vcpu_stat = 0
> +        xml = minidom.parse(iDOM_XML)
> +        vcpu = xml.getElementsByTagName('vcpu')[0]
> +        vcpu_max = int(vcpu.childNodes[0].data)
> +        vcpu_cur = vcpu.getAttributeNode('current')
> +        if not vcpu_cur:
> +            for i in range(0,vcpu_max):
> +                vcpu_pre = "vcpu."+ str(i) + "."
> +                logger.debug("Checking %sstate: %d" \
> +                        %(vcpu_pre, dom_eles.get(vcpu_pre + "state")))
> +                if not compare_value(logger,vcpu_stat, \
> +                        dom_eles.get(vcpu_pre + "state")):
> +                    return False
> +        elif int(vcpu_cur.nodeValue) <= vcpu_max:
> +            for i in range(0,int(vcpu_cur.nodeValue)):
> +                vcpu_pre = "vcpu."+ str(i) + "."
> +                logger.debug("Checking %sstate: %d" \
> +                        %(vcpu_pre, dom_eles.get(vcpu_pre + "state")))
> +                if not compare_value(logger,vcpu_stat, \
> +                        dom_eles.get(vcpu_pre + "state")):
> +                    return False
> +    return True
> +
> +def check_balloon(logger,dom_name,dom_active,dom_eles):
> +    """
> +       check balloon of given domain
> +    """
> +    iDOM_XML = "/etc/libvirt/qemu/" + dom_name +".xml"
> +    aDOM_XML = "/run/libvirt/qemu/" + dom_name +".xml"
> +    if dom_active:
> +        xml = minidom.parse(aDOM_XML)
> +        dom = xml.getElementsByTagName('domain')[0]
> +        mem_max = int(dom.getElementsByTagName('memory')[0]\
> +                .childNodes[0].data)
> +        mem_cur = int(dom.getElementsByTagName('currentMemory')[0]\
> +                .childNodes[0].data)
> +        logger.debug("Checking balloon.maximum: %d" \
> +                % dom_eles.get("balloon.maximum"))
> +        if not compare_value(logger,mem_max, \
> +                dom_eles.get("balloon.maximum")):
> +            return False
> +        logger.debug("Checking balloon.current: %d" \
> +                % dom_eles.get("balloon.current"))
> +        if not compare_value(logger,mem_cur, \
> +                dom_eles.get("balloon.current")):
> +            return False
> +    else:
> +        xml = minidom.parse(iDOM_XML)
> +        mem_max = int(xml.getElementsByTagName('memory')[0].\
> +                childNodes[0].data)
> +        logger.debug("Checking balloon.maximum: %d" \
> +                % dom_eles.get("balloon.maximum"))
> +        if not compare_value(logger,mem_max, \
> +                dom_eles.get("balloon.maximum")):
> +            return False
> +    return True
> +
> +def check_interface(logger,dom_name,dom_active, dom_eles):
> +    """
> +       check interface info, only check the count and name  attributes
> +       other sub-attributes of net.* will be ignored
> +    """
> +    iDOM_XML = "/etc/libvirt/qemu/" + dom_name +".xml"
> +    aDOM_XML = "/run/libvirt/qemu/" + dom_name +".xml"
> +    netfile = "/proc/net/dev"
> +    if dom_active:
> +        xml = minidom.parse(aDOM_XML)
> +        dom = xml.getElementsByTagName('domain')[0]
> +        dev = dom.getElementsByTagName('devices')[0]
> +        nic = dev.getElementsByTagName('interface')
> +        logger.debug("Checking net.count: %d" % dom_eles.get("net.count"))
> +        if not compare_value(logger,len(nic),dom_eles.get("net.count")):
> +            return False
> +        for iface in nic:
> +            if_name = iface.getElementsByTagName("target")[0].\
> +                    getAttribute('dev')
> +            if_name += ":"
> +            logger.debug("Checking %s" % if_name)
> +            content = open(netfile, 'r')
> +            if if_name in str(content.readlines()):
> +                logger.debug("Check %s: Pass" % if_name)
> +            else:
> +                logger.debug("Check %s: Fail" % if_name)
> +                return False
> +            content.close()
> +    else:
> +        pass
> +    return True
> +
> +def count_disk_chain(logger,filepath,dom_active):
> +    """
> +       count deep of disk chain
> +    """
> +    CMD = "file %s"
> +    num = 0
> +    while True:
> +        status, output = utils.exec_cmd(CMD % filepath, shell=True)
> +        if status != 0:
> +            logger.debug("Can not see the back file")
> +        if "has backing file" in output[0]:
> +            num +=1
> +            filepath = output[0].split("(path")[1].split(")")[0].strip()
> +        else:
> +            break
> +        if not dom_active:
> +            break
> +    return num
> +
> +def check_block(logger,dom_name,dom_active,dom_eles,backing_f):
> +    """
> +       check the block info, only check count, name and path attributes,
> +       other sub-attributes of block.* will be ignored
> +    """
> +    iDOM_XML = "/etc/libvirt/qemu/" + dom_name +".xml"
> +    aDOM_XML = "/run/libvirt/qemu/" + dom_name +".xml"
> +    disk_index = 0
> +    if dom_active:
> +        xml = minidom.parse(aDOM_XML)
> +        dom = xml.getElementsByTagName('domain')[0]
> +        dev = dom.getElementsByTagName('devices')[0]
> +        disk = dev.getElementsByTagName('disk')
> +        disk_count = len(disk)
> +        for dk in disk:
> +            disk_name = dk.getElementsByTagName('target')[0]\
> +                    .getAttributeNode('dev').nodeValue
> +            disk_sour = dk.getElementsByTagName('source')[0]\
> +                    .getAttributeNode('file').nodeValue
> +            if backing_f:
> +                disk_count += count_disk_chain(logger,disk_sour,dom_active)
> +        logger.debug("Checking disk.count: %d" % dom_eles.get("block.count"))
> +        if not compare_value(logger,disk_count,dom_eles.get("block.count")):
> +            return False
> +        if not check_each_block(logger,dom_name,dom_eles,backing_f):
> +            return False
> +    else:
> +        xml = minidom.parse(iDOM_XML)
> +        dev = xml.getElementsByTagName('devices')[0]
> +        disk = dev.getElementsByTagName('disk')
> +        disk_count = len(disk)
> +        logger.debug("Checking disk.count: %d" % dom_eles.get("block.count"))
> +        if not compare_value(logger,disk_count,dom_eles.get("block.count")):
> +            return False
> +        for dk in disk:
> +            disk_pre = "block."+ str(disk_index) + "."
> +            disk_name = dk.getElementsByTagName('target')[0]\
> +                    .getAttributeNode('dev').nodeValue
> +            logger.debug("Checking %sname: %s" \
> +                    % (disk_pre, dom_eles.get(disk_pre + "name")))
> +            if not compare_value(logger,disk_name,\
> +                    dom_eles.get(disk_pre + "name")):
> +                return False
> +            disk_sour = dk.getElementsByTagName('source')[0]\
> +                    .getAttributeNode('file').nodeValue
> +            logger.debug("Checking %spath: %s" \
> +                    % (disk_pre, dom_eles.get(disk_pre + "path")))
> +            if not compare_value(logger,disk_sour,\
> +                    dom_eles.get(disk_pre + "path")):
> +                return False
> +            disk_index += 1
> +    return True
> +
> +def check_each_block(logger,dom_name,dom_eles,backing_f):
> +    """
> +       for a active domain, this function will list all backing
> +       block info
> +    """
> +    aDOM_XML = "/run/libvirt/qemu/" + dom_name +".xml"
> +    disk_index = 0
> +    xml = minidom.parse(aDOM_XML)
> +    dom = xml.getElementsByTagName('domain')[0]
> +    dev = dom.getElementsByTagName('devices')[0]
> +    disk = dev.getElementsByTagName('disk')
> +    for dk in disk:
> +        disk_pre = "block."+ str(disk_index) + "."
> +        disk_name = dk.getElementsByTagName('target')[0]\
> +                .getAttributeNode('dev').nodeValue
> +        disk_sour = dk.getElementsByTagName('source')[0]\
> +                .getAttributeNode('file').nodeValue
> +        logger.debug("Checking %s %s" % (disk_name,disk_sour))
> +        if not compare_value(logger,disk_name, \
> +                dom_eles.get(disk_pre + "name")):
> +            return False
> +        if not compare_value(logger,disk_sour, \
> +                dom_eles.get(disk_pre + "path")):
> +            return False
> +        if not backing_f:
> +            disk_index += 1
> +            continue
> +        while True:
> +            temp = dk.getElementsByTagName('backingStore')[0]
> +            if temp.hasChildNodes():
> +                temp_name = disk_name
> +                temp_backingIndex = int(temp.getAttributeNode('index').\
> +                        nodeValue)
> +                temp_path = temp.getElementsByTagName('source')[0].\
> +                        getAttributeNode('file').nodeValue
> +                logger.debug("Checking %s %s %s" \
> +                        % (temp_name, temp_backingIndex, temp_path))
> +                disk_index += 1
> +                disk_pre = "block."+ str(disk_index) + "."
> +                if not compare_value(logger,temp_name, \
> +                        dom_eles.get(disk_pre + "name")):
> +                    return False
> +                if not compare_value(logger,temp_backingIndex, \
> +                        dom_eles.get(disk_pre + "backingIndex")):
> +                    return False
> +                if not compare_value(logger,temp_path, \
> +                        dom_eles.get(disk_pre + "path")):
> +                    return False
> +            else:
> +                break
> +            dk = temp
> +        disk_index += 1
> +    return True
> +
> +def connection_getAllDomainStats(params):
> +    """
> +       test API for getAllDomainStats in class virConnect, the script need
> +       static values to compare with those returned by API,but they are
> +       hard to calculate, so ignore below attributes temporarily:
> +           cpu.time
> +           cpu.user
> +           cpu.system
> +           *.*.time
> +           net.*.rx.*
> +           net.*.tx.*
> +           block.*.rd
> +           block.*.wr
> +           block.*.fl
> +           ...
> +      for below two attributes, no good method to obtain values when
> +      out of libvirt, pass them temporarily too.
> +           state.state
> +           state.reason
> +    """
> +    balloon_f = False
> +    vcpu_f = False
> +    interface_f = False
> +    block_f = False
> +    backing_f = False
> +    filter_f = True
> +
> +    logger = params['logger']
> +    domstats = params.get('stats', "all")
> +    domstats_string = domstats.split("|")
> +    logger.info("The stats are %s" % domstats)
> +    domstats = 0
> +    for domstat in domstats_string:
> +        if domstat == 'state':
> +            domstats |= ds.get('state')
> +        elif domstat == 'cpu':
> +            domstats |= ds.get('cpu')
> +        elif domstat == 'balloon':
> +            domstats |= ds.get('balloon')
> +            balloon_f = True
> +        elif domstat == 'vcpu':
> +            domstats |= ds.get('vcpu')
> +            vcpu_f = True
> +        elif domstat == 'interface':
> +            domstats |= ds.get('interface')
> +            interface_f = True
> +        elif domstat == 'block':
> +            domstats |= ds.get('block')
> +            block_f = True
> +        elif domstat == "all":
> +            domstats = 0
> +            balloon_f = True
> +            vcpu_f = True
> +            interface_f = True
> +            block_f = True
> +        else:
> +            logger.error("Unknown flags")
> +            return 1
> +    logger.info("The given stats is %d" % domstats)
> +
> +    flags = params.get('flags',"all")
> +    logger.info("The flags are %s" % flags)
> +    flags_string = flags.split("|")
> +    flags = 0
> +    for flag in flags_string:
> +        if flag == 'active':
> +            flags |= fg.get('active')
> +        elif flag == 'inactive':
> +            flags |= fg.get('inactive')
> +        elif flag == 'persistent':
> +            flags |= fg.get('persistent')
> +        elif flag == 'transient':
> +            flags |= fg.get('transient')
> +        elif flag == 'running':
> +            flags |= fg.get('running')
> +            filter_f = False
> +        elif flag == 'paused':
> +            flags |= fg.get('paused')
> +            filter_f = False
> +        elif flag == 'shutoff':
> +            flags |= fg.get('shutoff')
> +            filter_f = False
> +        elif flag == 'other':
> +            flags |= fg.get('other')
> +            filter_f = False
> +        elif flag == 'backing':
> +            flags |= fg.get('backing')
> +            backing_f = True
> +        elif flag == 'enforce':
> +            flags |= fg.get('enforce')
> +        elif flag == 'all':
> +            flags = 0
> +            filter_f = False
> +        else:
> +            logger.error("Unknown flags")
> +            return 1
> +    logger.info("The given flags is %d" % flags)
> +
> +    try:
> +        conn = sharedmod.libvirtobj['conn']
> +
> +        domstats_from_api =  conn.getAllDomainStats(domstats,flags)
> +        logger.info("Got the number of domain from API: %s" \
> +                % len(domstats_from_api))
> +        #filter expected domains
> +        domains = filer_domains(logger,flags)
> +        if not filter_f:
> +            logger.info("Check the number of domain: Skip")
> +        elif len(domains) == len(domstats_from_api):
> +            logger.info("Available domains: %s" % list(domains))
> +            logger.info("Check the number of domain %s: Pass" \
> +                    % len(domstats_from_api))
> +        else:
> +            logger.info("Available domains: %s" % list(domains))
> +            logger.info("Check the number of domain %s: Fail" \
> +                    % len(domstats_from_api))
> +            return 1
> +
> +        for dom in domstats_from_api:
> +            dom_name = dom[0].name()
> +            dom_active = dom[0].isActive()
> +            dom_eles = dom[1]
> +            logger.debug("Domain elements are %s" %(dom_eles))
> +            logger.info("Checking %s:" %(dom_name))
> +            if vcpu_f:
> +                if not check_vcpu(logger,dom_name,dom_active,dom_eles):
> +                    logger.info("Failed to check vcpu states")
> +                    return 1
> +                else:
> +                    logger.info("Success to check vcpu state")
> +            if balloon_f:
> +                if not check_balloon(logger,dom_name,dom_active,dom_eles):
> +                    logger.info("Failed to check balloon state")
> +                    return 1
> +                else:
> +                    logger.info("Success to check balloon state")
> +            if interface_f:
> +                if not check_interface(logger,dom_name,dom_active,dom_eles):
> +                    logger.info("Failed to check interface state")
> +                    return 1
> +                else:
> +                    logger.info("Success to check interface state")
> +            if block_f:
> +                if not check_block(logger,dom_name,dom_active,\
> +                        dom_eles,backing_f):
> +                    logger.info("Failed to check block state")
> +                    return 1
> +                else:
> +                    logger.info("Success to check block state")
> +
> +    except libvirtError, e:
> +        logger.error("API error message: %s" % e.message)
> +        return 1
> +
> +    return 0




More information about the libvir-list mailing list