summaryrefslogtreecommitdiff
path: root/libvirt-utils.c
diff options
context:
space:
mode:
authorPavel Hrdina <phrdina@redhat.com>2015-09-22 10:33:57 +0200
committerPavel Hrdina <phrdina@redhat.com>2015-10-05 08:35:05 +0200
commita7d71b769d8e3d59515d1b9517ec5d4e0214b743 (patch)
treedbdd69b316b1d841245102895929b51522e39b73 /libvirt-utils.c
parent46b950790565708733ac5b4e3938cf87bac24cbb (diff)
downloadlibvirt-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.c406
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(&params, &n, &max,
+ hints, nhints, keystr, v) < 0)
+ goto cleanup;
+ }
+ } else if (virPyDictToTypedParamOne(&params, &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) */