| /* |
| * Liblvm -- Python interface to LVM2 API. |
| * |
| * Copyright (C) 2010, 2013 Red Hat, Inc. All rights reserved. |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU Lesser General Public License as published by |
| * the Free Software Foundation, either version 2.1 of the License, or |
| * (at your option) any later version. |
| |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU Lesser General Public License for more details. |
| |
| * You should have received a copy of the GNU Lesser General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| * |
| * Authors: Lars Sjostrom (lars sjostrom redhat com) |
| * Andy Grover (agrover redhat com) |
| * Tony Asleson (tasleson redhat com) |
| */ |
| |
| #include <Python.h> |
| #include "lvm2app.h" |
| #include "defaults.h" |
| |
| #if PY_MAJOR_VERSION >= 3 |
| #define IS_PY3K |
| #define PYINTTYPE_CHECK PyLong_Check |
| #define PYINTTYPE_ASLONG PyLong_AsLong |
| #define PYINTTYPE_FROMLONG PyLong_FromLong |
| #define PYSTRYPE_CHECK PyUnicode_Check |
| #define PYSTRTYPE_ASSTRING PyUnicode_AsUTF8 |
| #define PYSTRTYPE_FROMSTRING PyUnicode_FromString |
| #else |
| #define PYINTTYPE_CHECK PyInt_Check |
| #define PYINTTYPE_ASLONG PyInt_AsLong |
| #define PYINTTYPE_FROMLONG PyInt_FromLong |
| #define PYSTRYPE_CHECK PyString_Check |
| #define PYSTRTYPE_ASSTRING PyString_AsString |
| #define PYSTRTYPE_FROMSTRING PyString_FromString |
| #endif |
| |
| static lvm_t _libh; |
| |
| |
| typedef struct { |
| PyObject_HEAD |
| vg_t vg; /* vg handle */ |
| lvm_t libh_copy; |
| } vgobject; |
| |
| typedef struct { |
| PyObject_HEAD |
| struct dm_list *pvslist; |
| lvm_t libh_copy; |
| } pvslistobject; |
| |
| typedef struct { |
| PyObject_HEAD |
| lv_t lv; /* lv handle */ |
| vgobject *parent_vgobj; |
| } lvobject; |
| |
| typedef struct { |
| PyObject_HEAD |
| pv_t pv; /* pv handle */ |
| vgobject *parent_vgobj; |
| pvslistobject *parent_pvslistobj; |
| } pvobject; |
| |
| typedef struct { |
| PyObject_HEAD |
| lvseg_t lv_seg; /* lv segment handle */ |
| lvobject *parent_lvobj; |
| } lvsegobject; |
| |
| typedef struct { |
| PyObject_HEAD |
| pvseg_t pv_seg; /* pv segment handle */ |
| pvobject *parent_pvobj; |
| } pvsegobject; |
| |
| static PyTypeObject _LibLVMvgType; |
| static PyTypeObject _LibLVMlvType; |
| static PyTypeObject _LibLVMpvlistType; |
| static PyTypeObject _LibLVMpvType; |
| static PyTypeObject _LibLVMlvsegType; |
| static PyTypeObject _LibLVMpvsegType; |
| |
| static PyObject *_LibLVMError; |
| |
| #define LVM_VALID(ptr) \ |
| do { \ |
| if (!_libh) { \ |
| _libh = lvm_init(NULL); \ |
| } \ |
| if (ptr && _libh) { \ |
| if (ptr != _libh) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "LVM handle reference stale"); \ |
| return NULL; \ |
| } \ |
| } else if (!_libh) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "LVM handle invalid"); \ |
| return NULL; \ |
| } \ |
| } while (0) |
| |
| /** |
| * Ensure that we initialize all the bits to a sane state. |
| */ |
| static pvobject *_create_py_pv(void) |
| { |
| pvobject * pvobj = PyObject_New(pvobject, &_LibLVMpvType); |
| |
| if (pvobj) { |
| pvobj->pv = NULL; |
| pvobj->parent_vgobj = NULL; |
| pvobj->parent_pvslistobj = NULL; |
| } |
| |
| return pvobj; |
| } |
| |
| static vgobject *_create_py_vg(void) |
| { |
| vgobject *vgobj = PyObject_New(vgobject, &_LibLVMvgType); |
| |
| if (vgobj) { |
| vgobj->vg = NULL; |
| vgobj->libh_copy = _libh; |
| } |
| |
| return vgobj; |
| } |
| |
| static pvslistobject *_create_py_pvlist(void) |
| { |
| pvslistobject *pvlistobj = PyObject_New(pvslistobject, &_LibLVMpvlistType); |
| |
| if (pvlistobj) { |
| pvlistobj->pvslist = NULL; |
| pvlistobj->libh_copy = _libh; |
| } |
| |
| return pvlistobj; |
| } |
| |
| static lvobject *_create_py_lv(vgobject *parent, lv_t lv) |
| { |
| lvobject * lvobj = PyObject_New(lvobject, &_LibLVMlvType); |
| if (lvobj) { |
| lvobj->parent_vgobj = parent; |
| Py_INCREF(lvobj->parent_vgobj); |
| lvobj->lv = lv; |
| } |
| return lvobj; |
| } |
| |
| static PyObject *_liblvm_get_last_error(void) |
| { |
| PyObject *info; |
| const char *msg = NULL; |
| |
| LVM_VALID(NULL); |
| |
| if (!(info = PyTuple_New(2))) |
| return NULL; |
| |
| PyTuple_SetItem(info, 0, PYINTTYPE_FROMLONG((long) lvm_errno(_libh))); |
| msg = lvm_errmsg(_libh); |
| PyTuple_SetItem(info, 1, ((msg) ? PYSTRTYPE_FROMSTRING(msg) : |
| PYSTRTYPE_FROMSTRING("Memory error while retrieving error message"))); |
| |
| return info; |
| } |
| |
| static PyObject *_liblvm_library_get_version(void) |
| { |
| return Py_BuildValue("s", lvm_library_get_version()); |
| } |
| |
| static const char _gc_doc[] = "Garbage collect the C library"; |
| |
| static PyObject *_liblvm_lvm_gc(void) |
| { |
| if (_libh) { |
| lvm_quit(_libh); |
| _libh = NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_list_vg_names(void) |
| { |
| struct dm_list *vgnames; |
| struct lvm_str_list *strl; |
| PyObject * pytuple; |
| int i = 0; |
| |
| LVM_VALID(NULL); |
| |
| if (!(vgnames = lvm_list_vg_names(_libh))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(vgnames)))) |
| return NULL; |
| |
| dm_list_iterate_items(strl, vgnames) { |
| PyTuple_SET_ITEM(pytuple, i, PYSTRTYPE_FROMSTRING(strl->str)); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_list_vg_uuids(void) |
| { |
| struct dm_list *uuids; |
| struct lvm_str_list *strl; |
| PyObject * pytuple; |
| int i = 0; |
| |
| LVM_VALID(NULL); |
| |
| if (!(uuids = lvm_list_vg_uuids(_libh))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(uuids)))) |
| return NULL; |
| |
| dm_list_iterate_items(strl, uuids) { |
| PyTuple_SET_ITEM(pytuple, i, PYSTRTYPE_FROMSTRING(strl->str)); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_pvlist_get(pvslistobject *pvsobj) |
| { |
| struct lvm_pv_list *pvl; |
| PyObject * pytuple; |
| pvobject * pvobj; |
| int i = 0; |
| |
| /* unlike other LVM api calls, if there are no results, we get NULL */ |
| pvsobj->pvslist = lvm_list_pvs(_libh); |
| |
| if (!pvsobj->pvslist) |
| return Py_BuildValue("()"); |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(pvsobj->pvslist)))) |
| return NULL; |
| |
| dm_list_iterate_items(pvl, pvsobj->pvslist) { |
| /* Create and initialize the object */ |
| if (!(pvobj = _create_py_pv())) { |
| Py_DECREF(pytuple); |
| return NULL; |
| } |
| |
| /* We don't have a parent vg object to be concerned about */ |
| pvobj->parent_vgobj = NULL; |
| pvobj->parent_pvslistobj = pvsobj; |
| Py_INCREF(pvobj->parent_pvslistobj); |
| |
| pvobj->pv = pvl->pv; |
| PyTuple_SET_ITEM(pytuple, i, (PyObject *) pvobj); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_pvlist_put(pvslistobject *self) |
| { |
| if (self->pvslist) { |
| if (lvm_list_pvs_free(self->pvslist)) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| self->pvslist = NULL; |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_pvlist_dealloc(pvslistobject *self) |
| { |
| if (self->pvslist) |
| _liblvm_lvm_pvlist_put(self); |
| |
| PyObject_Del(self); |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_list_pvs(void) |
| { |
| LVM_VALID(NULL); |
| |
| return (PyObject *)_create_py_pvlist(); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_remove(PyObject *self, PyObject *arg) |
| { |
| const char *pv_name; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s", &pv_name)) |
| return NULL; |
| |
| if (lvm_pv_remove(_libh, pv_name) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static int _set_pv_numeric_prop(pv_create_params_t pv_params, const char *name, |
| unsigned long long value) |
| { |
| struct lvm_property_value prop_value = { |
| .is_integer = 1, |
| .value.integer = value, |
| }; |
| |
| return lvm_pv_params_set_property(pv_params, name, &prop_value); |
| } |
| |
| #define SET_PV_PROP(params, name, value) \ |
| do { \ |
| if (_set_pv_numeric_prop(params, name, value) == -1) \ |
| goto error; \ |
| } while(0)\ |
| |
| static PyObject *_liblvm_lvm_pv_create(PyObject *self, PyObject *arg) |
| { |
| const char *pv_name; |
| unsigned long long size = 0; |
| unsigned long long pvmetadatacopies = DEFAULT_PVMETADATACOPIES; |
| unsigned long long pvmetadatasize = DEFAULT_PVMETADATASIZE; |
| unsigned long long data_alignment = 0; |
| unsigned long long data_alignment_offset = 0; |
| unsigned long long zero = 1; |
| pv_create_params_t pv_params = NULL; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s|KKKKKK", &pv_name, &size, &pvmetadatacopies, |
| &pvmetadatasize, &data_alignment, |
| &data_alignment_offset, &zero)) |
| return NULL; |
| |
| pv_params = lvm_pv_params_create(_libh, pv_name); |
| if (!pv_params) { |
| goto error; |
| } |
| |
| SET_PV_PROP(pv_params, "size", size); |
| SET_PV_PROP(pv_params, "pvmetadatacopies", pvmetadatacopies); |
| SET_PV_PROP(pv_params, "pvmetadatasize", pvmetadatasize); |
| SET_PV_PROP(pv_params, "data_alignment", data_alignment); |
| SET_PV_PROP(pv_params, "data_alignment_offset", data_alignment_offset); |
| SET_PV_PROP(pv_params, "zero", zero); |
| |
| if (lvm_pv_create_adv(pv_params)) { |
| goto error; |
| } |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_percent_to_float(PyObject *self, PyObject *arg) |
| { |
| double converted; |
| int percent; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "i", &percent)) |
| return NULL; |
| |
| converted = lvm_percent_to_float(percent); |
| |
| return Py_BuildValue("d", converted); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_name_validate(PyObject *self, PyObject *arg) |
| { |
| const char *name; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s", &name)) |
| return NULL; |
| |
| if (lvm_vg_name_validate(_libh, name) < 0) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_vgname_from_pvid(PyObject *self, PyObject *arg) |
| { |
| const char *pvid; |
| const char *vgname; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s", &pvid)) |
| return NULL; |
| |
| if (!(vgname = lvm_vgname_from_pvid(_libh, pvid))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| return Py_BuildValue("s", vgname); |
| } |
| |
| static PyObject *_liblvm_lvm_vgname_from_device(PyObject *self, PyObject *arg) |
| { |
| const char *device; |
| const char *vgname; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s", &device)) |
| return NULL; |
| |
| if (!(vgname = lvm_vgname_from_device(_libh, device))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| return Py_BuildValue("s", vgname); |
| } |
| |
| |
| static PyObject *_liblvm_lvm_config_find_bool(PyObject *self, PyObject *arg) |
| { |
| const char *config; |
| int rval; |
| PyObject *rc; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s", &config)) |
| return NULL; |
| |
| if ((rval = lvm_config_find_bool(_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(void) |
| { |
| LVM_VALID(NULL); |
| |
| if (lvm_config_reload(_libh) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| |
| static PyObject *_liblvm_lvm_scan(void) |
| { |
| LVM_VALID(NULL); |
| |
| if (lvm_scan(_libh) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_config_override(PyObject *self, PyObject *arg) |
| { |
| const char *config; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(arg, "s", &config)) |
| return NULL; |
| |
| if (lvm_config_override(_libh, config) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| /* ---------------------------------------------------------------------- |
| * VG object initialization/deallocation |
| */ |
| |
| |
| static PyObject *_liblvm_lvm_vg_open(PyObject *self, PyObject *args) |
| { |
| const char *vgname; |
| const char *mode = NULL; |
| |
| vgobject *vgobj; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(args, "s|s", &vgname, &mode)) |
| return NULL; |
| |
| if (mode == NULL) |
| mode = "r"; |
| |
| if (!(vgobj = _create_py_vg())) |
| return NULL; |
| |
| if (!(vgobj->vg = lvm_vg_open(_libh, vgname, mode, 0))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| Py_DECREF(vgobj); |
| return NULL; |
| } |
| |
| return (PyObject *)vgobj; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_create(PyObject *self, PyObject *args) |
| { |
| const char *vgname; |
| vgobject *vgobj; |
| |
| LVM_VALID(NULL); |
| |
| if (!PyArg_ParseTuple(args, "s", &vgname)) |
| return NULL; |
| |
| if (!(vgobj = _create_py_vg())) |
| return NULL; |
| |
| if (!(vgobj->vg = lvm_vg_create(_libh, vgname))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| Py_DECREF(vgobj); |
| return NULL; |
| } |
| |
| return (PyObject *)vgobj; |
| } |
| |
| static void liblvm_vg_dealloc(vgobject *self) |
| { |
| /* if already closed, don't reclose it */ |
| if (self->vg != NULL) { |
| lvm_vg_close(self->vg); |
| self->vg = NULL; |
| self->libh_copy = NULL; |
| } |
| |
| PyObject_Del(self); |
| } |
| |
| /* VG Methods */ |
| |
| #define VG_VALID(vgobject) \ |
| do { \ |
| if (!vgobject || !vgobject->vg) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "VG object invalid"); \ |
| return NULL; \ |
| } \ |
| LVM_VALID(vgobject->libh_copy); \ |
| } while (0) |
| |
| #define PVSLIST_VALID(pvslistobject) \ |
| do { \ |
| if (!pvslistobject || !pvslistobject->pvslist) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "PVS object invalid"); \ |
| return NULL; \ |
| } \ |
| LVM_VALID(pvslistobject->libh_copy); \ |
| } while (0) |
| |
| static PyObject *_liblvm_lvm_vg_close(vgobject *self) |
| { |
| /* if already closed, don't reclose it */ |
| if (self->vg) { |
| if (lvm_vg_close(self->vg) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| self->vg = NULL; |
| self->libh_copy = NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_name(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("s", lvm_vg_get_name(self->vg)); |
| } |
| |
| |
| static PyObject *_liblvm_lvm_vg_get_uuid(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("s", lvm_vg_get_uuid(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_remove(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| if (lvm_vg_remove(self->vg) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->vg) == -1) |
| goto error; |
| |
| /* Not much you can do with a vg that is removed so close it */ |
| return _liblvm_lvm_vg_close(self); |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_extend(vgobject *self, PyObject *args) |
| { |
| const char *device; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &device)) { |
| return NULL; |
| } |
| |
| if (lvm_vg_extend(self->vg, device) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->vg) == -1) |
| goto error; |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_reduce(vgobject *self, PyObject *args) |
| { |
| const char *device; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &device)) |
| return NULL; |
| |
| if (lvm_vg_reduce(self->vg, device) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->vg) == -1) |
| goto error; |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_add_tag(vgobject *self, PyObject *args) |
| { |
| const char *tag; |
| int rval; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &tag)) { |
| return NULL; |
| } |
| if ((rval = lvm_vg_add_tag(self->vg, tag)) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->vg) == -1) |
| goto error; |
| |
| return Py_BuildValue("i", rval); |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_remove_tag(vgobject *self, PyObject *args) |
| { |
| const char *tag; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &tag)) |
| return NULL; |
| |
| if (lvm_vg_remove_tag(self->vg, tag) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->vg) == -1) |
| goto error; |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_is_clustered(vgobject *self) |
| { |
| PyObject *rval; |
| |
| VG_VALID(self); |
| |
| rval = ( lvm_vg_is_clustered(self->vg) == 1) ? Py_True : Py_False; |
| |
| Py_INCREF(rval); |
| |
| return rval; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_is_exported(vgobject *self) |
| { |
| PyObject *rval; |
| |
| VG_VALID(self); |
| |
| rval = ( lvm_vg_is_exported(self->vg) == 1) ? Py_True : Py_False; |
| |
| Py_INCREF(rval); |
| |
| return rval; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_is_partial(vgobject *self) |
| { |
| PyObject *rval; |
| |
| VG_VALID(self); |
| |
| rval = ( lvm_vg_is_partial(self->vg) == 1) ? Py_True : Py_False; |
| |
| Py_INCREF(rval); |
| |
| return rval; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_seqno(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_seqno(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_size(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_size(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_free_size(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_free_size(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_extent_size(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_extent_size(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_extent_count(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_extent_count(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_free_extent_count(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)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(struct lvm_property_value *prop) |
| { |
| PyObject *pytuple; |
| PyObject *setable; |
| |
| if (!prop->is_valid) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(pytuple = PyTuple_New(2))) |
| return NULL; |
| |
| if (prop->is_integer) { |
| if (prop->is_signed) { |
| PyTuple_SET_ITEM(pytuple, 0, Py_BuildValue("L", prop->value.signed_integer)); |
| } else { |
| PyTuple_SET_ITEM(pytuple, 0, Py_BuildValue("K", prop->value.integer)); |
| } |
| } else { |
| if ( prop->value.string ) { |
| PyTuple_SET_ITEM(pytuple, 0, PYSTRTYPE_FROMSTRING(prop->value.string)); |
| } else { |
| PyTuple_SET_ITEM(pytuple, 0, Py_None); |
| } |
| } |
| |
| 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(&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; |
| int temp_py_int; |
| unsigned long long temp_py_long; |
| |
| 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 (PYSTRYPE_CHECK(variant_type_arg)) { |
| |
| if (!lvm_property.is_string) { |
| PyErr_Format(PyExc_ValueError, "Property requires string value"); |
| goto bail; |
| } |
| |
| if (!(string_value = PYSTRTYPE_ASSTRING(variant_type_arg))) { |
| PyErr_NoMemory(); |
| goto bail; |
| } |
| |
| lvm_property.value.string = string_value; |
| } else { |
| |
| if (!lvm_property.is_integer) { |
| PyErr_Format(PyExc_ValueError, "Property requires numeric value"); |
| goto bail; |
| } |
| |
| if (PYINTTYPE_CHECK(variant_type_arg)) { |
| temp_py_int = PYINTTYPE_ASLONG(variant_type_arg); |
| |
| /* -1 could be valid, need to see if an exception was gen. */ |
| if (temp_py_int == -1 && 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)){ |
| /* If PyLong_AsUnsignedLongLong function fails an OverflowError is |
| * raised and (unsigned long long)-1 is returned |
| */ |
| if ((temp_py_long = PyLong_AsUnsignedLongLong(variant_type_arg)) == ~0ULL) |
| goto bail; |
| |
| lvm_property.value.integer = temp_py_long; |
| } else { |
| PyErr_Format(PyExc_ValueError, "supported value types are numeric and string"); |
| goto bail; |
| } |
| } |
| |
| if (lvm_vg_set_property(self->vg, property_name, &lvm_property) == -1) |
| goto lvmerror; |
| |
| if (lvm_vg_write(self->vg) == -1) |
| goto lvmerror; |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| |
| lvmerror: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| bail: |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_pv_count(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_pv_count(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_max_pv(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_max_pv(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_max_lv(vgobject *self) |
| { |
| VG_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_vg_get_max_lv(self->vg)); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_set_extent_size(vgobject *self, PyObject *args) |
| { |
| unsigned int new_size; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "I", &new_size)) |
| return NULL; |
| |
| if (lvm_vg_set_extent_size(self->vg, new_size) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_list_lvs(vgobject *self) |
| { |
| struct dm_list *lvs; |
| struct lvm_lv_list *lvl; |
| PyObject * pytuple; |
| lvobject * lvobj; |
| int i = 0; |
| |
| VG_VALID(self); |
| |
| /* unlike other LVM api calls, if there are no results, we get NULL */ |
| if (!(lvs = lvm_vg_list_lvs(self->vg))) |
| return Py_BuildValue("()"); |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(lvs)))) |
| return NULL; |
| |
| dm_list_iterate_items(lvl, lvs) { |
| /* Create and initialize the object */ |
| if (!(lvobj = _create_py_lv(self, lvl->lv))) { |
| Py_DECREF(pytuple); |
| return NULL; |
| } |
| |
| PyTuple_SET_ITEM(pytuple, i, (PyObject *) lvobj); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_get_tags(vgobject *self) |
| { |
| struct dm_list *tagsl; |
| struct lvm_str_list *strl; |
| PyObject * pytuple; |
| int i = 0; |
| |
| VG_VALID(self); |
| |
| if (!(tagsl = lvm_vg_get_tags(self->vg))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(tagsl)))) |
| return NULL; |
| |
| dm_list_iterate_items(strl, tagsl) { |
| PyTuple_SET_ITEM(pytuple, i, PYSTRTYPE_FROMSTRING(strl->str)); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_create_lv_linear(vgobject *self, PyObject *args) |
| { |
| const char *vgname; |
| unsigned long long size; |
| lv_t lv; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "sK", &vgname, &size)) |
| return NULL; |
| |
| if (!(lv = lvm_vg_create_lv_linear(self->vg, vgname, size))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| return (PyObject *)_create_py_lv(self, lv); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_create_lv_thinpool(vgobject *self, PyObject *args) |
| { |
| unsigned long long size = 0; |
| unsigned long long meta_size = 0; |
| const char *pool_name; |
| unsigned long chunk_size = 0; |
| int skip_zero = 0; |
| lvm_thin_discards_t discard = LVM_THIN_DISCARDS_PASSDOWN; |
| lv_t lv; |
| lv_create_params_t lvp = NULL; |
| struct lvm_property_value prop_value; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "sK|kKii", &pool_name, &size, &chunk_size, |
| &meta_size, &discard, &skip_zero)) |
| return NULL; |
| |
| if (!(lvp = lvm_lv_params_create_thin_pool(self->vg, pool_name, size, chunk_size, |
| meta_size, discard))) { |
| |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (skip_zero) { |
| prop_value = lvm_lv_params_get_property(lvp, "skip_zero"); |
| |
| if (prop_value.is_valid) { |
| prop_value.value.integer = 1; |
| |
| if (lvm_lv_params_set_property(lvp, "skip_zero", |
| &prop_value) == -1) { |
| goto error; |
| } |
| } |
| } |
| |
| if (!(lv = lvm_lv_create(lvp))) { |
| goto error; |
| } |
| |
| return (PyObject *)_create_py_lv(self, lv); |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_create_lv_thin(vgobject *self, PyObject *args) |
| { |
| const char *pool_name; |
| const char *lv_name; |
| unsigned long long size = 0; |
| lv_t lv; |
| lv_create_params_t lvp = NULL; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "ssK", &pool_name, &lv_name, &size)) |
| return NULL; |
| |
| if (!(lvp = lvm_lv_params_create_thin(self->vg, pool_name, lv_name,size))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(lv = lvm_lv_create(lvp))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| return (PyObject *)_create_py_lv(self, lv); |
| } |
| |
| static void liblvm_lv_dealloc(lvobject *self) |
| { |
| /* We can dealloc an object that didn't get fully created */ |
| if (self->parent_vgobj) { |
| Py_DECREF(self->parent_vgobj); |
| } |
| |
| PyObject_Del(self); |
| } |
| |
| static PyObject *_liblvm_lvm_vg_list_pvs(vgobject *self) |
| { |
| struct dm_list *pvs; |
| struct lvm_pv_list *pvl; |
| PyObject * pytuple; |
| pvobject * pvobj; |
| int i = 0; |
| |
| VG_VALID(self); |
| |
| /* unlike other LVM api calls, if there are no results, we get NULL */ |
| if (!(pvs = lvm_vg_list_pvs(self->vg))) |
| return Py_BuildValue("()"); |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(pvs)))) |
| return NULL; |
| |
| dm_list_iterate_items(pvl, pvs) { |
| /* Create and initialize the object */ |
| if (!(pvobj = _create_py_pv())) { |
| Py_DECREF(pytuple); |
| return NULL; |
| } |
| |
| pvobj->parent_vgobj = self; |
| Py_INCREF(pvobj->parent_vgobj); |
| |
| pvobj->pv = pvl->pv; |
| PyTuple_SET_ITEM(pytuple, i, (PyObject *) pvobj); |
| i++; |
| } |
| |
| 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; |
| lv_t lv = NULL; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(arg, "s", &id)) |
| return NULL; |
| |
| if (!(lv = method(self->vg, id))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| return (PyObject *)_create_py_lv(self, lv); |
| } |
| |
| 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_lv_name_validate(vgobject *self, PyObject *args) |
| { |
| const char *name; |
| |
| VG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &name)) |
| return NULL; |
| |
| if (lvm_lv_name_validate(self->vg, name) < 0) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| 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; |
| |
| if (!(pv = method(self->vg, id))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(rc = _create_py_pv())) |
| return NULL; |
| |
| Py_INCREF(self); |
| rc->pv = pv; |
| |
| 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) |
| { |
| if (self->parent_vgobj) { |
| Py_DECREF(self->parent_vgobj); |
| } |
| |
| if (self->parent_pvslistobj) { |
| Py_DECREF(self->parent_pvslistobj); |
| } |
| |
| self->parent_vgobj = NULL; |
| self->parent_pvslistobj = NULL; |
| PyObject_Del(self); |
| } |
| |
| /* LV Methods */ |
| |
| #define LV_VALID(lvobject) \ |
| do { \ |
| if (!lvobject || !lvobject->lv) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "LV object invalid"); \ |
| return NULL; \ |
| }\ |
| VG_VALID(lvobject->parent_vgobj); \ |
| } while (0) |
| |
| static PyObject *_liblvm_lvm_lv_get_attr(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| return Py_BuildValue("s", lvm_lv_get_attr(self->lv)); |
| } |
| |
| static PyObject *_liblvm_lvm_lv_get_origin(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| return Py_BuildValue("s", lvm_lv_get_origin(self->lv)); |
| } |
| |
| static PyObject *_liblvm_lvm_lv_get_name(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| return Py_BuildValue("s", lvm_lv_get_name(self->lv)); |
| } |
| |
| static PyObject *_liblvm_lvm_lv_get_uuid(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| return Py_BuildValue("s", lvm_lv_get_uuid(self->lv)); |
| } |
| |
| static PyObject *_liblvm_lvm_lv_activate(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| if (lvm_lv_activate(self->lv) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_deactivate(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| if (lvm_lv_deactivate(self->lv) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_vg_remove_lv(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| if (lvm_vg_remove_lv(self->lv) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| self->lv = NULL; |
| |
| Py_INCREF(Py_None); |
| |
| 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(&prop_value); |
| } |
| |
| static PyObject *_liblvm_lvm_lv_get_size(lvobject *self) |
| { |
| LV_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_lv_get_size(self->lv)); |
| } |
| |
| static PyObject *_liblvm_lvm_lv_is_active(lvobject *self) |
| { |
| PyObject *rval; |
| |
| LV_VALID(self); |
| |
| rval = (lvm_lv_is_active(self->lv) == 1) ? Py_True : Py_False; |
| |
| Py_INCREF(rval); |
| |
| return rval; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_is_suspended(lvobject *self) |
| { |
| PyObject *rval; |
| |
| LV_VALID(self); |
| |
| rval = (lvm_lv_is_suspended(self->lv) == 1) ? Py_True : Py_False; |
| |
| Py_INCREF(rval); |
| |
| return rval; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_add_tag(lvobject *self, PyObject *args) |
| { |
| const char *tag; |
| |
| LV_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &tag)) |
| return NULL; |
| |
| if (lvm_lv_add_tag(self->lv, tag) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->parent_vgobj->vg) == -1) |
| goto error; |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_remove_tag(lvobject *self, PyObject *args) |
| { |
| const char *tag; |
| |
| LV_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &tag)) |
| return NULL; |
| |
| if (lvm_lv_remove_tag(self->lv, tag) == -1) |
| goto error; |
| |
| if (lvm_vg_write(self->parent_vgobj->vg) == -1) |
| goto error; |
| |
| Py_INCREF(Py_None); |
| return Py_None; |
| |
| error: |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_get_tags(lvobject *self) |
| { |
| struct dm_list *tagsl; |
| struct lvm_str_list *strl; |
| PyObject * pytuple; |
| int i = 0; |
| |
| LV_VALID(self); |
| |
| if (!(tagsl = lvm_lv_get_tags(self->lv))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(tagsl)))) |
| return NULL; |
| |
| dm_list_iterate_items(strl, tagsl) { |
| PyTuple_SET_ITEM(pytuple, i, PYSTRTYPE_FROMSTRING(strl->str)); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_rename(lvobject *self, PyObject *args) |
| { |
| const char *new_name; |
| |
| LV_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &new_name)) |
| return NULL; |
| |
| if (lvm_lv_rename(self->lv, new_name) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_resize(lvobject *self, PyObject *args) |
| { |
| unsigned long long new_size; |
| |
| LV_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "K", &new_size)) |
| return NULL; |
| |
| if (lvm_lv_resize(self->lv, new_size) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_list_lvsegs(lvobject *self) |
| { |
| struct dm_list *lvsegs; |
| lvseg_list_t *lvsegl; |
| PyObject * pytuple; |
| lvsegobject *lvsegobj; |
| int i = 0; |
| |
| LV_VALID(self); |
| |
| if (!(lvsegs = lvm_lv_list_lvsegs(self->lv))) |
| return Py_BuildValue("()"); |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(lvsegs)))) |
| return NULL; |
| |
| dm_list_iterate_items(lvsegl, lvsegs) { |
| /* Create and initialize the object */ |
| if (!(lvsegobj = PyObject_New(lvsegobject, &_LibLVMlvsegType))) { |
| Py_DECREF(pytuple); |
| return NULL; |
| } |
| |
| lvsegobj->parent_lvobj = self; |
| Py_INCREF(lvsegobj->parent_lvobj); |
| |
| lvsegobj->lv_seg = lvsegl->lvseg; |
| PyTuple_SET_ITEM(pytuple, i, (PyObject *) lvsegobj); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| static PyObject *_liblvm_lvm_lv_snapshot(lvobject *self, PyObject *args) |
| { |
| const char *snap_name; |
| unsigned long long size = 0; |
| lv_t lv; |
| lv_create_params_t lvp = NULL; |
| |
| LV_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s|K", &snap_name, &size)) |
| return NULL; |
| |
| if (!(lvp = lvm_lv_params_create_snapshot(self->lv, snap_name, size))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| if (!(lv = lvm_lv_create(lvp))) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| return (PyObject *)_create_py_lv(self->parent_vgobj, lv); |
| } |
| |
| /* PV Methods */ |
| |
| #define PV_VALID(pvobject) \ |
| do { \ |
| if (!pvobject || !pvobject->pv) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "PV object invalid"); \ |
| return NULL; \ |
| } \ |
| if (pvobject->parent_vgobj) { \ |
| VG_VALID(pvobject->parent_vgobj); \ |
| } \ |
| if (pvobject->parent_pvslistobj) { \ |
| PVSLIST_VALID(pvobject->parent_pvslistobj); \ |
| } \ |
| } while (0) |
| |
| static PyObject *_liblvm_lvm_pv_get_name(pvobject *self) |
| { |
| PV_VALID(self); |
| |
| return Py_BuildValue("s", lvm_pv_get_name(self->pv)); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_get_uuid(pvobject *self) |
| { |
| PV_VALID(self); |
| |
| return Py_BuildValue("s", lvm_pv_get_uuid(self->pv)); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_get_mda_count(pvobject *self) |
| { |
| PV_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_pv_get_mda_count(self->pv)); |
| } |
| |
| 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(&prop_value); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_get_dev_size(pvobject *self) |
| { |
| PV_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_pv_get_dev_size(self->pv)); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_get_size(pvobject *self) |
| { |
| PV_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_pv_get_size(self->pv)); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_get_free(pvobject *self) |
| { |
| PV_VALID(self); |
| |
| return Py_BuildValue("K", (unsigned long long)lvm_pv_get_free(self->pv)); |
| } |
| |
| static PyObject *_liblvm_lvm_pv_resize(pvobject *self, PyObject *args) |
| { |
| unsigned long long new_size; |
| |
| PV_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "K", &new_size)) |
| return NULL; |
| |
| if (lvm_pv_resize(self->pv, new_size) == -1) { |
| PyErr_SetObject(_LibLVMError, _liblvm_get_last_error()); |
| return NULL; |
| } |
| |
| Py_INCREF(Py_None); |
| |
| return Py_None; |
| } |
| |
| static PyObject *_liblvm_lvm_pv_list_pvsegs(pvobject *self) |
| { |
| struct dm_list *pvsegs; |
| pvseg_list_t *pvsegl; |
| PyObject *pytuple; |
| pvsegobject *pvsegobj; |
| int i = 0; |
| |
| PV_VALID(self); |
| |
| if (!(pvsegs = lvm_pv_list_pvsegs(self->pv))) |
| return Py_BuildValue("()"); |
| |
| if (!(pytuple = PyTuple_New(dm_list_size(pvsegs)))) |
| return NULL; |
| |
| dm_list_iterate_items(pvsegl, pvsegs) { |
| /* Create and initialize the object */ |
| if (!(pvsegobj = PyObject_New(pvsegobject, &_LibLVMpvsegType))) { |
| Py_DECREF(pytuple); |
| return NULL; |
| } |
| |
| pvsegobj->parent_pvobj = self; |
| Py_INCREF(pvsegobj->parent_pvobj); |
| |
| pvsegobj->pv_seg = pvsegl->pvseg; |
| PyTuple_SET_ITEM(pytuple, i, (PyObject *) pvsegobj); |
| i++; |
| } |
| |
| return pytuple; |
| } |
| |
| /* LV seg methods */ |
| |
| /* |
| * No way to close/destroy an lvseg, just need to make sure parents are |
| * still good |
| */ |
| #define LVSEG_VALID(lvsegobject) \ |
| do { \ |
| if ( !lvsegobject || !lvsegobject->parent_lvobj ) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "LV segment object invalid"); \ |
| return NULL; \ |
| } \ |
| LV_VALID(lvsegobject->parent_lvobj); \ |
| } while(0) |
| |
| static void _liblvm_lvseg_dealloc(lvsegobject *self) |
| { |
| Py_DECREF(self->parent_lvobj); |
| PyObject_Del(self); |
| } |
| |
| static PyObject *_liblvm_lvm_lvseg_get_property(lvsegobject *self, PyObject *args) |
| { |
| const char *name; |
| struct lvm_property_value prop_value; |
| |
| LVSEG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &name)) |
| return NULL; |
| |
| prop_value = lvm_lvseg_get_property(self->lv_seg, name); |
| |
| return get_property(&prop_value); |
| } |
| |
| /* PV seg methods */ |
| |
| /* |
| * No way to close/destroy a pvseg, just need to make sure parents are |
| * still good |
| */ |
| #define PVSEG_VALID(pvsegobject) \ |
| do { \ |
| if (!pvsegobject || !pvsegobject->parent_pvobj) { \ |
| PyErr_SetString(PyExc_UnboundLocalError, "PV segment object invalid"); \ |
| return NULL; \ |
| } \ |
| PV_VALID(pvsegobject->parent_pvobj); \ |
| } while(0) |
| |
| static void _liblvm_pvseg_dealloc(pvsegobject *self) |
| { |
| Py_DECREF(self->parent_pvobj); |
| PyObject_Del(self); |
| } |
| |
| static PyObject *_liblvm_lvm_pvseg_get_property(pvsegobject *self, PyObject *args) |
| { |
| const char *name; |
| struct lvm_property_value prop_value; |
| |
| PVSEG_VALID(self); |
| |
| if (!PyArg_ParseTuple(args, "s", &name)) |
| return NULL; |
| |
| prop_value = lvm_pvseg_get_property(self->pv_seg, name); |
| |
| return get_property(&prop_value); |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * Method tables and other bureaucracy |
| */ |
| |
| static PyMethodDef _Liblvm_methods[] = { |
| /* LVM methods */ |
| { "getVersion", (PyCFunction)_liblvm_library_get_version, METH_NOARGS }, |
| { "gc", (PyCFunction)_liblvm_lvm_gc, METH_NOARGS, _gc_doc }, |
| { "vgOpen", (PyCFunction)_liblvm_lvm_vg_open, METH_VARARGS }, |
| { "vgCreate", (PyCFunction)_liblvm_lvm_vg_create, METH_VARARGS }, |
| { "configFindBool", (PyCFunction)_liblvm_lvm_config_find_bool, METH_VARARGS }, |
| { "configReload", (PyCFunction)_liblvm_lvm_config_reload, METH_NOARGS }, |
| { "configOverride", (PyCFunction)_liblvm_lvm_config_override, METH_VARARGS }, |
| { "scan", (PyCFunction)_liblvm_lvm_scan, METH_NOARGS }, |
| { "listVgNames", (PyCFunction)_liblvm_lvm_list_vg_names, METH_NOARGS }, |
| { "listVgUuids", (PyCFunction)_liblvm_lvm_list_vg_uuids, METH_NOARGS }, |
| { "listPvs", (PyCFunction)_liblvm_lvm_list_pvs, METH_NOARGS }, |
| { "pvCreate", (PyCFunction)_liblvm_lvm_pv_create, METH_VARARGS }, |
| { "pvRemove", (PyCFunction)_liblvm_lvm_pv_remove, METH_VARARGS }, |
| { "percentToFloat", (PyCFunction)_liblvm_lvm_percent_to_float, METH_VARARGS }, |
| { "vgNameValidate", (PyCFunction)_liblvm_lvm_vg_name_validate, METH_VARARGS }, |
| { "vgNameFromPvid", (PyCFunction)_liblvm_lvm_vgname_from_pvid, METH_VARARGS }, |
| { "vgNameFromDevice", (PyCFunction)_liblvm_lvm_vgname_from_device, METH_VARARGS }, |
| { NULL, NULL } /* sentinel */ |
| }; |
| |
| static PyMethodDef _liblvm_vg_methods[] = { |
| /* vg methods */ |
| { "getName", (PyCFunction)_liblvm_lvm_vg_get_name, METH_NOARGS }, |
| { "getUuid", (PyCFunction)_liblvm_lvm_vg_get_uuid, METH_NOARGS }, |
| { "close", (PyCFunction)_liblvm_lvm_vg_close, METH_NOARGS }, |
| { "remove", (PyCFunction)_liblvm_lvm_vg_remove, METH_NOARGS }, |
| { "extend", (PyCFunction)_liblvm_lvm_vg_extend, METH_VARARGS }, |
| { "reduce", (PyCFunction)_liblvm_lvm_vg_reduce, METH_VARARGS }, |
| { "addTag", (PyCFunction)_liblvm_lvm_vg_add_tag, METH_VARARGS }, |
| { "removeTag", (PyCFunction)_liblvm_lvm_vg_remove_tag, METH_VARARGS }, |
| { "setExtentSize", (PyCFunction)_liblvm_lvm_vg_set_extent_size, METH_VARARGS }, |
| { "isClustered", (PyCFunction)_liblvm_lvm_vg_is_clustered, METH_NOARGS }, |
| { "isExported", (PyCFunction)_liblvm_lvm_vg_is_exported, METH_NOARGS }, |
| { "isPartial", (PyCFunction)_liblvm_lvm_vg_is_partial, METH_NOARGS }, |
| { "getSeqno", (PyCFunction)_liblvm_lvm_vg_get_seqno, METH_NOARGS }, |
| { "getSize", (PyCFunction)_liblvm_lvm_vg_get_size, METH_NOARGS }, |
| { "getFreeSize", (PyCFunction)_liblvm_lvm_vg_get_free_size, METH_NOARGS }, |
| { "getExtentSize", (PyCFunction)_liblvm_lvm_vg_get_extent_size, METH_NOARGS }, |
| { "getExtentCount", (PyCFunction)_liblvm_lvm_vg_get_extent_count, METH_NOARGS }, |
| { "getFreeExtentCount", (PyCFunction)_liblvm_lvm_vg_get_free_extent_count, METH_NOARGS }, |
| { "getProperty", (PyCFunction)_liblvm_lvm_vg_get_property, METH_VARARGS }, |
| { "setProperty", (PyCFunction)_liblvm_lvm_vg_set_property, METH_VARARGS }, |
| { "getPvCount", (PyCFunction)_liblvm_lvm_vg_get_pv_count, METH_NOARGS }, |
| { "getMaxPv", (PyCFunction)_liblvm_lvm_vg_get_max_pv, METH_NOARGS }, |
| { "getMaxLv", (PyCFunction)_liblvm_lvm_vg_get_max_lv, METH_NOARGS }, |
| { "listLVs", (PyCFunction)_liblvm_lvm_vg_list_lvs, METH_NOARGS }, |
| { "listPVs", (PyCFunction)_liblvm_lvm_vg_list_pvs, METH_NOARGS }, |
| { "lvFromName", (PyCFunction)_liblvm_lvm_lv_from_name, METH_VARARGS }, |
| { "lvFromUuid", (PyCFunction)_liblvm_lvm_lv_from_uuid, METH_VARARGS }, |
| { "lvNameValidate", (PyCFunction)_liblvm_lvm_lv_name_validate, METH_VARARGS }, |
| { "pvFromName", (PyCFunction)_liblvm_lvm_pv_from_name, METH_VARARGS }, |
| { "pvFromUuid", (PyCFunction)_liblvm_lvm_pv_from_uuid, METH_VARARGS }, |
| { "getTags", (PyCFunction)_liblvm_lvm_vg_get_tags, METH_NOARGS }, |
| { "createLvLinear", (PyCFunction)_liblvm_lvm_vg_create_lv_linear, METH_VARARGS }, |
| { "createLvThinpool", (PyCFunction)_liblvm_lvm_vg_create_lv_thinpool, METH_VARARGS }, |
| { "createLvThin", (PyCFunction)_liblvm_lvm_vg_create_lv_thin, METH_VARARGS }, |
| { NULL, NULL } /* sentinel */ |
| }; |
| |
| static PyMethodDef _liblvm_lv_methods[] = { |
| /* lv methods */ |
| { "getAttr", (PyCFunction)_liblvm_lvm_lv_get_attr, METH_NOARGS }, |
| { "getName", (PyCFunction)_liblvm_lvm_lv_get_name, METH_NOARGS }, |
| { "getOrigin", (PyCFunction)_liblvm_lvm_lv_get_origin, METH_NOARGS }, |
| { "getUuid", (PyCFunction)_liblvm_lvm_lv_get_uuid, METH_NOARGS }, |
| { "activate", (PyCFunction)_liblvm_lvm_lv_activate, METH_NOARGS }, |
| { "deactivate", (PyCFunction)_liblvm_lvm_lv_deactivate, METH_NOARGS }, |
| { "remove", (PyCFunction)_liblvm_lvm_vg_remove_lv, METH_NOARGS }, |
| { "getProperty", (PyCFunction)_liblvm_lvm_lv_get_property, METH_VARARGS }, |
| { "getSize", (PyCFunction)_liblvm_lvm_lv_get_size, METH_NOARGS }, |
| { "isActive", (PyCFunction)_liblvm_lvm_lv_is_active, METH_NOARGS }, |
| { "isSuspended", (PyCFunction)_liblvm_lvm_lv_is_suspended, METH_NOARGS }, |
| { "addTag", (PyCFunction)_liblvm_lvm_lv_add_tag, METH_VARARGS }, |
| { "removeTag", (PyCFunction)_liblvm_lvm_lv_remove_tag, METH_VARARGS }, |
| { "getTags", (PyCFunction)_liblvm_lvm_lv_get_tags, METH_NOARGS }, |
| { "rename", (PyCFunction)_liblvm_lvm_lv_rename, METH_VARARGS }, |
| { "resize", (PyCFunction)_liblvm_lvm_lv_resize, METH_VARARGS }, |
| { "listLVsegs", (PyCFunction)_liblvm_lvm_lv_list_lvsegs, METH_NOARGS }, |
| { "snapshot", (PyCFunction)_liblvm_lvm_lv_snapshot, METH_VARARGS }, |
| { NULL, NULL } /* sentinel */ |
| }; |
| |
| static PyMethodDef _liblvm_pv_list_methods[] = { |
| /* pv list methods */ |
| { "__enter__", (PyCFunction)_liblvm_lvm_pvlist_get, METH_VARARGS }, |
| { "__exit__", (PyCFunction)_liblvm_lvm_pvlist_put, METH_VARARGS }, |
| { "open", (PyCFunction)_liblvm_lvm_pvlist_get, METH_VARARGS }, |
| { "close", (PyCFunction)_liblvm_lvm_pvlist_put, METH_VARARGS }, |
| { NULL, NULL } |
| }; |
| |
| static PyMethodDef _liblvm_pv_methods[] = { |
| /* pv methods */ |
| { "getName", (PyCFunction)_liblvm_lvm_pv_get_name, METH_NOARGS }, |
| { "getUuid", (PyCFunction)_liblvm_lvm_pv_get_uuid, METH_NOARGS }, |
| { "getMdaCount", (PyCFunction)_liblvm_lvm_pv_get_mda_count, METH_NOARGS }, |
| { "getProperty", (PyCFunction)_liblvm_lvm_pv_get_property, METH_VARARGS }, |
| { "getSize", (PyCFunction)_liblvm_lvm_pv_get_size, METH_NOARGS }, |
| { "getDevSize", (PyCFunction)_liblvm_lvm_pv_get_dev_size, METH_NOARGS }, |
| { "getFree", (PyCFunction)_liblvm_lvm_pv_get_free, METH_NOARGS }, |
| { "resize", (PyCFunction)_liblvm_lvm_pv_resize, METH_VARARGS }, |
| { "listPVsegs", (PyCFunction)_liblvm_lvm_pv_list_pvsegs, METH_NOARGS }, |
| { 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 _LibLVMvgType = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| .tp_name = "lvm.Liblvm_vg", |
| .tp_basicsize = sizeof(vgobject), |
| .tp_new = PyType_GenericNew, |
| .tp_dealloc = (destructor)liblvm_vg_dealloc, |
| .tp_flags = Py_TPFLAGS_DEFAULT, |
| .tp_doc = "LVM Volume Group object", |
| .tp_methods = _liblvm_vg_methods, |
| }; |
| |
| static PyTypeObject _LibLVMlvType = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| .tp_name = "lvm.Liblvm_lv", |
| .tp_basicsize = sizeof(lvobject), |
| .tp_new = PyType_GenericNew, |
| .tp_dealloc = (destructor)liblvm_lv_dealloc, |
| .tp_flags = Py_TPFLAGS_DEFAULT, |
| .tp_doc = "LVM Logical Volume object", |
| .tp_methods = _liblvm_lv_methods, |
| }; |
| |
| static PyTypeObject _LibLVMpvlistType = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| .tp_name = "lvm.Liblvm_pvlist", |
| .tp_basicsize = sizeof(pvslistobject), |
| .tp_new = PyType_GenericNew, |
| .tp_dealloc = (destructor)_liblvm_pvlist_dealloc, |
| .tp_flags = Py_TPFLAGS_DEFAULT, |
| .tp_doc = "LVM Physical Volume list object", |
| .tp_methods = _liblvm_pv_list_methods, |
| }; |
| |
| static PyTypeObject _LibLVMpvType = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| .tp_name = "lvm.Liblvm_pv", |
| .tp_basicsize = sizeof(pvobject), |
| .tp_new = PyType_GenericNew, |
| .tp_dealloc = (destructor)_liblvm_pv_dealloc, |
| .tp_flags = Py_TPFLAGS_DEFAULT, |
| .tp_doc = "LVM Physical Volume object", |
| .tp_methods = _liblvm_pv_methods, |
| }; |
| |
| static PyTypeObject _LibLVMlvsegType = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| .tp_name = "lvm.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 = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| .tp_name = "lvm.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, |
| }; |
| |
| static void _liblvm_cleanup(void) |
| { |
| if (_libh) { |
| lvm_quit(_libh); |
| _libh = NULL; |
| } |
| } |
| |
| #ifdef IS_PY3K |
| static struct PyModuleDef moduledef = { |
| PyModuleDef_HEAD_INIT, |
| "lvm", |
| "Liblvm module", |
| -1, |
| _Liblvm_methods, |
| NULL, |
| NULL, |
| NULL, |
| NULL |
| }; |
| |
| #define MODINITERROR return NULL |
| PyObject * |
| PyInit_lvm(void) |
| |
| #else |
| #define MODINITERROR return |
| PyMODINIT_FUNC initlvm(void); |
| PyMODINIT_FUNC initlvm(void) |
| #endif |
| { |
| PyObject *m; |
| |
| if (PyType_Ready(&_LibLVMvgType) < 0) |
| MODINITERROR; |
| if (PyType_Ready(&_LibLVMlvType) < 0) |
| MODINITERROR; |
| if (PyType_Ready(&_LibLVMpvType) < 0) |
| MODINITERROR; |
| if (PyType_Ready(&_LibLVMlvsegType) < 0) |
| MODINITERROR; |
| if (PyType_Ready(&_LibLVMpvsegType) < 0) |
| MODINITERROR; |
| if (PyType_Ready(&_LibLVMpvlistType) < 0) |
| MODINITERROR; |
| |
| #ifdef IS_PY3K |
| m = PyModule_Create(&moduledef); |
| #else |
| m = Py_InitModule3("lvm", _Liblvm_methods, "Liblvm module"); |
| #endif |
| if (m == NULL) |
| MODINITERROR; |
| |
| if (PyModule_AddIntConstant(m, "THIN_DISCARDS_IGNORE", |
| LVM_THIN_DISCARDS_IGNORE) < 0) |
| MODINITERROR; |
| |
| if (PyModule_AddIntConstant(m, "THIN_DISCARDS_NO_PASSDOWN", |
| LVM_THIN_DISCARDS_NO_PASSDOWN) < 0) |
| MODINITERROR; |
| |
| if (PyModule_AddIntConstant(m, "THIN_DISCARDS_PASSDOWN", |
| LVM_THIN_DISCARDS_PASSDOWN) < 0) |
| MODINITERROR; |
| |
| if ((_LibLVMError = PyErr_NewException((char*)"lvm.LibLVMError", NULL, NULL))) { |
| /* Each call to PyModule_AddObject decrefs it; compensate: */ |
| Py_INCREF(_LibLVMError); |
| Py_INCREF(_LibLVMError); |
| PyModule_AddObject(m, "error", _LibLVMError); |
| PyModule_AddObject(m, "LibLVMError", _LibLVMError); |
| } |
| |
| Py_AtExit(_liblvm_cleanup); |
| #ifdef IS_PY3K |
| return m; |
| #endif |
| } |