On Thu, Feb 19, 2015 at 07:59:39AM -0500, John Ferlan wrote: > Support the libvirt_virDomainSetIOThreads method using code that mimics > the existing libvirt_virDomainPinVcpuFlags method > > The following is a sample session assuming guest 'iothr-gst' has IOThreads > configured (it's currently running, too) > > >>> import libvirt > >>> con=libvirt.open("qemu:///system") > >>> dom=con.lookupByName('iothr-gst') > >>> dom.getIOThreadsInfo() > [(1, [False, False, True, False], ['/home/vm-images/iothr-vol1']), (2, [False, False, False, True], ['/home/vm-images/iothr-vol2']), (3, [False, False, False, True], [])] > >>> cpumap=(True,True,True,False) > >>> dom.setIOThreads(3,cpumap) > 0 > >>> print dom.getIOThreadsInfo() > [(1, [False, False, True, False], ['/home/vm-images/iothr-vol1']), (2, [False, False, False, True], ['/home/vm-images/iothr-vol2']), (3, [True, True, True, False], [])] > >>> > > Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> > --- > generator.py | 1 + > libvirt-override-api.xml | 8 ++++++ > libvirt-override.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 76 insertions(+) > > diff --git a/generator.py b/generator.py > index 327c896..c79acf1 100755 > --- a/generator.py > +++ b/generator.py > @@ -436,6 +436,7 @@ skip_impl = ( > 'virDomainGetEmulatorPinInfo', > 'virDomainPinEmulator', > 'virDomainGetIOThreadsInfo', > + 'virDomainSetIOThreads', > 'virSecretGetValue', > 'virSecretSetValue', > 'virSecretGetUUID', > diff --git a/libvirt-override-api.xml b/libvirt-override-api.xml > index e512311..19667b6 100644 > --- a/libvirt-override-api.xml > +++ b/libvirt-override-api.xml > @@ -284,6 +284,14 @@ > <arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/> > <return type='char *' info="list of IOThreads information including the iothread_id, the cpumap, the cpumap length, number of associated resources, and a list of each resource assigned to the iothread_id."/> > </function> > + <function name='virDomainSetIOThreads' file='python'> > + <info>Dynamically change the real CPUs which can be allocated to an IOThread. This function requires privileged access to the hypervisor.</info> > + <return type='int' info='0 in case of success, -1 in case of failure.'/> > + <arg name='domain' type='virDomainPtr' info='pointer to domain object'/> > + <arg name='iothread_val' type='unsigned int' info='iothread_id number'/> > + <arg name='cpumap' type='unsigned char *' info='pointer to a bit map of real CPUs (in 8-bit bytes) (IN) Each bit set to 1 means that corresponding CPU is usable. Bytes are stored in little-endian order: CPU0-7, 8-15... In each byte, lowest CPU number is least significant bit.'/> > + <arg name='flags' type='int' info='an OR'ed set of virDomainIOThreadsFlags'/> > + </function> > <function name='virDomainSetSchedulerParameters' file='python'> > <info>Change the scheduler parameters</info> > <return type='int' info='-1 in case of error, 0 in case of success.'/> > diff --git a/libvirt-override.c b/libvirt-override.c > index 17f3bf3..f9af5a9 100644 > --- a/libvirt-override.c > +++ b/libvirt-override.c > @@ -2082,6 +2082,72 @@ cleanup: > return VIR_PY_NONE; > } > > +static PyObject * > +libvirt_virDomainSetIOThreads(PyObject *self ATTRIBUTE_UNUSED, > + PyObject *args) > +{ > + virDomainPtr domain; > + PyObject *pyobj_domain, *pycpumap; > + PyObject *ret = NULL; > + unsigned char *cpumap; > + int cpumaplen, iothread_val, tuple_size, cpunum; > + size_t i; > + unsigned int flags; > + int i_retval; > + > + if (!PyArg_ParseTuple(args, (char *)"OiOI:virDomainSetIOThread", > + &pyobj_domain, &iothread_val, &pycpumap, &flags)) > + return NULL; > + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); > + > + if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) > + return VIR_PY_INT_FAIL; > + > + if (PyTuple_Check(pycpumap)) { > + tuple_size = PyTuple_Size(pycpumap); > + if (tuple_size == -1) This could be merged into one line as the condition before. And returning NULL is correct because the PyTuple_Size sets an exception in case of failure. > + return ret; > + } else { > + PyErr_SetString(PyExc_TypeError, "Unexpected type, tuple is required"); > + return ret; > + } > + > + cpumaplen = VIR_CPU_MAPLEN(cpunum); > + if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) > + return PyErr_NoMemory(); > + > + for (i = 0; i < tuple_size; i++) { > + PyObject *flag = PyTuple_GetItem(pycpumap, i); > + bool b; > + > + if (!flag || libvirt_boolUnwrap(flag, &b) < 0) > + goto cleanup; > + > + if (b) > + VIR_USE_CPU(cpumap, i); > + else > + VIR_UNUSE_CPU(cpumap, i); > + } > + > + for (; i < cpunum; i++) > + VIR_UNUSE_CPU(cpumap, i); > + > + flags |= VIR_DOMAIN_IOTHREADS_PIN; > + LIBVIRT_BEGIN_ALLOW_THREADS; > + i_retval = virDomainSetIOThreads(domain, iothread_val, > + cpumap, cpumaplen, flags); > + LIBVIRT_END_ALLOW_THREADS; > + if (i_retval < 0) { > + ret = VIR_PY_INT_FAIL; > + goto cleanup; > + } > + ret = VIR_PY_INT_SUCCESS; > + > +cleanup: > + VIR_FREE(cpumap); > + return ret; > +} > + > #endif /* LIBVIR_CHECK_VERSION(1, 2, 13) */ > > /************************************************************************ > @@ -8578,6 +8644,7 @@ static PyMethodDef libvirtMethods[] = { > #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ > #if LIBVIR_CHECK_VERSION(1, 2, 13) > {(char *) "virDomainGetIOThreadsInfo", libvirt_virDomainGetIOThreadsInfo, METH_VARARGS, NULL}, > + {(char *) "virDomainSetIOThreads", libvirt_virDomainSetIOThreads, METH_VARARGS, NULL}, > #endif /* LIBVIR_CHECK_VERSION(1, 2, 13) */ > {(char *) "virConnectListStoragePools", libvirt_virConnectListStoragePools, METH_VARARGS, NULL}, > {(char *) "virConnectListDefinedStoragePools", libvirt_virConnectListDefinedStoragePools, METH_VARARGS, NULL}, > -- > 2.1.0 ACK with the change proposed above. Pavel > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list