diff options
author | Pavel Hrdina <phrdina@redhat.com> | 2015-09-22 10:33:57 +0200 |
---|---|---|
committer | Pavel Hrdina <phrdina@redhat.com> | 2015-10-05 08:35:05 +0200 |
commit | a7d71b769d8e3d59515d1b9517ec5d4e0214b743 (patch) | |
tree | dbdd69b316b1d841245102895929b51522e39b73 /libvirt-utils.c | |
parent | 46b950790565708733ac5b4e3938cf87bac24cbb (diff) | |
download | libvirt-python-a7d71b769d8e3d59515d1b9517ec5d4e0214b743.tar.gz |
Move utils and shared code into libvirt-utils
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Diffstat (limited to 'libvirt-utils.c')
-rw-r--r-- | libvirt-utils.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/libvirt-utils.c b/libvirt-utils.c index d1f6e70..651d74f 100644 --- a/libvirt-utils.c +++ b/libvirt-utils.c @@ -19,12 +19,21 @@ * */ +#include <Python.h> + +/* Ugly python defines that, which is also defined in errno.h */ +#undef _POSIC_C_SOURCE + +/* We want to see *_LAST enums. */ +#define VIR_ENUM_SENTINELS + #include <errno.h> #include <stddef.h> #include <stdlib.h> #include <unistd.h> #include <libvirt/libvirt.h> #include "libvirt-utils.h" +#include "typewrappers.h" /** * virAlloc: @@ -184,3 +193,400 @@ virTypedParamsFree(virTypedParameterPtr params, VIR_FREE(params); } #endif /* ! LIBVIR_CHECK_VERSION(1, 0, 2) */ + +char * +py_str(PyObject *obj) +{ + PyObject *str = PyObject_Str(obj); + char *ret; + if (!str) { + PyErr_Print(); + PyErr_Clear(); + return NULL; + }; + libvirt_charPtrUnwrap(str, &ret); + return ret; +} + +/* Helper function to convert a virTypedParameter output array into a + * Python dictionary for return to the user. Return NULL on failure, + * after raising a python exception. */ +PyObject * +getPyVirTypedParameter(const virTypedParameter *params, + int nparams) +{ + PyObject *key, *val, *info; + size_t i; + + if ((info = PyDict_New()) == NULL) + return NULL; + + for (i = 0; i < nparams; i++) { + switch (params[i].type) { + case VIR_TYPED_PARAM_INT: + val = libvirt_intWrap(params[i].value.i); + break; + + case VIR_TYPED_PARAM_UINT: + val = libvirt_intWrap(params[i].value.ui); + break; + + case VIR_TYPED_PARAM_LLONG: + val = libvirt_longlongWrap(params[i].value.l); + break; + + case VIR_TYPED_PARAM_ULLONG: + val = libvirt_ulonglongWrap(params[i].value.ul); + break; + + case VIR_TYPED_PARAM_DOUBLE: + val = PyFloat_FromDouble(params[i].value.d); + break; + + case VIR_TYPED_PARAM_BOOLEAN: + val = PyBool_FromLong(params[i].value.b); + break; + + case VIR_TYPED_PARAM_STRING: + val = libvirt_constcharPtrWrap(params[i].value.s); + break; + + default: + /* Possible if a newer server has a bug and sent stuff we + * don't recognize. */ + PyErr_Format(PyExc_LookupError, + "Type value \"%d\" not recognized", + params[i].type); + val = NULL; + break; + } + + key = libvirt_constcharPtrWrap(params[i].field); + if (!key || !val) + goto cleanup; + + if (PyDict_SetItem(info, key, val) < 0) { + Py_DECREF(info); + goto cleanup; + } + + Py_DECREF(key); + Py_DECREF(val); + } + return info; + + cleanup: + Py_XDECREF(key); + Py_XDECREF(val); + return NULL; +} + +/* Allocate a new typed parameter array with the same contents and + * length as info, and using the array params of length nparams as + * hints on what types to use when creating the new array. The caller + * must clear the array before freeing it. Return NULL on failure, + * after raising a python exception. */ +virTypedParameterPtr +setPyVirTypedParameter(PyObject *info, + const virTypedParameter *params, + int nparams) +{ + PyObject *key, *value; +#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4 + int pos = 0; +#else + Py_ssize_t pos = 0; +#endif + virTypedParameterPtr temp = NULL, ret = NULL; + Py_ssize_t size; + size_t i; + + if ((size = PyDict_Size(info)) < 0) + return NULL; + + /* Libvirt APIs use NULL array and 0 size as a special case; + * setting should have at least one parameter. */ + if (size == 0) { + PyErr_Format(PyExc_LookupError, "Dictionary must not be empty"); + return NULL; + } + + if (VIR_ALLOC_N(ret, size) < 0) { + PyErr_NoMemory(); + return NULL; + } + + temp = &ret[0]; + while (PyDict_Next(info, &pos, &key, &value)) { + char *keystr = NULL; + + if (libvirt_charPtrUnwrap(key, &keystr) < 0 || + keystr == NULL) + goto cleanup; + + for (i = 0; i < nparams; i++) { + if (STREQ(params[i].field, keystr)) + break; + } + if (i == nparams) { + PyErr_Format(PyExc_LookupError, + "Attribute name \"%s\" could not be recognized", + keystr); + VIR_FREE(keystr); + goto cleanup; + } + + strncpy(temp->field, keystr, VIR_TYPED_PARAM_FIELD_LENGTH - 1); + temp->type = params[i].type; + VIR_FREE(keystr); + + switch (params[i].type) { + case VIR_TYPED_PARAM_INT: + if (libvirt_intUnwrap(value, &temp->value.i) < 0) + goto cleanup; + break; + + case VIR_TYPED_PARAM_UINT: + if (libvirt_uintUnwrap(value, &temp->value.ui) < 0) + goto cleanup; + break; + + case VIR_TYPED_PARAM_LLONG: + if (libvirt_longlongUnwrap(value, &temp->value.l) < 0) + goto cleanup; + break; + + case VIR_TYPED_PARAM_ULLONG: + if (libvirt_ulonglongUnwrap(value, &temp->value.ul) < 0) + goto cleanup; + break; + + case VIR_TYPED_PARAM_DOUBLE: + if (libvirt_doubleUnwrap(value, &temp->value.d) < 0) + goto cleanup; + break; + + case VIR_TYPED_PARAM_BOOLEAN: + { + bool b; + if (libvirt_boolUnwrap(value, &b) < 0) + goto cleanup; + temp->value.b = b; + break; + } + case VIR_TYPED_PARAM_STRING: + { + char *string_val; + if (libvirt_charPtrUnwrap(value, &string_val) < 0 || + !string_val) + goto cleanup; + temp->value.s = string_val; + break; + } + + default: + /* Possible if a newer server has a bug and sent stuff we + * don't recognize. */ + PyErr_Format(PyExc_LookupError, + "Type value \"%d\" not recognized", + params[i].type); + goto cleanup; + } + + temp++; + } + return ret; + +cleanup: + virTypedParamsFree(ret, size); + return NULL; +} + + +/* While these appeared in libvirt in 1.0.2, we only + * need them in the python from 1.1.0 onwards */ +#if LIBVIR_CHECK_VERSION(1, 1, 0) +int +virPyDictToTypedParamOne(virTypedParameterPtr *params, + int *n, + int *max, + virPyTypedParamsHintPtr hints, + int nhints, + const char *keystr, + PyObject *value) +{ + int rv = -1, type = -1; + size_t i; + + for (i = 0; i < nhints; i++) { + if (STREQ(hints[i].name, keystr)) { + type = hints[i].type; + break; + } + } + + if (type == -1) { + if (libvirt_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; +#if PY_MAJOR_VERSION < 3 + } else if (PyInt_Check(value)) { + if (PyInt_AS_LONG(value) < 0) + type = VIR_TYPED_PARAM_LLONG; + else + type = VIR_TYPED_PARAM_ULLONG; +#endif + } 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;; + if (libvirt_charPtrUnwrap(value, &val) < 0 || + !val || + virTypedParamsAddString(params, n, max, keystr, val) < 0) { + VIR_FREE(val); + goto cleanup; + } + VIR_FREE(val); + break; + } + case VIR_TYPED_PARAM_LAST: + break; /* unreachable */ + } + + rv = 0; + + cleanup: + return rv; +} + + +/* 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. + */ +int +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 n = 0; + int max = 0; + int ret = -1; + char *keystr = NULL; + + *ret_params = NULL; + *ret_nparams = 0; + + if (PyDict_Size(dict) < 0) + return -1; + + while (PyDict_Next(dict, &pos, &key, &value)) { + if (libvirt_charPtrUnwrap(key, &keystr) < 0 || + !keystr) + goto cleanup; + + if (PyList_Check(value) || PyTuple_Check(value)) { + Py_ssize_t i, size = PySequence_Size(value); + + for (i = 0; i < size; i++) { + PyObject *v = PySequence_ITEM(value, i); + if (virPyDictToTypedParamOne(¶ms, &n, &max, + hints, nhints, keystr, v) < 0) + goto cleanup; + } + } else if (virPyDictToTypedParamOne(¶ms, &n, &max, + hints, nhints, keystr, value) < 0) + goto cleanup; + + VIR_FREE(keystr); + } + + *ret_params = params; + *ret_nparams = n; + params = NULL; + ret = 0; + +cleanup: + VIR_FREE(keystr); + virTypedParamsFree(params, n); + return ret; +} +#endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */ |