On 11/03/15 17:14, hongming wrote:
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
OK, the V2 patch series has been sent out, please review them.
BR,
Jianwei
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