diff options
author | Tony Asleson <tasleson@redhat.com> | 2012-10-01 21:59:26 -0700 |
---|---|---|
committer | Andy Grover <agrover@redhat.com> | 2012-10-09 15:13:51 -0700 |
commit | 066be84083005bf2c03f147d10322eb02aaafe2e (patch) | |
tree | 6cd8d2d11a26f5666a7239386f4334dd92fe7ca7 | |
parent | 44f40f7f599b5813d54c1427af99fc877655c303 (diff) | |
download | lvm2-066be84083005bf2c03f147d10322eb02aaafe2e.tar.gz lvm2-066be84083005bf2c03f147d10322eb02aaafe2e.tar.xz lvm2-066be84083005bf2c03f147d10322eb02aaafe2e.zip |
python-lvm: feature parity with liblvm
This patch set brings python-lvm up to date with the features that are currently
in lvm2app.h.
Minimal unit testing has been done at this time.
Signed-off-by: Tony Asleson <tasleson@redhat.com>
Signed-off-by: Andy Grover <agrover@redhat.com>
-rw-r--r-- | liblvm/python/liblvm.c | 497 |
1 files changed, 496 insertions, 1 deletions
diff --git a/liblvm/python/liblvm.c b/liblvm/python/liblvm.c index 79ca9c94..9ab93861 100644 --- a/liblvm/python/liblvm.c +++ b/liblvm/python/liblvm.c @@ -17,7 +17,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authors: Lars Sjostrom (lars sjostrom redhat com) - * Andy Grover (agrover redhat com) + * Andy Grover (agrover redhat com) + * Tony Asleson (tasleson redhat com) * */ @@ -47,9 +48,23 @@ typedef struct { lvmobject *lvm_obj; } pvobject; +typedef struct { + PyObject_HEAD + lvseg_t lv_seg; /* lv segment handle */ + lvmobject *lvm_obj; +} lvsegobject; + +typedef struct { + PyObject_HEAD + pvseg_t pv_seg; /* pv segment handle */ + lvmobject *lvm_obj; +} pvsegobject; + static PyTypeObject LibLVMvgType; static PyTypeObject LibLVMlvType; static PyTypeObject LibLVMpvType; +static PyTypeObject LibLVMlvsegType; +static PyTypeObject LibLVMpvsegType; static PyObject *LibLVMError; @@ -191,6 +206,21 @@ liblvm_lvm_list_vg_uuids(lvmobject *self) } static PyObject * +liblvm_lvm_percent_to_float(lvmobject *self, PyObject *arg) +{ + double converted; + int percent; + + LVM_VALID(self); + + if (!PyArg_ParseTuple(arg, "i", &percent)) + return NULL; + + converted = lvm_percent_to_float(percent); + return Py_BuildValue("d", converted); +} + +static PyObject * liblvm_lvm_vgname_from_pvid(lvmobject *self, PyObject *arg) { const char *pvid; @@ -228,6 +258,31 @@ liblvm_lvm_vgname_from_device(lvmobject *self, PyObject *arg) return Py_BuildValue("s", vgname); } + +static PyObject * +liblvm_lvm_config_find_bool(lvmobject *self, PyObject *arg) +{ + const char *config; + int rval; + PyObject *rc; + + LVM_VALID(self); + + if (!PyArg_ParseTuple(arg, "s", &config)) + return NULL; + + if ((rval = lvm_config_find_bool(self->libh, config, -10)) == -10) { + /* Retrieving error information yields no error in this case */ + PyErr_Format(PyExc_ValueError, "config path not found"); + return NULL; + } + + rc = (rval) ? Py_True: Py_False; + + Py_INCREF(rc); + return rc; +} + static PyObject * liblvm_lvm_config_reload(lvmobject *self) { @@ -602,6 +657,151 @@ liblvm_lvm_vg_get_free_extent_count(vgobject *self) return Py_BuildValue("l", lvm_vg_get_free_extent_count(self->vg)); } +/* Builds a python tuple ([string|number], bool) from a struct lvm_property_value */ +static PyObject * +get_property(lvmobject *h, struct lvm_property_value *prop) +{ + PyObject *pytuple; + PyObject *setable; + + if( !prop->is_valid ) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(h)); + return NULL; + } + + pytuple = PyTuple_New(2); + if (!pytuple) + return NULL; + + if( prop->is_integer ) { + PyTuple_SET_ITEM(pytuple, 0, Py_BuildValue("K", prop->value.integer)); + } else { + PyTuple_SET_ITEM(pytuple, 0, PyString_FromString(prop->value.string)); + } + + if (prop->is_settable) { + setable = Py_True; + } else { + setable = Py_False; + } + + Py_INCREF(setable); + PyTuple_SET_ITEM(pytuple, 1, setable); + return pytuple; +} + +/* This will return a tuple of (value, bool) with the value being a string or + integer and bool indicating if property is settable */ +static PyObject * +liblvm_lvm_vg_get_property(vgobject *self, PyObject *args) +{ + const char *name; + struct lvm_property_value prop_value; + + VG_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + prop_value = lvm_vg_get_property(self->vg, name); + return get_property(self->lvm_obj, &prop_value); +} + +static PyObject * +liblvm_lvm_vg_set_property(vgobject *self, PyObject *args) +{ + const char *property_name = NULL; + PyObject *variant_type_arg = NULL; + struct lvm_property_value lvm_property; + char *string_value = NULL; + + VG_VALID(self); + + if (!PyArg_ParseTuple(args, "sO", &property_name, &variant_type_arg)) + return NULL; + + lvm_property = lvm_vg_get_property(self->vg, property_name); + + if( !lvm_property.is_valid ) { + goto lvmerror; + } + + if(PyObject_IsInstance(variant_type_arg, (PyObject*)&PyString_Type)) { + + if (!lvm_property.is_string) { + PyErr_Format(PyExc_ValueError, "Property requires string value"); + goto bail; + } + + /* Based on cursory code inspection this path may cause a memory + leak when calling into set_property, need to verify*/ + string_value = strdup(PyString_AsString(variant_type_arg)); + lvm_property.value.string = string_value; + if(!lvm_property.value.string) { + PyErr_NoMemory(); + goto bail; + } + + } else { + + if (!lvm_property.is_integer) { + PyErr_Format(PyExc_ValueError, "Property requires numeric value"); + goto bail; + } + + if(PyObject_IsInstance(variant_type_arg, (PyObject*)&PyInt_Type)) { + int temp_py_int = PyInt_AsLong(variant_type_arg); + + /* -1 could be valid, need to see if an exception was gen. */ + if( -1 == temp_py_int ) { + if( PyErr_Occurred() ) { + goto bail; + } + } + + if (temp_py_int < 0) { + PyErr_Format(PyExc_ValueError, "Positive integers only!"); + goto bail; + } + + lvm_property.value.integer = temp_py_int; + } else if(PyObject_IsInstance(variant_type_arg, (PyObject*)&PyLong_Type)){ + /* This will fail on negative numbers */ + unsigned long long temp_py_long = PyLong_AsUnsignedLongLong(variant_type_arg); + if( (unsigned long long)-1 == temp_py_long ) { + goto bail; + } + + lvm_property.value.integer = temp_py_long; + } else { + PyErr_Format(PyExc_ValueError, "supported value types are numeric and string"); + goto bail; + } + } + + if( -1 == lvm_vg_set_property(self->vg, property_name, &lvm_property) ) { + goto lvmerror; + } + + if( -1 == lvm_vg_write(self->vg)) { + goto lvmerror; + } + + Py_DECREF(variant_type_arg); + Py_INCREF(Py_None); + return Py_None; + +lvmerror: + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); +bail: + free(string_value); + if( variant_type_arg ) { + Py_DECREF(variant_type_arg); + variant_type_arg = NULL; + } + return NULL; +} + static PyObject * liblvm_lvm_vg_get_pv_count(vgobject *self) { @@ -781,6 +981,89 @@ liblvm_lvm_vg_list_pvs(vgobject *vg) return pytuple; } +typedef lv_t (*lv_fetch_by_N)(vg_t vg, const char *id); +typedef pv_t (*pv_fetch_by_N)(vg_t vg, const char *id); + +static PyObject * +liblvm_lvm_lv_from_N(vgobject *self, PyObject *arg, lv_fetch_by_N method) +{ + const char *id; + lvobject *rc; + lv_t lv = NULL; + + VG_VALID(self); + + if (!PyArg_ParseTuple(arg, "s", &id)) + return NULL; + + lv = method(self->vg, id); + if( !lv ) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + rc = PyObject_New(lvobject, &LibLVMlvType); + if( !rc ) { + return NULL; + } + + rc->lv = lv; + rc->lvm_obj = self->lvm_obj; + return (PyObject *)rc; +} + +static PyObject * +liblvm_lvm_lv_from_name(vgobject *self, PyObject *arg) +{ + return liblvm_lvm_lv_from_N(self, arg, lvm_lv_from_name); +} + +static PyObject * +liblvm_lvm_lv_from_uuid(vgobject *self, PyObject *arg) +{ + return liblvm_lvm_lv_from_N(self, arg, lvm_lv_from_uuid); +} + +static PyObject * +liblvm_lvm_pv_from_N(vgobject *self, PyObject *arg, pv_fetch_by_N method) +{ + const char *id; + pvobject *rc; + pv_t pv = NULL; + + VG_VALID(self); + + if (!PyArg_ParseTuple(arg, "s", &id)) + return NULL; + + pv = method(self->vg, id); + if( !pv ) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + rc = PyObject_New(pvobject, &LibLVMpvType); + if( !rc ) { + return NULL; + } + + rc->pv = pv; + rc->lvm_obj = self->lvm_obj; + return (PyObject *)rc; +} + +static PyObject * +liblvm_lvm_pv_from_name(vgobject *self, PyObject *arg) +{ + return liblvm_lvm_pv_from_N(self, arg, lvm_pv_from_name); +} + +static PyObject * +liblvm_lvm_pv_from_uuid(vgobject *self, PyObject *arg) +{ + return liblvm_lvm_pv_from_N(self, arg, lvm_pv_from_uuid); +} + static void liblvm_pv_dealloc(pvobject *self) { @@ -864,6 +1147,23 @@ liblvm_lvm_vg_remove_lv(lvobject *self) return Py_None; } +/* This will return a tuple of (value, bool) with the value being a string or + integer and bool indicating if property is settable */ +static PyObject * +liblvm_lvm_lv_get_property(lvobject *self, PyObject *args) +{ + const char *name; + struct lvm_property_value prop_value; + + LV_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + prop_value = lvm_lv_get_property(self->lv, name); + return get_property(self->lvm_obj, &prop_value); +} + static PyObject * liblvm_lvm_lv_get_size(lvobject *self) { @@ -969,6 +1269,26 @@ liblvm_lvm_lv_get_tags(lvobject *self) } static PyObject * +liblvm_lvm_lv_rename(lvobject *self, PyObject *args) +{ + const char *new_name; + int rval; + + LV_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &new_name)) + return NULL; + + if ((rval = lvm_lv_rename(self->lv, new_name)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * liblvm_lvm_lv_resize(lvobject *self, PyObject *args) { uint64_t new_size; @@ -989,8 +1309,53 @@ liblvm_lvm_lv_resize(lvobject *self, PyObject *args) return Py_None; } +static PyObject * +liblvm_lvm_lv_list_lvsegs(lvobject *lv) +{ + struct dm_list *lvsegs; + lvseg_list_t *lvsegl; + PyObject * pytuple; + lvsegobject *self; + int i = 0; + + LV_VALID(lv); + + lvsegs = lvm_lv_list_lvsegs(lv->lv); + if(!lvsegs) { + return Py_BuildValue("()"); + } + + pytuple = PyTuple_New(dm_list_size(lvsegs)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(lvsegl, lvsegs) { + /* Create and initialize the object */ + self = PyObject_New(lvsegobject, &LibLVMlvsegType); + if (!self) { + Py_DECREF(pytuple); + return NULL; + } + + self->lv_seg = lvsegl->lvseg; + self->lvm_obj = lv->lvm_obj; + PyTuple_SET_ITEM(pytuple, i, (PyObject *) self); + i++; + } + + return pytuple; +} + /* PV Methods */ +#define PV_VALID(pvobject) \ + do { \ + if (!pvobject->pv || !pvobject->lvm_obj) { \ + PyErr_SetString(PyExc_UnboundLocalError, "PV object invalid"); \ + return NULL; \ + } \ + } while (0) + static PyObject * liblvm_lvm_pv_get_name(pvobject *self) { @@ -1010,6 +1375,21 @@ liblvm_lvm_pv_get_mda_count(pvobject *self) } static PyObject * +liblvm_lvm_pv_get_property(pvobject *self, PyObject *args) +{ + const char *name; + struct lvm_property_value prop_value; + + PV_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + prop_value = lvm_pv_get_property(self->pv, name); + return get_property(self->lvm_obj, &prop_value); +} + +static PyObject * liblvm_lvm_pv_get_dev_size(pvobject *self) { return Py_BuildValue("l", lvm_pv_get_dev_size(self->pv)); @@ -1046,6 +1426,85 @@ liblvm_lvm_pv_resize(pvobject *self, PyObject *args) return Py_None; } +static PyObject * +liblvm_lvm_lv_list_pvsegs(pvobject *pv) +{ + struct dm_list *pvsegs; + pvseg_list_t *pvsegl; + PyObject *pytuple; + pvsegobject *self; + int i = 0; + + PV_VALID(pv); + + pvsegs = lvm_pv_list_pvsegs(pv->pv); + if(!pvsegs) { + return Py_BuildValue("()"); + } + + pytuple = PyTuple_New(dm_list_size(pvsegs)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(pvsegl, pvsegs) { + /* Create and initialize the object */ + self = PyObject_New(pvsegobject, &LibLVMpvsegType); + if (!self) { + Py_DECREF(pytuple); + return NULL; + } + + self->pv_seg = pvsegl->pvseg; + self->lvm_obj = pv->lvm_obj; + PyTuple_SET_ITEM(pytuple, i, (PyObject *) self); + i++; + } + + return pytuple; +} + +/* LV seg methods */ + +static void +liblvm_lvseg_dealloc(lvsegobject *self) +{ + PyObject_Del(self); +} + +static PyObject * +liblvm_lvm_lvseg_get_property(lvsegobject *self, PyObject *args) +{ + const char *name; + struct lvm_property_value prop_value; + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + prop_value = lvm_lvseg_get_property(self->lv_seg, name); + return get_property(self->lvm_obj, &prop_value); +} + +/* PV seg methods */ + +static void +liblvm_pvseg_dealloc(pvsegobject *self) +{ + PyObject_Del(self); +} + +static PyObject * +liblvm_lvm_pvseg_get_property(pvsegobject *self, PyObject *args) +{ + const char *name; + struct lvm_property_value prop_value; + + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + prop_value = lvm_pvseg_get_property(self->pv_seg, name); + return get_property(self->lvm_obj, &prop_value); +} + /* ---------------------------------------------------------------------- * Method tables and other bureaucracy */ @@ -1138,6 +1597,16 @@ static PyMethodDef liblvm_pv_methods[] = { { NULL, NULL} /* sentinel */ }; +static PyMethodDef liblvm_lvseg_methods[] = { + { "getProperty", (PyCFunction)liblvm_lvm_lvseg_get_property, METH_VARARGS }, + { NULL, NULL} /* sentinel */ +}; + +static PyMethodDef liblvm_pvseg_methods[] = { + { "getProperty", (PyCFunction)liblvm_lvm_pvseg_get_property, METH_VARARGS }, + { NULL, NULL} /* sentinel */ +}; + static PyTypeObject LiblvmType = { PyObject_HEAD_INIT(&PyType_Type) .tp_name = "liblvm.Liblvm", @@ -1183,6 +1652,28 @@ static PyTypeObject LibLVMpvType = { .tp_methods = liblvm_pv_methods, }; +static PyTypeObject LibLVMlvsegType = { + PyObject_HEAD_INIT(&PyType_Type) + .tp_name = "liblvm.Liblvm_lvseg", + .tp_basicsize = sizeof(lvsegobject), + .tp_new = PyType_GenericNew, + .tp_dealloc = (destructor)liblvm_lvseg_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "LVM Logical Volume Segment object", + .tp_methods = liblvm_lvseg_methods, +}; + +static PyTypeObject LibLVMpvsegType = { + PyObject_HEAD_INIT(&PyType_Type) + .tp_name = "liblvm.Liblvm_pvseg", + .tp_basicsize = sizeof(pvsegobject), + .tp_new = PyType_GenericNew, + .tp_dealloc = (destructor)liblvm_pvseg_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "LVM Physical Volume Segment object", + .tp_methods = liblvm_pvseg_methods, +}; + PyMODINIT_FUNC initlvm(void) { @@ -1196,6 +1687,10 @@ initlvm(void) return; if (PyType_Ready(&LibLVMpvType) < 0) return; + if (PyType_Ready(&LibLVMlvsegType) < 0) + return; + if (PyType_Ready(&LibLVMpvsegType) < 0) + return; m = Py_InitModule3("lvm", Liblvm_methods, "Liblvm module"); if (m == NULL) |