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(a)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