python: Add bindings for extensible migration APIs

The patch implements wrappers for virDomainMigrate3 and
virDomainMigrateToURI3.
This commit is contained in:
Jiri Denemark 2013-06-14 11:20:54 +02:00
parent 4bf62f44a9
commit 6f4c6af6ed
2 changed files with 236 additions and 0 deletions

View File

@ -527,6 +527,24 @@
<arg name='flags' type='unsigned int' info='flags, currently unused, pass 0.'/>
<return type='unsigned long' info='current max migration speed, or None in case of error'/>
</function>
<function name='virDomainMigrate3' file='python'>
<info>Migrate the domain object from its current host to the destination host
given by dconn (a connection to the destination host).</info>
<arg name='domain' type='virDomainPtr' info='a domain object'/>
<arg name='dconn' type='virConnectPtr' info='pointer to the destination host connection'/>
<arg name='params' type='char *' info='dictionary with migration parameters'/>
<arg name='flags' type='unsigned int' info='an OR&apos;ed set of virDomainMigrateFlags'/>
<return type='virDomainPtr' info='a new domain object or NULL in case of failure'/>
</function>
<function name='virDomainMigrateToURI3' file='python'>
<info>Migrate the domain object from its current host to the destination host
given by URI.</info>
<arg name='domain' type='virDomainPtr' info='a domain object'/>
<arg name='dconnuri' type='virConnectPtr' info='URI for target libvirtd if @flags includes VIR_MIGRATE_PEER2PEER'/>
<arg name='params' type='char *' info='dictionary with migration parameters'/>
<arg name='flags' type='unsigned int' info='an OR&apos;ed set of virDomainMigrateFlags'/>
<return type='int' info='0 in case of success, -1 in case of failure.'/>
</function>
<function name='virDomainSetBlockIoTune' file='python'>
<info>Change the I/O tunables for a block device</info>
<arg name='dom' type='virDomainPtr' info='pointer to the domain'/>

View File

@ -258,6 +258,160 @@ cleanup:
return NULL;
}
typedef struct {
const char *name;
int type;
} virPyTypedParamsHint;
typedef virPyTypedParamsHint *virPyTypedParamsHintPtr;
/* Automatically convert dict into type parameters based on types reported
* by python. All integer types are converted into LLONG (in case of a negative
* value) or ULLONG (in case of a positive value). If you need different
* handling, use @hints to explicitly specify what types should be used for
* specific parameters.
*/
static int
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
virPyDictToTypedParams(PyObject *dict,
virTypedParameterPtr *ret_params,
int *ret_nparams,
virPyTypedParamsHintPtr hints,
int nhints)
{
PyObject *key;
PyObject *value;
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
int pos = 0;
#else
Py_ssize_t pos = 0;
#endif
virTypedParameterPtr params = NULL;
int i;
int n = 0;
int max = 0;
int ret = -1;
*ret_params = NULL;
*ret_nparams = 0;
if (PyDict_Size(dict) < 0)
return -1;
while (PyDict_Next(dict, &pos, &key, &value)) {
char *keystr;
int type = -1;
if (!(keystr = PyString_AsString(key)))
goto cleanup;
for (i = 0; i < nhints; i++) {
if (STREQ(hints[i].name, keystr)) {
type = hints[i].type;
break;
}
}
if (type == -1) {
if (PyString_Check(value)) {
type = VIR_TYPED_PARAM_STRING;
} else if (PyBool_Check(value)) {
type = VIR_TYPED_PARAM_BOOLEAN;
} else if (PyLong_Check(value)) {
unsigned long long ull = PyLong_AsUnsignedLongLong(value);
if (ull == (unsigned long long) -1 && PyErr_Occurred())
type = VIR_TYPED_PARAM_LLONG;
else
type = VIR_TYPED_PARAM_ULLONG;
} else if (PyInt_Check(value)) {
if (PyInt_AS_LONG(value) < 0)
type = VIR_TYPED_PARAM_LLONG;
else
type = VIR_TYPED_PARAM_ULLONG;
} else if (PyFloat_Check(value)) {
type = VIR_TYPED_PARAM_DOUBLE;
}
}
if (type == -1) {
PyErr_Format(PyExc_TypeError,
"Unknown type of \"%s\" field", keystr);
goto cleanup;
}
switch ((virTypedParameterType) type) {
case VIR_TYPED_PARAM_INT:
{
int val;
if (libvirt_intUnwrap(value, &val) < 0 ||
virTypedParamsAddInt(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_UINT:
{
unsigned int val;
if (libvirt_uintUnwrap(value, &val) < 0 ||
virTypedParamsAddUInt(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_LLONG:
{
long long val;
if (libvirt_longlongUnwrap(value, &val) < 0 ||
virTypedParamsAddLLong(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_ULLONG:
{
unsigned long long val;
if (libvirt_ulonglongUnwrap(value, &val) < 0 ||
virTypedParamsAddULLong(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_DOUBLE:
{
double val;
if (libvirt_doubleUnwrap(value, &val) < 0 ||
virTypedParamsAddDouble(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_BOOLEAN:
{
bool val;
if (libvirt_boolUnwrap(value, &val) < 0 ||
virTypedParamsAddBoolean(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_STRING:
{
char *val = PyString_AsString(value);
if (!val ||
virTypedParamsAddString(&params, &n, &max, keystr, val) < 0)
goto cleanup;
break;
}
case VIR_TYPED_PARAM_LAST:
break; /* unreachable */
}
}
*ret_params = params;
*ret_nparams = n;
params = NULL;
ret = 0;
cleanup:
virTypedParamsFree(params, n);
return ret;
}
/*
* Utility function to retrieve the number of node CPUs present.
* It first tries virGetNodeCPUMap, which will return the
@ -6494,6 +6648,68 @@ libvirt_virDomainMigrateGetMaxSpeed(PyObject *self ATTRIBUTE_UNUSED, PyObject *a
return py_retval;
}
static PyObject *
libvirt_virDomainMigrate3(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args)
{
PyObject *pyobj_domain;
virDomainPtr domain;
PyObject *pyobj_dconn;
virConnectPtr dconn;
PyObject *dict;
unsigned int flags;
virTypedParameterPtr params;
int nparams;
virDomainPtr ddom = NULL;
if (!PyArg_ParseTuple(args, (char *) "OOOi:virDomainMigrate3",
&pyobj_domain, &pyobj_dconn, &dict, &flags))
return NULL;
domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
dconn = (virConnectPtr) PyvirConnect_Get(pyobj_dconn);
if (virPyDictToTypedParams(dict, &params, &nparams, NULL, 0) < 0)
return NULL;
LIBVIRT_BEGIN_ALLOW_THREADS;
ddom = virDomainMigrate3(domain, dconn, params, nparams, flags);
LIBVIRT_END_ALLOW_THREADS;
virTypedParamsFree(params, nparams);
return libvirt_virDomainPtrWrap(ddom);
}
static PyObject *
libvirt_virDomainMigrateToURI3(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args)
{
PyObject *pyobj_domain;
virDomainPtr domain;
char *dconnuri;
PyObject *dict;
unsigned int flags;
virTypedParameterPtr params;
int nparams;
int ret = -1;
if (!PyArg_ParseTuple(args, (char *) "OzOi:virDomainMigrate3",
&pyobj_domain, &dconnuri, &dict, &flags))
return NULL;
domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
if (virPyDictToTypedParams(dict, &params, &nparams, NULL, 0) < 0)
return NULL;
LIBVIRT_BEGIN_ALLOW_THREADS;
ret = virDomainMigrateToURI3(domain, dconnuri, params, nparams, flags);
LIBVIRT_END_ALLOW_THREADS;
virTypedParamsFree(params, nparams);
return libvirt_intWrap(ret);
}
static PyObject *
libvirt_virDomainBlockPeek(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) {
@ -6876,6 +7092,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virDomainSendKey", libvirt_virDomainSendKey, METH_VARARGS, NULL},
{(char *) "virDomainMigrateGetCompressionCache", libvirt_virDomainMigrateGetCompressionCache, METH_VARARGS, NULL},
{(char *) "virDomainMigrateGetMaxSpeed", libvirt_virDomainMigrateGetMaxSpeed, METH_VARARGS, NULL},
{(char *) "virDomainMigrate3", libvirt_virDomainMigrate3, METH_VARARGS, NULL},
{(char *) "virDomainMigrateToURI3", libvirt_virDomainMigrateToURI3, METH_VARARGS, NULL},
{(char *) "virDomainBlockPeek", libvirt_virDomainBlockPeek, METH_VARARGS, NULL},
{(char *) "virDomainMemoryPeek", libvirt_virDomainMemoryPeek, METH_VARARGS, NULL},
{(char *) "virDomainGetDiskErrors", libvirt_virDomainGetDiskErrors, METH_VARARGS, NULL},