The python binding is missing all the APIs relating to CPU pinning and
schedular parameters because they are too hard for the generator to manage.
This patch implements them manually. Now a few words about the impls since
they are non-trivial
* virDomainGetSchedulerType
The C binding has a return value, and an out parameter. I translated
this into a tuple in python (schedular-type, n-parms)
eg
print dom.schedulerType()
('credit', 2)
Arguably we could drop the nparams field - its less use in python
since you don't have to pre-allocate a virSchedParam list.
* virDomainGetSchedulerParameters
This has an out parameter which is a list of virSchedParam structs, and
a param specifying the length of the passed in virSchedParam list. The
latter is irrelevant; The former I translated into a hash table return
value
eg
print dom.schedulerParameters()
{'cap': 0, 'weight': 100}
* virDomainSetSchedulerParameters
This has two in parameters, a list of virSchedParma structs, and a param
specifying length of the list. I just convert this into a hash. I also
make all the fields optional - it'll copy existing values for any params
which are omimtted.
eg
dom.setSchedulerParameters({'weight': 100})
* virDomainGetVcpus
This has two out parameters, a list of virVcpuInfo structs, and a bitmap
both pre-allocated, and their size passed in. This needs to be turned into
a 2 element tuple return value. First element returning vcpu info, and the
second element returning mapping. The vcpu info will be returned as a list
of lists, and the cpumap will be another list of lists - a True indicating
affinity.
eg
(cpuinfo, cpumap) = dom.vcpus()
print cpuinfo
print cpumap
[(0, 2, 7753916026L, 1), (1, 2, 5698028782L, 0), (2, 2, 4916522979L, 0), (3, 2,
3773416711L, 1)]
[(False, True), (True, True), (True, False), (True, True)]
* virDomainPinVcpu
This takes a vcpu number and a bitmap of affinity. I turn the bitmap
into a list of True/False values
eg
dom.pinVcpu(1, (True, True))
The generator fails on the C code part of the bindings completely, so that
is hand-written. It also fails on the python part of the bindings, but
the way the generator is structured doesn't enable us to hand-write the
python part for methods within objects :-( So I have basically just editted
the generator to blacklist all the out-parameters, and blacklist the in
parameters which specify list lengths.
Here is the code I used to test the functions:
#!/usr/bin/python
import libvirt
con = libvirt.open("xen:///")
dom = con.lookupByName("rhel5pv")
dominfo = dom.info()
nodeinfo = con.getInfo()
pcpus = nodeinfo[4] * nodeinfo[5] * nodeinfo[6] * nodeinfo[7]
(cpuinfo, cpumap) = dom.vcpus()
print cpuinfo
print cpumap
for i in range(dominfo[3]):
print "vcpu: %d" % i
if cpuinfo[i][1] == 0:
print "state: offline"
elif cpuinfo[i][1] == 2:
print "state: blocked"
else:
print "state: running"
print "cputime: %d" % cpuinfo[i][2]
print "pcpu: %d" % cpuinfo[i][3]
affinity = ""
for p in range(pcpus):
if cpumap[i][p] == True:
affinity = affinity + "y"
else:
affinity = affinity + "-"
print "affinity: %s" % affinity
print
dom.pinVcpu(1, (True, True))
print dom.schedulerType()
print dom.schedulerParameters()
dom.setSchedulerParameters({"weight": 100})
And here is the diffstat:
generator.py | 26 ++++
libvir.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 344 insertions(+)
Dan.
diff -r 8468c0d428c9 python/generator.py
--- a/python/generator.py Sun Jan 20 12:06:47 2008 -0500
+++ b/python/generator.py Sun Jan 20 12:07:59 2008 -0500
@@ -229,6 +229,7 @@ py_types = {
'double': ('d', None, "double", "double"),
'unsigned int': ('i', None, "int", "int"),
'unsigned long': ('l', None, "long", "long"),
+ 'unsigned long long': ('l', None, "longlong", "long
long"),
'unsigned char *': ('z', None, "charPtr", "char
*"),
'char *': ('z', None, "charPtr", "char *"),
'const char *': ('z', None, "charPtrConst", "const
char *"),
@@ -279,6 +280,11 @@ skip_impl = (
'virDomainBlockStats',
'virDomainInterfaceStats',
'virNodeGetCellsFreeMemory',
+ 'virDomainGetSchedulerType',
+ 'virDomainGetSchedulerParameters',
+ 'virDomainSetSchedulerParameters',
+ 'virDomainGetVcpus',
+ 'virDomainPinVcpu',
)
def skip_function(name):
@@ -918,6 +924,16 @@ def buildWrappers():
txt.write(" %s()\n" % func);
n = 0
for arg in args:
+ if name == "virDomainPinVcpu" and arg[0] ==
"maplen":
+ continue
+ if name == "virDomainGetSchedulerType" and arg[0] ==
"nparams":
+ continue
+ if name == "virDomainSetSchedulerParameters" and arg[0] ==
"nparams":
+ continue
+ if name == "virDomainGetSchedulerParameters" and arg[0] !=
"domain":
+ continue
+ if name == "virDomainGetVcpus" and arg[0] !=
"domain":
+ continue
if n != index:
classes.write(", %s" % arg[0])
n = n + 1
@@ -939,6 +955,16 @@ def buildWrappers():
classes.write("libvirtmod.%s(" % name)
n = 0
for arg in args:
+ if name == "virDomainPinVcpu" and arg[0] ==
"maplen":
+ continue
+ if name == "virDomainGetSchedulerType" and arg[0] ==
"nparams":
+ continue
+ if name == "virDomainSetSchedulerParameters" and arg[0] ==
"nparams":
+ continue
+ if name == "virDomainGetSchedulerParameters" and arg[0] !=
"domain":
+ continue
+ if name == "virDomainGetVcpus" and arg[0] !=
"domain":
+ continue
if n != 0:
classes.write(", ");
if n != index:
diff -r 8468c0d428c9 python/libvir.c
--- a/python/libvir.c Sun Jan 20 12:06:47 2008 -0500
+++ b/python/libvir.c Sun Jan 20 12:07:59 2008 -0500
@@ -102,6 +102,319 @@ libvirt_virDomainInterfaceStats(PyObject
PyTuple_SetItem(info, 7, PyLong_FromLongLong(stats.tx_drop));
return(info);
}
+
+
+static PyObject *
+libvirt_virDomainGetSchedulerType(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ char *c_retval;
+ int nparams;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetScedulerType",
+ &pyobj_domain))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ c_retval = virDomainGetSchedulerType(domain, &nparams);
+ if (c_retval == NULL)
+ return VIR_PY_NONE;
+
+ /* convert to a Python tupple of long objects */
+ if ((info = PyTuple_New(2)) == NULL) {
+ free(c_retval);
+ return VIR_PY_NONE;
+ }
+
+ PyTuple_SetItem(info, 0, libvirt_constcharPtrWrap(c_retval));
+ PyTuple_SetItem(info, 1, PyInt_FromLong((long)nparams));
+ free(c_retval);
+ return(info);
+}
+
+static PyObject *
+libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ char *c_retval;
+ int nparams, i;
+ virSchedParameterPtr params;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetScedulerParameters",
+ &pyobj_domain))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ c_retval = virDomainGetSchedulerType(domain, &nparams);
+ if (c_retval == NULL)
+ return VIR_PY_NONE;
+ free(c_retval);
+
+ if ((params = malloc(sizeof(*params)*nparams)) == NULL)
+ return VIR_PY_NONE;
+
+ if (virDomainGetSchedulerParameters(domain, params, &nparams) < 0) {
+ free(params);
+ return VIR_PY_NONE;
+ }
+
+ /* convert to a Python tupple of long objects */
+ if ((info = PyDict_New()) == NULL) {
+ free(params);
+ return VIR_PY_NONE;
+ }
+ for (i = 0 ; i < nparams ; i++) {
+ PyObject *key, *val;
+
+ switch (params[i].type) {
+ case VIR_DOMAIN_SCHED_FIELD_INT:
+ val = PyInt_FromLong((long)params[i].value.i);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_UINT:
+ val = PyInt_FromLong((long)params[i].value.ui);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_LLONG:
+ val = PyLong_FromLongLong((long long)params[i].value.l);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_ULLONG:
+ val = PyLong_FromLongLong((long long)params[i].value.ul);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
+ val = PyFloat_FromDouble((double)params[i].value.d);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
+ val = PyBool_FromLong((long)params[i].value.b);
+ break;
+
+ default:
+ free(params);
+ Py_DECREF(info);
+ return VIR_PY_NONE;
+ }
+
+ key = libvirt_constcharPtrWrap(params[i].field);
+ PyDict_SetItem(info, key, val);
+ }
+ free(params);
+ return(info);
+}
+
+static PyObject *
+libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ char *c_retval;
+ int nparams, i;
+ virSchedParameterPtr params;
+
+ if (!PyArg_ParseTuple(args, (char *)"OO:virDomainSetScedulerParameters",
+ &pyobj_domain, &info))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ c_retval = virDomainGetSchedulerType(domain, &nparams);
+ if (c_retval == NULL)
+ return VIR_PY_NONE;
+ free(c_retval);
+
+ if ((params = malloc(sizeof(*params)*nparams)) == NULL)
+ return VIR_PY_NONE;
+
+ if (virDomainGetSchedulerParameters(domain, params, &nparams) < 0) {
+ free(params);
+ return VIR_PY_NONE;
+ }
+
+ /* convert to a Python tupple of long objects */
+ for (i = 0 ; i < nparams ; i++) {
+ PyObject *key, *val;
+ key = libvirt_constcharPtrWrap(params[i].field);
+ val = PyDict_GetItem(info, key);
+ Py_DECREF(key);
+
+ if (val == NULL)
+ continue;
+
+ switch (params[i].type) {
+ case VIR_DOMAIN_SCHED_FIELD_INT:
+ params[i].value.i = (int)PyInt_AS_LONG(val);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_UINT:
+ params[i].value.ui = (unsigned int)PyInt_AS_LONG(val);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_LLONG:
+ params[i].value.l = (long long)PyLong_AsLongLong(val);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_ULLONG:
+ params[i].value.ul = (unsigned long long)PyLong_AsLongLong(val);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
+ params[i].value.d = (double)PyFloat_AsDouble(val);
+ break;
+
+ case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
+ {
+ /* Hack - Python's definition of Py_True breaks strict
+ * aliasing rules, so can't directly compare :-(
+ */
+ PyObject *hacktrue = PyBool_FromLong(1);
+ params[i].value.b = hacktrue == val ? 1 : 0;
+ Py_DECREF(hacktrue);
+ }
+ break;
+
+ default:
+ free(params);
+ return VIR_PY_NONE;
+ }
+ }
+
+ if (virDomainSetSchedulerParameters(domain, params, nparams) < 0) {
+ free(params);
+ return VIR_PY_NONE;
+ }
+
+ free(params);
+ return VIR_PY_NONE;
+}
+
+static PyObject *
+libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *pyretval = NULL, *pycpuinfo = NULL, *pycpumap = NULL;
+ virNodeInfo nodeinfo;
+ virDomainInfo dominfo;
+ virVcpuInfoPtr cpuinfo = NULL;
+ unsigned char *cpumap = NULL;
+ int cpumaplen, i;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetVcpus",
+ &pyobj_domain))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if (virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo) != 0)
+ return VIR_PY_NONE;
+
+ if (virDomainGetInfo(domain, &dominfo) != 0)
+ return VIR_PY_NONE;
+
+ if ((cpuinfo = malloc(sizeof(*cpuinfo)*dominfo.nrVirtCpu)) == NULL)
+ return VIR_PY_NONE;
+
+ cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+ if ((cpumap = malloc(dominfo.nrVirtCpu * cpumaplen)) == NULL)
+ goto cleanup;
+
+ if (virDomainGetVcpus(domain,
+ cpuinfo, dominfo.nrVirtCpu,
+ cpumap, cpumaplen) < 0)
+ goto cleanup;
+
+ /* convert to a Python tupple of long objects */
+ if ((pyretval = PyTuple_New(2)) == NULL)
+ goto cleanup;
+ if ((pycpuinfo = PyList_New(dominfo.nrVirtCpu)) == NULL)
+ goto cleanup;
+ if ((pycpumap = PyList_New(dominfo.nrVirtCpu)) == NULL)
+ goto cleanup;
+
+ for (i = 0 ; i < dominfo.nrVirtCpu ; i++) {
+ PyObject *info = PyTuple_New(4);
+ if (info == NULL)
+ goto cleanup;
+ PyTuple_SetItem(info, 0, PyInt_FromLong((long)cpuinfo[i].number));
+ PyTuple_SetItem(info, 1, PyInt_FromLong((long)cpuinfo[i].state));
+ PyTuple_SetItem(info, 2, PyLong_FromLongLong((long long)cpuinfo[i].cpuTime));
+ PyTuple_SetItem(info, 3, PyInt_FromLong((long)cpuinfo[i].cpu));
+ PyList_SetItem(pycpuinfo, i, info);
+ }
+ for (i = 0 ; i < dominfo.nrVirtCpu ; i++) {
+ PyObject *info = PyTuple_New(VIR_NODEINFO_MAXCPUS(nodeinfo));
+ int j;
+ if (info == NULL)
+ goto cleanup;
+ for (j = 0 ; j < VIR_NODEINFO_MAXCPUS(nodeinfo) ; j++) {
+ PyTuple_SetItem(info, j, PyBool_FromLong(VIR_CPU_USABLE(cpumap, cpumaplen, i,
j)));
+ }
+ PyList_SetItem(pycpumap, i, info);
+ }
+ PyTuple_SetItem(pyretval, 0, pycpuinfo);
+ PyTuple_SetItem(pyretval, 1, pycpumap);
+
+ free(cpuinfo);
+ free(cpumap);
+
+ return(pyretval);
+
+ cleanup:
+ free(cpuinfo);
+ free(cpumap);
+ /* NB, Py_DECREF is a badly defined macro, so we require
+ * braces here to avoid 'ambiguous else' warnings from
+ * the compiler.
+ * NB. this comment is true at of time of writing wrt to
+ * at least python2.5.
+ */
+ if (pyretval) { Py_DECREF(pyretval); }
+ if (pycpuinfo) { Py_DECREF(pycpuinfo); }
+ if (pycpumap) { Py_DECREF(pycpumap); }
+ return VIR_PY_NONE;
+}
+
+
+static PyObject *
+libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *pycpumap, *truth;
+ virNodeInfo nodeinfo;
+ unsigned char *cpumap;
+ int cpumaplen, i, vcpu;
+
+ if (!PyArg_ParseTuple(args, (char *)"OiO:virDomainPinVcpu",
+ &pyobj_domain, &vcpu, &pycpumap))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if (virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo) != 0)
+ return VIR_PY_NONE;
+
+ cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+ if ((cpumap = malloc(cpumaplen)) == NULL)
+ return VIR_PY_NONE;
+ memset(cpumap, 0, cpumaplen);
+
+ truth = PyBool_FromLong(1);
+ for (i = 0 ; i < VIR_NODEINFO_MAXCPUS(nodeinfo) ; i++) {
+ PyObject *flag = PyTuple_GetItem(pycpumap, i);
+ if (flag == truth)
+ VIR_USE_CPU(cpumap, i);
+ else
+ VIR_UNUSE_CPU(cpumap, i);
+ }
+
+ virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen);
+ Py_DECREF(truth);
+ free(cpumap);
+
+ return VIR_PY_NONE;
+}
+
+
/************************************************************************
* *
* Global error handler at the Python level *
@@ -876,6 +1189,11 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virDomainBlockStats", libvirt_virDomainBlockStats, METH_VARARGS,
NULL},
{(char *) "virDomainInterfaceStats", libvirt_virDomainInterfaceStats,
METH_VARARGS, NULL},
{(char *) "virNodeGetCellsFreeMemory", libvirt_virNodeGetCellsFreeMemory,
METH_VARARGS, NULL},
+ {(char *) "virDomainGetSchedulerType", libvirt_virDomainGetSchedulerType,
METH_VARARGS, NULL},
+ {(char *) "virDomainGetSchedulerParameters",
libvirt_virDomainGetSchedulerParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainSetSchedulerParameters",
libvirt_virDomainSetSchedulerParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainGetVcpus", libvirt_virDomainGetVcpus, METH_VARARGS,
NULL},
+ {(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS,
NULL},
{NULL, NULL, 0, NULL}
};
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules:
http://search.cpan.org/~danberr/ -=|
|=- Projects:
http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|