[libvirt] [libvirt-test-API][PATCH] Add connection_getDomainCapabilities test case

jiahu jiahu at redhat.com
Thu Mar 26 09:06:04 UTC 2015


This case will test getDomainCapabilities API, and
connection_getDomainCapabilities test case was added to
test_connection.conf
---
 cases/test_connection.conf                        |  10 +
 repos/virconn/connection_getDomainCapabilities.py | 438 ++++++++++++++++++++++
 2 files changed, 448 insertions(+)
 create mode 100644 repos/virconn/connection_getDomainCapabilities.py

diff --git a/cases/test_connection.conf b/cases/test_connection.conf
index 7552024..5719937 100644
--- a/cases/test_connection.conf
+++ b/cases/test_connection.conf
@@ -47,3 +47,13 @@ virconn:free_pages
         0
     pagesize
         4k,2M
+
+virconn:connection_getDomainCapabilities
+    emulatorbin
+        /usr/libexec/qemu-kvm
+    arch
+        x86_64
+    machine
+        pc-i440fx-rhel7.0.0
+    virttype
+        kvm
diff --git a/repos/virconn/connection_getDomainCapabilities.py b/repos/virconn/connection_getDomainCapabilities.py
new file mode 100644
index 0000000..f0cfa1f
--- /dev/null
+++ b/repos/virconn/connection_getDomainCapabilities.py
@@ -0,0 +1,438 @@
+#!/usr/bin/env python
+# test getDomainCapabilities() API for libvirtd
+
+import os
+import libvirt
+import hashlib
+import fcntl
+
+from xml.dom import minidom
+from libvirt import libvirtError
+from src import sharedmod
+from utils import utils
+
+required_params = ('emulatorbin','arch','machine','virttype',)
+optional_params = {}
+
+QEMU_CAPS = ""
+API_FILE = "/tmp/caps_from_api.xml"
+CMD = "rm -rf %s"
+OVMF = "/usr/share/OVMF/OVMF_CODE.fd"
+IOMMU = "/sys/kernel/iommu_groups/"
+VFIO = "/dev/vfio/vfio"
+KVM = "/dev/kvm"
+KVM_CHECK_EXTENSION = 44547
+KVM_CAP_IOMMU = 18
+maxcpu = 0
+
+ovmf_f = False
+drive = False
+drive_forma = False
+drive_readonly = False
+blk_sg_io = False
+usb_storage = False
+device = False
+scsi_generic = False
+vfio_pci = False
+
+def clean_env(logger):
+    """
+       clean testing environment
+    """
+    status, output = utils.exec_cmd(CMD % API_FILE, shell=True)
+    if status != 0:
+        logger.error("Can not delete %s" % API_FILE)
+    else:
+        logger.debug("Deleted %s successfully" % API_FILE)
+
+def get_hypervisor_ver(emulatorbin,logger):
+    """
+       Obtain qemu-kvm's version, and return a number value of version
+    """
+    RPM = "rpm -qf %s"
+    status, package = utils.exec_cmd(RPM % emulatorbin, shell=True)
+    if not status:
+        logger.debug("The package is %s" % package)
+    else:
+        logger.debug("The package is %s" % package)
+        return 0
+    package = package[0].split('-')
+    version = ""
+    for item in package:
+        if not item.isalnum():
+            for v in item.split("."):
+                version = version + v.rjust(3,"0")
+            break
+    return int(version)
+
+def validate_caps_from_hv(emulatorbin,logger):
+    """
+        Validate the relative caps between libvirt and qemu-kvm
+    """
+    F1 = "%s -h| grep \"\-drive\""
+    F2 = "%s -h| grep \"format=\""
+    F3 = "%s -h| grep \"readonly=\""
+    F4 = "%s -h| grep \"^\\-device\""
+    l = [F1,F2,F3,F4]
+    flags = []
+    for item in l:
+        status, temp = utils.exec_cmd(item % emulatorbin, shell=True)
+        if not status:
+            flags.append(True)
+            logger.debug("Got: %s from vh" % temp)
+        else:
+            flags.append(False)
+            logger.debug("Got: %s from vh" % temp)
+    if get_hypervisor_ver(emulatorbin,logger) >= 11000:
+         flags.append(True)
+    else:
+         flags.append(False)
+    libvirt_f = [drive,drive_forma,drive_readonly,device,blk_sg_io]
+    if flags == libvirt_f:
+        return True
+    else:
+        return False
+
+def generate_hash(emulatorbin,logger):
+    """
+       generate file name using sha256
+    """
+    global QEMU_CAPS
+    QEMU_CAPS = "/var/cache/libvirt/qemu/capabilities/"
+    file_name = hashlib.sha256(emulatorbin).hexdigest()
+    QEMU_CAPS = QEMU_CAPS + file_name + ".xml"
+    logger.debug("Cache file is %s" % QEMU_CAPS)
+
+def get_maxcpu(machine,logger):
+    """
+       return maxcpu for given machine type from QEMU_CAPS xml
+    """
+    global maxcpu
+    xml = minidom.parse(QEMU_CAPS)
+    qemu = xml.getElementsByTagName('qemuCaps')[0]
+    for item in qemu.getElementsByTagName('machine'):
+        if item.getAttribute('name') == machine:
+            maxcpu = int(item.getAttribute('maxCpus'))
+    return True
+
+def get_os_flags(logger):
+    """
+       Read results from QEMU_CAPS file and set three flags
+    """
+    global drive, drive_forma, drive_readonly
+    xml = minidom.parse(QEMU_CAPS)
+    qemu = xml.getElementsByTagName('qemuCaps')[0]
+    for item in qemu.getElementsByTagName('flag'):
+        if item.getAttribute('name') == "drive":
+            drive = True
+        if item.getAttribute('name') == "drive-format":
+            drive_forma = True
+        if item.getAttribute('name') == "drive-readonly":
+            drive_readonly = True
+    logger.debug("drive = %s; drive_format = %s; drive_readonly = %s"\
+                % (drive,drive_forma,drive_readonly))
+    return True
+
+def get_disk_flags(logger):
+    """
+       Read results from QEMU_CAPS file and set two flags
+    """
+    global blk_sg_io,usb_storage
+    xml = minidom.parse(QEMU_CAPS)
+    qemu = xml.getElementsByTagName('qemuCaps')[0]
+    for item in qemu.getElementsByTagName('flag'):
+        if item.getAttribute('name') == "blk-sg-io":
+            blk_sg_io = True
+        if item.getAttribute('name') == "usb-storage":
+            usb_storage = True
+    logger.debug("blk_sg_io = %s; usb_storage = %s" % (blk_sg_io,usb_storage))
+    return True
+
+def get_hostdev_flags(logger):
+    """
+       Read results from QEMU_CAPS file and set three flags
+    """
+    global device, scsi_generic,vfio_pci
+    xml = minidom.parse(QEMU_CAPS)
+    for item in xml.getElementsByTagName('flag'):
+        if item.getAttribute('name') == "device":
+            device = True
+        if item.getAttribute('name') == "scsi-generic":
+            scsi_generic = True
+        if item.getAttribute('name') == "vfio-pci":
+            vfio_pci = True
+    logger.debug("device = %s; scsi_generic = %s; vfio_pci = %s"\
+                 % (device,scsi_generic,vfio_pci))
+    return True
+
+def supportsPassthroughVFIO(logger):
+    """
+       check the vfio mode
+    """
+    if not os.path.exists(IOMMU):
+        logger.error("File %s is not exist" % IOMMU)
+        return False
+    if not os.path.exists(VFIO):
+        logger.error("Module %s is not exist" % VFIO)
+        return False
+    if len(os.listdir(IOMMU)) > 0:
+        return True
+    return False
+
+def supportsPassthroughKVM(logger):
+    """
+       check the legacy kvm mode
+    """
+    if not os.path.exists(KVM):
+        logger.error("File %s is not exist" % KVM)
+        return False
+    with open(KVM, "r") as kvmfd:
+        if fcntl.ioctl(kvmfd,KVM_CHECK_EXTENSION,KVM_CAP_IOMMU) == 1:
+            return True
+    return False
+
+def check_common_values(given_list,logger):
+    """
+       Check path/machine/arch/vcpu parameters
+    """
+    xml = minidom.parse(API_FILE)
+    dom = xml.getElementsByTagName('domainCapabilities')[0]
+    #get path/machine/arch/vcpu from xml generated by api
+    path = dom.getElementsByTagName('path')[0].childNodes[0].data
+    domain = dom.getElementsByTagName('domain')[0].childNodes[0].data
+    machine = dom.getElementsByTagName('machine')[0].childNodes[0].data
+    arch = dom.getElementsByTagName('arch')[0].childNodes[0].data
+    vcpu = dom.getElementsByTagName('vcpu')[0].getAttribute('max')
+    #put all of them to a list
+    list1 = [str(path),str(machine),str(arch),int(vcpu)]
+    logger.debug("Got 4 common parameters: %s" % list1)
+    if  given_list == list1:
+        logger.debug("Checking common value: Pass")
+    else:
+        logger.debug("Checking common value: Fail")
+        return False
+    return True
+
+def check_os(arch, logger):
+    """
+       check the os part
+    """
+    alltype = ["rom","pflash"]
+    allreadonly = ["yes","no"]
+    type_api = []
+    readonly_api = []
+    xml = minidom.parse(API_FILE)
+    dom = xml.getElementsByTagName('domainCapabilities')[0]
+    os = dom.getElementsByTagName('os')[0]
+    loader = os.getElementsByTagName('loader')[0]
+    ovmf1 =  os.getElementsByTagName('value')[0]
+    ovmf1 = ovmf1.childNodes[0].data
+    logger.debug("Got OVMF path is %s" % ovmf1)
+    if ovmf_f and ovmf1 == OVMF:
+        pass
+    else:
+        return False
+    enum = loader.getElementsByTagName('enum')
+    for item in enum:
+        if item.getAttribute('name') == "type":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                type_api.append(str(temp.childNodes[0].data))
+        if item.getAttribute('name') == "readonly":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                readonly_api.append(str(temp.childNodes[0].data))
+    if not (drive & drive_forma):
+        alltype.remove("pflash")
+    if not drive_readonly:
+        allreadonly = []
+    logger.debug("Got type list: %s" % type_api)
+    logger.debug("Got readonly list: %s" % readonly_api)
+    if not type_api == alltype:
+        return False
+    if not readonly_api == allreadonly:
+        return False
+    return True
+
+def check_disk(logger):
+    """
+       check the disk part in <devices>
+    """
+    alldevice = ["disk","cdrom","floppy","lun"]
+    allbus = ["ide","fdc","scsi","virtio","usb"]
+    device_api = []
+    bus_api = []
+    xml = minidom.parse(API_FILE)
+    dom = xml.getElementsByTagName('domainCapabilities')[0]
+    devices = dom.getElementsByTagName('devices')[0]
+    disk = devices.getElementsByTagName('disk')[0]
+    enum = disk.getElementsByTagName('enum')
+    for item in enum:
+        if item.getAttribute('name') == "diskDevice":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                device_api.append(str(temp.childNodes[0].data))
+        if item.getAttribute('name') == "bus":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                bus_api.append(str(temp.childNodes[0].data))
+    if not blk_sg_io:
+        alldevice.remove("lun")
+    if not usb_storage:
+        allbus.remove("usb")
+    logger.debug("Got diskDevice list: %s" % device_api)
+    logger.debug("Got bus list: %s" % bus_api)
+    if not device_api == alldevice:
+        return False
+    if not bus_api == allbus:
+        return False
+    return True
+
+def check_hostdev(logger):
+    """
+       check the hostdev part in <devices>
+    """
+    allmode = ["subsystem"]
+    allpolicy = ["default","mandatory","requisite","optional"]
+    allsubsys = ["usb","pci","scsi"]
+    allbackend = ["default","default","vfio","kvm"]
+    mode_api = []
+    policy_api = []
+    subsys_api = []
+    backend_api = []
+    caps_api = []
+    xml = minidom.parse(API_FILE)
+    dom = xml.getElementsByTagName('domainCapabilities')[0]
+    devices = dom.getElementsByTagName('devices')[0]
+    hostdev = devices.getElementsByTagName('hostdev')[0]
+    enum = hostdev.getElementsByTagName('enum')
+    for item in enum:
+        if item.getAttribute('name') == "mode":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                mode_api.append(str(temp.childNodes[0].data))
+        if item.getAttribute('name') == "startupPolicy":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                policy_api.append(str(temp.childNodes[0].data))
+        if item.getAttribute('name') == "subsysType":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                subsys_api.append(str(temp.childNodes[0].data))
+        if item.getAttribute('name') == "capsType":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                caps_api.append(str(temp.childNodes[0].data))
+        if item.getAttribute('name') == "pciBackend":
+            value = item.getElementsByTagName("value")
+            for temp in value:
+                backend_api.append(str(temp.childNodes[0].data))
+    #WIP, we need more codes to check vfio
+    if not (drive & device & scsi_generic):
+        allsubsys.remove("scsi")
+    if not (supportsPassthroughKVM(logger) & device):
+        allbackend.remove("default")
+        allbackend.remove("kvm")
+    if not (supportsPassthroughVFIO(logger) & vfio_pci):
+        allbackend.remove("default")
+        allbackend.remove("vfio")
+    logger.debug("Got mode list: %s" % mode_api)
+    logger.debug("Got startupPolicy list: %s" % policy_api)
+    logger.debug("Got subsysType list: %s" % subsys_api)
+    logger.debug("Got capsType list: %s" % caps_api)
+    logger.debug("Got pciBackend list: %s" % backend_api)
+    if not mode_api == allmode:
+        return False
+    if not policy_api == allpolicy:
+        return False
+    if not subsys_api == allsubsys:
+        return False
+    if not backend_api == allbackend:
+        return False
+    return True
+
+def connection_getDomainCapabilities(params):
+    """
+       test API for getDomainCapabilities in class virConnect
+    """
+    global ovmf_f
+    logger = params['logger']
+    emulatorbin = params['emulatorbin']
+    arch = params['arch']
+    machine = params['machine']
+    virttype = params['virttype']
+
+    try:
+        logger.info("The specified emulatorbin is %s" \
+                    % emulatorbin)
+        logger.info("The specified architecture is %s" \
+                    % arch)
+        logger.info("The specified machine is %s" \
+                    % machine)
+        logger.info("The specified virttype is %s" \
+                    % virttype)
+
+        generate_hash(emulatorbin, logger)
+        if not os.path.exists(QEMU_CAPS):
+            logger.error("cache file, %s is not exist" % QEMU_CAPS)
+            return 1
+        if os.path.exists(OVMF):
+            ovmf_f = True
+        else:
+            logger.warning("cache file, %s is not exist" % OVMF)
+        if not get_maxcpu(machine,logger):
+            logger.debug("get maxcpu: Fail")
+            return 1
+        if not get_os_flags(logger):
+            logger.debug("get os: Fail")
+            return 1
+        if not get_disk_flags(logger):
+            logger.debug("get disk: Fail")
+            return 1
+        if not get_hostdev_flags(logger):
+            logger.debug("get hostdev: Fail")
+            return 1
+        if not validate_caps_from_hv(emulatorbin,logger):
+            logger.error("Failed to compare caps")
+            return 1
+        else:
+            logger.debug("Successed to compare caps")
+
+        conn = sharedmod.libvirtobj['conn']
+        caps_from_api = conn.getDomainCapabilities\
+(emulatorbin,arch,machine,virttype,0)
+
+        logger.debug("The return of API: %s" % caps_from_api)
+        fd = open(API_FILE,"w+")
+        fd.write(caps_from_api)
+        fd.flush()
+
+        given_list = [emulatorbin,machine,arch,maxcpu]
+        if not check_common_values(given_list,logger):
+            logger.info("Failed to validate common elements")
+            return 1
+        else:
+            logger.info("Successed to validate common elements")
+        if not check_os(arch,logger):
+            logger.info("Failed to validate os block")
+            return 1
+        else:
+            logger.info("Successed to validate os block")
+        if not check_disk(logger):
+            logger.info("Failed to validate disk block")
+            return 1
+        else:
+            logger.info("Successed to validate disk block")
+        if not check_hostdev(logger):
+            logger.info("Failed to validate hostdev block")
+            return 1
+        else:
+            logger.info("Successed to validate hostdev block")
+
+    except libvirtError, e:
+        logger.error("API error message: %s" % e.message)
+        clean_env(logger)
+        return 1
+
+    clean_env(logger)
+    return 0
-- 
1.8.1.4




More information about the libvir-list mailing list