[libvirt] [test-API][PATCH] Add test case of set vcpus with flags

Wayne Sun gsun at redhat.com
Tue Nov 20 08:57:31 UTC 2012


Use setVcpusFlags API to set domain vcpu with flags, domain could
be active or not. Flags could be '0', 'live', 'config', 'maximum'
and their combinations, use '|' between flags for combinations. A
sample conf file also added.

Signed-off-by: Wayne Sun <gsun at redhat.com>
---
 cases/set_vcpus_flags.conf      |   56 ++++++++
 repos/domain/set_vcpus_flags.py |  283 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 339 insertions(+), 0 deletions(-)
 create mode 100644 cases/set_vcpus_flags.conf
 create mode 100644 repos/domain/set_vcpus_flags.py

diff --git a/cases/set_vcpus_flags.conf b/cases/set_vcpus_flags.conf
new file mode 100644
index 0000000..7da13a2
--- /dev/null
+++ b/cases/set_vcpus_flags.conf
@@ -0,0 +1,56 @@
+domain:install_linux_cdrom
+    guestname
+        $defaultname
+    guestos
+        $defaultos
+    guestarch
+        $defaultarch
+    vcpu
+        $defaultvcpu
+    memory
+        $defaultmem
+    hddriver
+        $defaulthd
+    nicdriver
+        $defaultnic
+    imageformat
+        qcow2
+
+domain:set_vcpus_flags
+    guestname
+        $defaultname
+    vcpu
+        4
+    flags
+        0|config|live
+    username
+        $username
+    password
+        $password
+
+domain:destroy
+    guestname
+        $defaultname
+
+domain:set_vcpus_flags
+    guestname
+        $defaultname
+    vcpu
+        5
+    flags
+        0|config
+
+domain:set_vcpus_flags
+    guestname
+        $defaultname
+    vcpu
+        6
+    flags
+        maximum
+
+domain:undefine
+    guestname
+        $defaultname
+
+options cleanup=enable
+
diff --git a/repos/domain/set_vcpus_flags.py b/repos/domain/set_vcpus_flags.py
new file mode 100644
index 0000000..ca614cc
--- /dev/null
+++ b/repos/domain/set_vcpus_flags.py
@@ -0,0 +1,283 @@
+#!/usr/bin/env python
+# Test set domain vcpu with flags. Flags could be 0, live, config,
+# maximum and their combinations, use '|' for combinations. If
+# domain is active, username and password should be provided, else
+# not.
+
+import time
+import commands
+from xml.dom import minidom
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('guestname', 'vcpu', 'flags', )
+optional_params = {
+                   'username': 'root',
+                   'password': '',
+                  }
+
+def check_domain_running(conn, guestname):
+    """ check if the domain exists, may or may not be active """
+    guest_names = []
+    ids = conn.listDomainsID()
+    for id in ids:
+        obj = conn.lookupByID(id)
+        guest_names.append(obj.name())
+
+    if guestname not in guest_names:
+        logger.info("%s is not running" % guestname)
+        return 1
+    else:
+        return 0
+
+def redefine_vcpu_number(domobj, guestname, vcpu):
+    """dump domain xml description to change the vcpu number,
+       then, define the domain again
+    """
+    guestxml = domobj.XMLDesc(0)
+    logger.debug('''original guest %s xml :\n%s''' %(guestname, guestxml))
+
+    doc = minidom.parseString(guestxml)
+
+    newvcpu = doc.createElement('vcpu')
+    newvcpuval = doc.createTextNode(str(vcpu))
+    newvcpu.appendChild(newvcpuval)
+    newvcpu.setAttribute('current', '1')
+
+    domain = doc.getElementsByTagName('domain')[0]
+    oldvcpu = doc.getElementsByTagName('vcpu')[0]
+
+    domain.replaceChild(newvcpu, oldvcpu)
+
+    return doc.toxml()
+
+def check_current_vcpu(domobj, state, flag, username, password):
+    """dump domain xml description to get current vcpu number and
+       check vcpu in domain if domain is active
+    """
+    if len(flag) == 1 and flag[0] == '0':
+        if state:
+            flag.append('config')
+        else:
+            flag.append('live')
+
+    if len(flag) == 1 and flag[0] == 'maximum':
+        if state:
+            flag.append('config')
+        else:
+            logger.error("'maximum' on live domain is not supported'")
+            return False
+
+    if 'live' in flag:
+        if 'maximum' in flag:
+            logger.error("'live' with 'maximum' is not supported'")
+            return False
+
+        guestxml = domobj.XMLDesc(1)
+        logger.debug("domain %s xml is :\n%s" %(domobj.name(), guestxml))
+
+        xml = minidom.parseString(guestxml)
+        vcpu = xml.getElementsByTagName('vcpu')[0]
+        if vcpu.hasAttribute('current'):
+            attr = vcpu.getAttributeNode('current')
+            current_vcpu = int(attr.nodeValue)
+        else:
+            logger.info("no 'current' attribute in vcpu element")
+            return False
+
+        if not state:
+            if password == '' and username == 'root':
+                logger.error("check will fail with empty root password")
+                return False
+
+            logger.info("check cpu number in domain")
+            ip = utils.mac_to_ip(mac, 180)
+
+            cmd = "cat /proc/cpuinfo | grep processor | wc -l"
+            ret, output = utils.remote_exec_pexpect(ip, username, password, cmd)
+            if not ret:
+                logger.info("cpu number in domain is %s" % output)
+                if int(output) == current_vcpu:
+                    logger.info("cpu in domain is equal to current vcpu value")
+                else:
+                    logger.error("current vcpu is not equal as check in domain")
+                    return False
+            else:
+                logger.error("check in domain fail")
+                return False
+
+    if 'config' in flag:
+        guestxml = domobj.XMLDesc(2)
+        logger.debug("domain %s xml is :\n%s" %(domobj.name(), guestxml))
+
+        xml = minidom.parseString(guestxml)
+        vcpu = xml.getElementsByTagName('vcpu')[0]
+        if 'maximum' in flag:
+            current_vcpu = int(vcpu.childNodes[0].data)
+        else:
+            if vcpu.hasAttribute('current'):
+                attr = vcpu.getAttributeNode('current')
+                conf_vcpu = int(attr.nodeValue)
+                if 'live' in flag:
+                    if not current_vcpu == conf_vcpu:
+                        return False
+                else:
+                    current_vcpu = conf_vcpu
+            else:
+                logger.info("no 'current' attribute in vcpu element")
+                return False
+
+    return current_vcpu
+
+def set_vcpus_offline(domobj, guestname, vcpu):
+    """offline set the domain vcpu as given and current value as 1,
+       then boot up the domain
+    """
+    timeout = 60
+    logger.info('destroy domain')
+
+    try:
+        domobj.destroy()
+    except libvirtError, e:
+        logger.error("libvirt call failed: " + str(e))
+        logger.error("fail to destroy domain")
+        return 1
+
+    newguestxml = redefine_vcpu_number(domobj, guestname, vcpu)
+    logger.debug('''new guest %s xml :\n%s''' %(guestname, newguestxml))
+
+    logger.info("undefine the original guest")
+    try:
+        domobj.undefine()
+    except libvirtError, e:
+        logger.error("libvirt call failed: " + str(e))
+        logger.error("fail to undefine guest %" % guestname)
+        return 1
+
+    logger.info("define guest with new xml")
+    try:
+        conn = domobj._conn
+        conn.defineXML(newguestxml)
+    except libvirtError, e:
+        logger.error("libvirt call failed: " + str(e))
+        logger.error("fail to define guest %s" % guestname)
+        return 1
+
+    try:
+        logger.info('boot guest up ...')
+        domobj.create()
+    except libvirtError, e:
+        logger.error("libvirt call failed: " + str(e))
+        logger.error("fail to start domain %s" % guestname)
+        return 1
+
+    timeout = 600
+
+    while timeout:
+        time.sleep(10)
+        timeout -= 10
+
+        logger.debug("get ip by mac address")
+        ip = utils.mac_to_ip(mac, 180)
+        logger.debug("the ip address of vm %s is %s" % (guestname, ip))
+
+        if not ip:
+            logger.info(str(timeout) + "s left")
+        else:
+            logger.info("vm %s power on successfully" % guestname)
+            logger.info("the ip address of vm %s is %s" % (guestname, ip))
+            break
+
+    if timeout <= 0:
+        logger.info("fail to power on vm %s" % guestname)
+        return 1
+
+    return 0
+
+def set_vcpus_flags(params):
+    """set domain vcpu with flags and check
+    """
+    global logger
+    logger = params['logger']
+    params.pop('logger')
+    guestname = params['guestname']
+    vcpu = int(params['vcpu'])
+    flags = params['flags']
+    username = params.get('username', 'root')
+    password = params.get('password', '')
+
+    logger.info("the name of virtual machine is %s" % guestname)
+    logger.info("the vcpu given is %s" % vcpu)
+
+    logger.info("the flags is %s" % flags)
+    flags_string = flags.split("|")
+
+    flags = 0
+    for flag in flags_string:
+        if flag == '0':
+            flags |= 0
+        elif flag == 'live':
+            flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
+        elif flag == 'config':
+            flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG
+        elif flag == 'maximum':
+            flags |= libvirt.VIR_DOMAIN_VCPU_MAXIMUM
+        else:
+            logger.error("unknown flag")
+            return 1
+
+    conn = sharedmod.libvirtobj['conn']
+
+    domobj = conn.lookupByName(guestname)
+    logger.debug("get the mac address of vm %s" % guestname)
+    global mac
+    mac = utils.get_dom_mac_addr(guestname)
+    logger.debug("the mac address of vm %s is %s" % (guestname, mac))
+
+    num = vcpu + 1
+    try:
+        max_vcpus = int(conn.getMaxVcpus('kvm'))
+        logger.debug("hypervisor supported max vcpu is %s" % max_vcpus)
+    except libvirtError, e:
+        logger.error("libvirt call failed: " + str(e))
+        return 1
+
+    if num > max_vcpus:
+        logger.error("vcpu must smaller than max number: %s" % max_vcpus)
+        return 1
+
+    state = check_domain_running(conn, guestname)
+
+    if state:
+        try:
+            logger.info("set domain maximum vcpu as: %s" % num)
+            domobj.setVcpusFlags(num, libvirt.VIR_DOMAIN_VCPU_MAXIMUM)
+        except libvirtError, e:
+            logger.error("libvirt call failed: " + str(e))
+            return 1
+    else:
+        logger.info("set domain vcpu to %s and restart with current cpu as 1" %
+                    num)
+        ret = set_vcpus_offline(domobj, guestname, num)
+        if ret != 0:
+            return 1
+
+    try:
+        logger.info("set vcpus to %s with flag: %s" % (vcpu, flags))
+        domobj.setVcpusFlags(vcpu, flags)
+        logger.info("set vcpu with flag succeed")
+    except libvirtError, e:
+        logger.error("libvirt call failed: " + str(e))
+        return 1
+
+    ret = check_current_vcpu(domobj, state, flags_string, username, password)
+    if ret == 'False':
+        logger.error("check set vcpu failed")
+        return 1
+    elif ret == vcpu:
+        logger.info("check set vcpu succeed")
+        return 0
-- 
1.7.1




More information about the libvir-list mailing list