Skip to content

Instantly share code, notes, and snippets.

Created December 21, 2012 04:13
Show Gist options
  • Save anonymous/4350624 to your computer and use it in GitHub Desktop.
Save anonymous/4350624 to your computer and use it in GitHub Desktop.
This gist pins unpinned vcpus for VMs running under xen. It assumes that dom0 vcpus are pinned via kernel command line (e.g. dom0_max_vcpus=1 dom0_vcpus_pin=true)
#!/usr/bin/env python
# Marcus Furlong <[email protected]> 4/4/2012
# Pin vcpus on xen
import sys
sys.path.insert(1, '/usr/lib/xen-4.0/lib/python')
sys.path.insert(1, '/usr/lib/xen-4.0/lib/python/xen/xm')
import os
import sys
import xml.dom.minidom
import warnings
warnings.filterwarnings('ignore', category=FutureWarning)
from xen.xend import sxp
from xen.xend import XendClient
from xen.util.xmlrpcclient import ServerProxy
from xen.util import auxbin
from xen.xend import XendOptions
xoptions = XendOptions.instance()
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
XM_CONFIG_FILE_DEFAULT = auxbin.xen_configdir() + '/xm-config.xml'
# Supported types of server
SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
SERVER_XEN_API = 'Xen-API'
def pin_vcpus():
doms = server.xend.domains_with_state(False, 'all', False)
dominfo = map(server.xend.domain.getVCPUInfo, doms)
nr_cpus = 0
for x in server.xend.node.info()[1:]:
if len(x) > 1 and x[0] == 'nr_cpus':
nr_cpus = int(x[1])
print "Host has %s physical CPUS" % nr_cpus
nonpinned = []
dom0_cpus = []
pcpumap = {}
dom0 = server.xend.domain.getVCPUInfo(0)
for vcpu in sxp.children(dom0, 'vcpu'):
cpumap = list(sxp.child_value(vcpu, 'cpumap'))
for pcpu in cpumap:
dom0_cpus.append(pcpu)
for i in range(0, nr_cpus):
if i in dom0_cpus:
pcpumap[i] = [0]
else:
pcpumap[i] = []
for dom in dominfo:
def get_info(n):
return sxp.child_value(dom, n)
name = get_info('name')
domid = get_info('domid')
if domid is not None:
domid = str(domid)
else:
domid = ''
for vcpu in sxp.children(dom, 'vcpu'):
def vinfo(n, t):
return t(sxp.child_value(vcpu, n))
number = vinfo('number', int)
cpumap = vinfo('cpumap', list)
print '%(name)-32s %(domid)5s %(number)5d %(cpumap)s' % locals()
if domid != '0':
for cpu in cpumap:
pcpumap[cpu].append(int(domid))
if len(cpumap) > 1:
nonpinned.append([domid, number])
vcpus_to_pin = len(nonpinned)
print "There are %s vCPUS to pin" % vcpus_to_pin
print "Domain-0 is using CPUs %s" % dom0_cpus
print "%s CPUS are available for pinning" % (nr_cpus - len(dom0_cpus))
if vcpus_to_pin > 0:
def get_minlevel(pcpumap, minlevel=50):
for pcpu in pcpumap:
if len(pcpumap[pcpu]) < minlevel and pcpu not in dom0_cpus:
minlevel = len(pcpumap[pcpu])
return minlevel
minlevel = get_minlevel(pcpumap)
for dom_vcpu in nonpinned:
for pcpu in pcpumap:
if len(pcpumap[pcpu]) > minlevel or pcpu in dom0_cpus:
continue
else:
domain_id = str(dom_vcpu[0])
vcpu_id = str(dom_vcpu[1])
cpu_id = str(pcpu)
pcpumap[pcpu].append(int(dom_vcpu[0]))
print >> sys.stderr, ("xm vcpu-pin %s %s %s" %
(domain_id, vcpu_id, cpu_id))
xm_vcpu_pin([domain_id, vcpu_id, cpu_id])
minlevel = get_minlevel(pcpumap)
break
print >> sys.stderr, ("%s vCPUs pinned" % vcpus_to_pin)
else:
print "No vCPUs need pinning."
def xm_vcpu_pin(args):
def cpu_make_map(cpulist):
cpus = []
for c in cpulist.split(','):
if c == '':
continue
if c.find('-') != -1:
(x, y) = c.split('-')
for i in range(int(x), int(y) + 1):
cpus.append(int(i))
else:
# remove this element from the list
if c[0] == '^':
cpus = [x for x in cpus if x != int(c[1:])]
else:
cpus.append(int(c))
cpus.sort()
return ",".join(map(str, cpus))
dom = args[0]
vcpu = args[1]
cpumap = cpu_make_map(args[2])
server.xend.domain.pincpu(dom, vcpu, cpumap)
def parseServer():
if config:
server = config.getElementsByTagName('server')
if server:
st = server[0].getAttribute('type')
if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
print >> sys.stderr, ('Invalid server type %s; using %s.' %
(st, SERVER_LEGACY_XMLRPC))
st = SERVER_LEGACY_XMLRPC
return (st, server[0].getAttribute('uri'))
return SERVER_LEGACY_XMLRPC, XendClient.uri
def parseAuthentication():
server = config.getElementsByTagName('server')[0]
return (server.getAttribute('username'),
server.getAttribute('password'))
if __name__ == "__main__":
print "WARNING: this program assumes that dom0_vcpus_pin=true has been"
print "set on the kernel command line."
xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
config = None
if os.path.isfile(xmConfigFile):
try:
config = xml.dom.minidom.parse(xmConfigFile)
except:
print >> sys.stderr, ('Ignoring invalid configuration file %s.' %
xmConfigFile)
serverType, serverURI = parseServer()
server = ServerProxy(serverURI)
pin_vcpus()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment