Skip to content

Instantly share code, notes, and snippets.

@furlongm
Forked from anonymous/pin-vcpus.py
Created December 21, 2012 04:14
Show Gist options
  • Save furlongm/4350627 to your computer and use it in GitHub Desktop.
Save furlongm/4350627 to your computer and use it in GitHub Desktop.
#!/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