diff options
author | Alasdair G Kergon <agk@redhat.com> | 2012-10-12 02:08:47 +0100 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-10-12 02:08:47 +0100 |
commit | ee3cfa41843b0af1ef220ecf8bf6db82676af8c8 (patch) | |
tree | 0302b1a7f2af5f5ffe4b427652443ffa85fea082 | |
parent | 4022fd3e79099fb22b2b7d3d6dca8de733a2a783 (diff) | |
download | lvm2-ee3cfa41843b0af1ef220ecf8bf6db82676af8c8.tar.gz |
python: Add bindings for liblvm2app.
Use configure --enable-python_bindings to generate them.
Note that the Makefiles do not yet control the owner or permissions of
the two new files on installation.
-rw-r--r-- | Makefile.in | 17 | ||||
-rw-r--r-- | WHATS_NEW | 1 | ||||
-rwxr-xr-x | configure | 216 | ||||
-rw-r--r-- | configure.in | 40 | ||||
-rw-r--r-- | lib/misc/configure.h.in | 3 | ||||
-rw-r--r-- | make.tmpl.in | 3 | ||||
-rw-r--r-- | python/Makefile.in | 39 | ||||
-rw-r--r-- | python/example.py | 125 | ||||
-rw-r--r-- | python/liblvm.c | 1711 | ||||
-rw-r--r-- | python/setup.py.in | 35 |
10 files changed, 2175 insertions, 15 deletions
diff --git a/Makefile.in b/Makefile.in index 6b153d33b..bbfcf2cf5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -32,13 +32,17 @@ ifeq ("@APPLIB@", "yes") SUBDIRS += liblvm endif +ifeq ("@PYTHON_BINDINGS@", "yes") + SUBDIRS += python +endif + SUBDIRS += scripts # FIXME Should use intermediate Makefiles here! ifeq ($(MAKECMDGOALS),distclean) SUBDIRS = doc include man test scripts \ libdaemon lib tools daemons libdm \ - udev po liblvm \ + udev po liblvm python \ unit-tests/datastruct unit-tests/mm unit-tests/regex endif DISTCLEAN_DIRS += lcov_reports* @@ -69,6 +73,10 @@ po.pofile: tools.pofile daemons.pofile pofile: po.pofile endif +ifeq ("@PYTHON_BINDINGS@", "yes") +python: liblvm +endif + ifneq ("$(CFLOW_CMD)", "") tools.cflow: libdm.cflow lib.cflow daemons.cflow: tools.cflow @@ -103,6 +111,11 @@ install_systemd_generators: install_systemd_units: $(MAKE) -C scripts install_systemd_units +ifeq ("@PYTHON_BINDINGS@", "yes") +install_python_bindings: + $(MAKE) -C liblvm/python install_python_bindings +endif + install_tmpfiles_configuration: $(MAKE) -C scripts install_tmpfiles_configuration @@ -148,7 +161,7 @@ ifeq ("$(TESTING)", "yes") # testing and report generation RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test -.PHONEY: unit-test ruby-test test-programs +.PHONY: unit-test ruby-test test-programs # FIXME: put dependencies on libdm and liblvm # FIXME: Should be handled by Makefiles in subdirs, not here at top level. @@ -1,5 +1,6 @@ Version 2.02.98 - ================================= + Add configure --enable-python_bindings for liblvm2app to new python subdir. Add implementation of lvm2api function lvm_percent_to_float. Allow non power of 2 thin chunk sizes if thin pool driver supports that. Allow limited metadata changes when PVs are missing via [vg|lv]change. @@ -624,6 +624,9 @@ SELINUX_LIBS REPLICATORS READLINE_LIBS RAID +PYTHON_LIBDIRS +PYTHON_INCDIRS +PYTHON_BINDINGS PTHREAD_LIBS POOL PKGCONFIG @@ -686,10 +689,15 @@ BUILD_CMIRRORD APPLIB MODPROBE_CMD MSGFMT +PYTHON_CONFIG +PYTHON LVM2CMD_LIB LVM2APP_LIB UDEV_LIBS UDEV_CFLAGS +VALGRIND_POOL +VALGRIND_LIBS +VALGRIND_CFLAGS CUNIT_LIBS CUNIT_CFLAGS GENPNG @@ -842,6 +850,7 @@ enable_ioctl enable_o_direct enable_applib enable_cmdlib +enable_python_bindings enable_pkgconfig enable_write_install enable_fsadm @@ -901,6 +910,8 @@ SACKPT_CFLAGS SACKPT_LIBS CUNIT_CFLAGS CUNIT_LIBS +VALGRIND_CFLAGS +VALGRIND_LIBS UDEV_CFLAGS UDEV_LIBS' @@ -1542,6 +1553,8 @@ Optional Features: --disable-o_direct disable O_DIRECT --enable-applib build application library --enable-cmdlib build shared command library + --enable-python_bindings + build Python applib bindings --enable-pkgconfig install pkgconfig support --enable-write_install install user writable files --disable-fsadm disable fsadm @@ -1678,6 +1691,10 @@ Some influential environment variables: CUNIT_CFLAGS C compiler flags for CUNIT, overriding pkg-config CUNIT_LIBS linker flags for CUNIT, overriding pkg-config + VALGRIND_CFLAGS + C compiler flags for VALGRIND, overriding pkg-config + VALGRIND_LIBS + linker flags for VALGRIND, overriding pkg-config UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config UDEV_LIBS linker flags for UDEV, overriding pkg-config @@ -8814,23 +8831,80 @@ fi $as_echo "$VALGRIND_POOL" >&6; } if test "$VALGRIND_POOL" = yes; then - for ac_header in valgrind/memcheck.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default" -if test "x$ac_cv_header_valgrind_memcheck_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_VALGRIND_MEMCHECK_H 1 -_ACEOF +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND" >&5 +$as_echo_n "checking for VALGRIND... " >&6; } + +if test -n "$VALGRIND_CFLAGS"; then + pkg_cv_VALGRIND_CFLAGS="$VALGRIND_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind\""; } >&5 + ($PKG_CONFIG --exists --print-errors "valgrind") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_VALGRIND_CFLAGS=`$PKG_CONFIG --cflags "valgrind" 2>/dev/null` else - as_fn_error $? "bailing out" "$LINENO" 5 + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$VALGRIND_LIBS"; then + pkg_cv_VALGRIND_LIBS="$VALGRIND_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind\""; } >&5 + ($PKG_CONFIG --exists --print-errors "valgrind") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_VALGRIND_LIBS=`$PKG_CONFIG --libs "valgrind" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried fi -done +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + VALGRIND_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "valgrind" 2>&1` + else + VALGRIND_PKG_ERRORS=`$PKG_CONFIG --print-errors "valgrind" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$VALGRIND_PKG_ERRORS" >&5 + + as_fn_error $? "bailing out" "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "bailing out" "$LINENO" 5 +else + VALGRIND_CFLAGS=$pkg_cv_VALGRIND_CFLAGS + VALGRIND_LIBS=$pkg_cv_VALGRIND_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + $as_echo "#define VALGRIND_POOL 1" >>confdefs.h + + fi ################################################################################ @@ -9121,6 +9195,122 @@ test x$CMDLIB = xyes \ || LVM2CMD_LIB= ################################################################################ +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Python wrapper for liblvm2app.so" >&5 +$as_echo_n "checking whether to build Python wrapper for liblvm2app.so... " >&6; } +# Check whether --enable-python_bindings was given. +if test "${enable_python_bindings+set}" = set; then : + enableval=$enable_python_bindings; PYTHON_BINDINGS=$enableval +else + PYTHON_BINDINGS=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BINDINGS" >&5 +$as_echo "$PYTHON_BINDINGS" >&6; } + +if test x$PYTHON_BINDINGS = xyes; then + if test x$APPLIB != xyes; then + as_fn_error $? "--enable-python_bindings requires --enable-applib + " "$LINENO" 5 + fi + + # Extract the first word of "python", so it can be a program name with args. +set dummy python; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PYTHON+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PYTHON" && ac_cv_path_PYTHON="notfound" + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x$PYTHON == xnotfound; then + as_fn_error $? "python is required for --enable-python_bindings but cannot be found + " "$LINENO" 5 + fi + + # Extract the first word of "python-config", so it can be a program name with args. +set dummy python-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PYTHON_CONFIG+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_CONFIG="$PYTHON_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PYTHON_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PYTHON_CONFIG" && ac_cv_path_PYTHON_CONFIG="notfound" + ;; +esac +fi +PYTHON_CONFIG=$ac_cv_path_PYTHON_CONFIG +if test -n "$PYTHON_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_CONFIG" >&5 +$as_echo "$PYTHON_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x$PYTHON_CONFIG == xnotfound; then + as_fn_error $? "python headers are required for --enable-python_bindings but cannot be found + " "$LINENO" 5 + fi + + PYTHON_INCDIRS=`$PYTHON_CONFIG --includes` + PYTHON_LIBDIRS=`$PYTHON_CONFIG --libs` + +fi + +################################################################################ # Check whether --enable-pkgconfig was given. if test "${enable_pkgconfig+set}" = set; then : enableval=$enable_pkgconfig; PKGCONFIG=$enableval @@ -10576,8 +10766,12 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'` + + + + ################################################################################ -ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.socket scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" +ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.socket scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -11303,6 +11497,8 @@ do "liblvm/liblvm2app.pc") CONFIG_FILES="$CONFIG_FILES liblvm/liblvm2app.pc" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; + "python/Makefile") CONFIG_FILES="$CONFIG_FILES python/Makefile" ;; + "python/setup.py") CONFIG_FILES="$CONFIG_FILES python/setup.py" ;; "scripts/clvmd_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/clvmd_init_red_hat" ;; "scripts/cmirrord_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/cmirrord_init_red_hat" ;; "scripts/lvm2_lvmetad_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_init_red_hat" ;; diff --git a/configure.in b/configure.in index 16f91fb32..eb209087a 100644 --- a/configure.in +++ b/configure.in @@ -1027,6 +1027,40 @@ test x$CMDLIB = xyes \ || LVM2CMD_LIB= ################################################################################ +dnl -- Enable Python liblvm2app bindings +AC_MSG_CHECKING(whether to build Python wrapper for liblvm2app.so) +AC_ARG_ENABLE(python_bindings, + AC_HELP_STRING([--enable-python_bindings], [build Python applib bindings]), + PYTHON_BINDINGS=$enableval, PYTHON_BINDINGS=no) +AC_MSG_RESULT($PYTHON_BINDINGS) + +if test x$PYTHON_BINDINGS = xyes; then + if test x$APPLIB != xyes; then + AC_MSG_ERROR( + --enable-python_bindings requires --enable-applib + ) + fi + + AC_PATH_PROG(PYTHON, python, notfound) + if test x$PYTHON == xnotfound; then + AC_MSG_ERROR( +[python is required for --enable-python_bindings but cannot be found] + ) + fi + + AC_PATH_PROG(PYTHON_CONFIG, python-config, notfound) + if test x$PYTHON_CONFIG == xnotfound; then + AC_MSG_ERROR( +[python headers are required for --enable-python_bindings but cannot be found] + ) + fi + + PYTHON_INCDIRS=`$PYTHON_CONFIG --includes` + PYTHON_LIBDIRS=`$PYTHON_CONFIG --libs` + +fi + +################################################################################ dnl -- Enable pkg-config AC_ARG_ENABLE(pkgconfig, AC_HELP_STRING([--enable-pkgconfig], [install pkgconfig support]), @@ -1523,6 +1557,10 @@ AC_SUBST(OCFDIR) AC_SUBST(PKGCONFIG) AC_SUBST(POOL) AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PYTHON) +AC_SUBST(PYTHON_BINDINGS) +AC_SUBST(PYTHON_INCDIRS) +AC_SUBST(PYTHON_LIBDIRS) AC_SUBST(QUORUM_CFLAGS) AC_SUBST(QUORUM_LIBS) AC_SUBST(RAID) @@ -1605,6 +1643,8 @@ liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile +python/Makefile +python/setup.py scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_lvmetad_init_red_hat diff --git a/lib/misc/configure.h.in b/lib/misc/configure.h.in index c1d121892..fdc5a2617 100644 --- a/lib/misc/configure.h.in +++ b/lib/misc/configure.h.in @@ -432,9 +432,6 @@ /* Define to 1 if you have the <utmpx.h> header file. */ #undef HAVE_UTMPX_H -/* Define to 1 if you have the <valgrind/memcheck.h> header file. */ -#undef HAVE_VALGRIND_MEMCHECK_H - /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK diff --git a/make.tmpl.in b/make.tmpl.in index 21fd41502..8b56f013b 100644 --- a/make.tmpl.in +++ b/make.tmpl.in @@ -28,6 +28,7 @@ LN_S = @LN_S@ SED = @SED@ CFLOW_CMD = @CFLOW_CMD@ AWK = @AWK@ +PYTHON = @PYTHON@ LIBS = @LIBS@ # Extra libraries always linked with static binaries @@ -52,6 +53,7 @@ prefix = @prefix@ exec_prefix = @exec_prefix@ udev_prefix = @udev_prefix@ sysconfdir = @sysconfdir@ +rootdir = $(DESTDIR)/ bindir = $(DESTDIR)@bindir@ confdir = $(DESTDIR)@CONFDIR@/lvm includedir = $(DESTDIR)@includedir@ @@ -196,6 +198,7 @@ POTFILES = $(SOURCES:%.c=%.pot) .PHONY: install install_cluster install_device-mapper install_lvm2 .PHONY: install_lib_shared install_dm_plugin install_lvm2_plugin .PHONY: install_ocf help +.PHONY: python_bindings install_python_bindings .PHONY: $(SUBDIRS) $(SUBDIRS.install) $(SUBDIRS.clean) $(SUBDIRS.distclean) .PHONY: $(SUBDIRS.pofile) $(SUBDIRS.install_cluster) $(SUBDIRS.cflow) .PHONY: $(SUBDIRS.device-mapper) $(SUBDIRS.install-device-mapper) diff --git a/python/Makefile.in b/python/Makefile.in new file mode 100644 index 000000000..1fead2209 --- /dev/null +++ b/python/Makefile.in @@ -0,0 +1,39 @@ +# +# Copyright (C) 2011-2012 Red Hat, Inc. +# +# This file is part of LVM2. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU Lesser General Public License v.2.1. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +python_bindings: .liblvm_built + +.liblvm_built: liblvm_python.c + $(PYTHON) setup.py build + touch $@ + +liblvm_python.c: + $(LN_S) $(srcdir)/liblvm.c $@ + +include $(top_builddir)/make.tmpl + +install_python_bindings: python_bindings + $(PYTHON) setup.py install --skip-build --root $(rootdir) + +install_lvm2: install_python_bindings + +install: install_lvm2 + +CLEAN_TARGETS += .liblvm_built liblvm_python.c + +DISTCLEAN_DIRS += build +DISTCLEAN_TARGETS += setup.py diff --git a/python/example.py b/python/example.py new file mode 100644 index 000000000..67bb7e420 --- /dev/null +++ b/python/example.py @@ -0,0 +1,125 @@ +# +# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +# +# This file is part of LVM2. +# +# 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/>. +# +#----------------------------- +# Python example code: +#----------------------------- + +import lvm + +# Note: This example will create a logical unit, tag it and +# delete it, don't run this on production box! + +#Dump information about PV +def print_pv(pv): + print 'PV name: ', pv.getName(), ' ID: ', pv.getUuid(), 'Size: ', pv.getSize() + + +#Dump some information about a specific volume group +def print_vg(h, vg_name): + #Open read only + vg = h.vgOpen(vg_name, 'r') + + print 'Volume group:', vg_name, 'Size: ', vg.getSize() + + #Retrieve a list of Physical volumes for this volume group + pv_list = vg.listPVs() + + #Print out the physical volumes + for p in pv_list: + print_pv(p) + + #Get a list of logical volumes in this volume group + lv_list = vg.listLVs() + if len(lv_list): + for l in lv_list: + print 'LV name: ', l.getName(), ' ID: ', l.getUuid() + else: + print 'No logical volumes present!' + + vg.close() + +#Returns the name of a vg with space available +def find_vg_with_free_space(h): + free_space = 0 + rc = None + + vg_names = l.listVgNames() + for v in vg_names: + vg = h.vgOpen(v, 'r') + c_free = vg.getFreeSize() + if c_free > free_space: + free_space = c_free + rc = v + vg.close() + + return rc + +#Walk through the volume groups and fine one with space in which we can +#create a new logical volume +def create_delete_logical_volume(h): + vg_name = find_vg_with_free_space(h) + + print 'Using volume group ', vg_name, ' for example' + + if vg_name: + vg = h.vgOpen(vg_name, 'w') + lv = vg.createLvLinear('python_lvm_ok_to_delete', vg.getFreeSize()) + + if lv: + print 'New lv, id= ', lv.getUuid() + + #Create a tag + lv.addTag('Demo_tag') + + #Get the tags + tags = lv.getTags() + for t in tags: + #Remove tag + lv.removeTag(t) + + #Try to rename + lv.rename("python_lvm_ok_to_be_removed_shortly") + print 'LV name= ', lv.getName() + + lv.deactivate() + lv.remove() + + vg.close() + else: + print 'No free space available to create demo lv!' + +if __name__ == '__main__': + #Create a new LVM instance + l = lvm.Liblvm() + + #What version + print 'lvm version=', l.getVersion() + + #Get a list of volume group names + vg_names = l.listVgNames() + + #For each volume group display some information about each of them + for vg_i in vg_names: + print_vg(l, vg_i) + + #Demo creating a logical volume + create_delete_logical_volume(l) + + #Close + l.close() diff --git a/python/liblvm.c b/python/liblvm.c new file mode 100644 index 000000000..cbfa17006 --- /dev/null +++ b/python/liblvm.c @@ -0,0 +1,1711 @@ +/* + * Liblvm -- Python interface to LVM2 API. + * + * Copyright (C) 2010, 2012 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" + +typedef struct { + PyObject_HEAD + lvm_t libh; /* lvm lib handle */ +} lvmobject; + +typedef struct { + PyObject_HEAD + vg_t vg; /* vg handle */ + lvmobject *lvm_obj; +} vgobject; + +typedef struct { + PyObject_HEAD + lv_t lv; /* lv handle */ + lvmobject *lvm_obj; +} lvobject; + +typedef struct { + PyObject_HEAD + pv_t pv; /* pv handle */ + 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; + + +/* ---------------------------------------------------------------------- + * LVM object initialization/deallocation + */ + +static int +liblvm_init(lvmobject *self, PyObject *arg) +{ + char *systemdir = NULL; + + if (!PyArg_ParseTuple(arg, "|s", &systemdir)) + return -1; + + self->libh = lvm_init(systemdir); + if (lvm_errno(self->libh)) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + return 0; +} + +static void +liblvm_dealloc(lvmobject *self) +{ + /* if already closed, don't reclose it */ + if (self->libh != NULL){ + lvm_quit(self->libh); + } + + PyObject_Del(self); +} + +#define LVM_VALID(lvmobject) \ + do { \ + if (!lvmobject->libh) { \ + PyErr_SetString(PyExc_UnboundLocalError, "LVM object invalid"); \ + return NULL; \ + } \ + } while (0) + +static PyObject * +liblvm_get_last_error(lvmobject *self) +{ + PyObject *info; + + LVM_VALID(self); + + if((info = PyTuple_New(2)) == NULL) + return NULL; + + PyTuple_SetItem(info, 0, PyInt_FromLong((long) lvm_errno(self->libh))); + PyTuple_SetItem(info, 1, PyString_FromString(lvm_errmsg(self->libh))); + + return info; +} + +static PyObject * +liblvm_library_get_version(lvmobject *self) +{ + LVM_VALID(self); + + return Py_BuildValue("s", lvm_library_get_version()); +} + + +static PyObject * +liblvm_close(lvmobject *self) +{ + LVM_VALID(self); + + /* if already closed, don't reclose it */ + if (self->libh != NULL) + lvm_quit(self->libh); + + self->libh = NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +liblvm_lvm_list_vg_names(lvmobject *self) +{ + struct dm_list *vgnames; + struct lvm_str_list *strl; + PyObject * pytuple; + int i = 0; + + LVM_VALID(self); + + vgnames = lvm_list_vg_names(self->libh); + if (!vgnames) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + pytuple = PyTuple_New(dm_list_size(vgnames)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(strl, vgnames) { + PyTuple_SET_ITEM(pytuple, i, PyString_FromString(strl->str)); + i++; + } + + return pytuple; +} + +static PyObject * +liblvm_lvm_list_vg_uuids(lvmobject *self) +{ + struct dm_list *uuids; + struct lvm_str_list *strl; + PyObject * pytuple; + int i = 0; + + LVM_VALID(self); + + uuids = lvm_list_vg_uuids(self->libh); + if (!uuids) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + pytuple = PyTuple_New(dm_list_size(uuids)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(strl, uuids) { + PyTuple_SET_ITEM(pytuple, i, PyString_FromString(strl->str)); + i++; + } + + return pytuple; +} + +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; + const char *vgname; + + LVM_VALID(self); + + if (!PyArg_ParseTuple(arg, "s", &pvid)) + return NULL; + + if((vgname = lvm_vgname_from_pvid(self->libh, pvid)) == NULL) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + return Py_BuildValue("s", vgname); +} + +static PyObject * +liblvm_lvm_vgname_from_device(lvmobject *self, PyObject *arg) +{ + const char *device; + const char *vgname; + + LVM_VALID(self); + + if (!PyArg_ParseTuple(arg, "s", &device)) + return NULL; + + if((vgname = lvm_vgname_from_device(self->libh, device)) == NULL) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + 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) +{ + int rval; + + LVM_VALID(self); + + if((rval = lvm_config_reload(self->libh)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + + +static PyObject * +liblvm_lvm_scan(lvmobject *self) +{ + int rval; + + LVM_VALID(self); + + if((rval = lvm_scan(self->libh)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +liblvm_lvm_config_override(lvmobject *self, PyObject *arg) +{ + const char *config; + int rval; + + LVM_VALID(self); + + if (!PyArg_ParseTuple(arg, "s", &config)) + return NULL; + + if ((rval = lvm_config_override(self->libh, config)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self)); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} +/* ---------------------------------------------------------------------- + * VG object initialization/deallocation + */ + + +static PyObject * +liblvm_lvm_vg_open(lvmobject *lvm, PyObject *args) +{ + const char *vgname; + const char *mode = NULL; + + vgobject *self; + + LVM_VALID(lvm); + + if (!PyArg_ParseTuple(args, "s|s", &vgname, &mode)) { + return NULL; + } + + if (mode == NULL) + mode = "r"; + + if ((self = PyObject_New(vgobject, &LibLVMvgType)) == NULL) + return NULL; + + if ((self->vg = lvm_vg_open(lvm->libh, vgname, mode, 0))== NULL) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(lvm)); + Py_DECREF(self); + return NULL; + } + self->lvm_obj = lvm; + + return (PyObject *)self; +} + +static PyObject * +liblvm_lvm_vg_create(lvmobject *lvm, PyObject *args) +{ + const char *vgname; + vgobject *self; + + LVM_VALID(lvm); + + if (!PyArg_ParseTuple(args, "s", &vgname)) { + return NULL; + } + + if ((self = PyObject_New(vgobject, &LibLVMvgType)) == NULL) + return NULL; + + if ((self->vg = lvm_vg_create(lvm->libh, vgname))== NULL) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(lvm)); + Py_DECREF(self); + return NULL; + } + self->lvm_obj = lvm; + + return (PyObject *)self; +} + +static void +liblvm_vg_dealloc(vgobject *self) +{ + /* if already closed, don't reclose it */ + if (self->vg != NULL) + lvm_vg_close(self->vg); + PyObject_Del(self); +} + +/* VG Methods */ + +#define VG_VALID(vgobject) \ + do { \ + if (!vgobject->vg) { \ + PyErr_SetString(PyExc_UnboundLocalError, "VG object invalid"); \ + return NULL; \ + } \ + } while (0) + +static PyObject * +liblvm_lvm_vg_close(vgobject *self) +{ + /* if already closed, don't reclose it */ + if (self->vg != NULL) + lvm_vg_close(self->vg); + + self->vg = 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) +{ + int rval; + + VG_VALID(self); + + if ((rval = lvm_vg_remove(self->vg)) == -1) + goto error; + + if (lvm_vg_write(self->vg) == -1) + goto error; + + self->vg = NULL; + + Py_INCREF(Py_None); + return Py_None; + +error: + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; +} + +static PyObject * +liblvm_lvm_vg_extend(vgobject *self, PyObject *args) +{ + const char *device; + int rval; + + VG_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &device)) { + return NULL; + } + + if ((rval = 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(self->lvm_obj)); + return NULL; +} + +static PyObject * +liblvm_lvm_vg_reduce(vgobject *self, PyObject *args) +{ + const char *device; + int rval; + + VG_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &device)) { + return NULL; + } + + if ((rval = 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(self->lvm_obj)); + 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(self->lvm_obj)); + return NULL; +} + +static PyObject * +liblvm_lvm_vg_remove_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_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(self->lvm_obj)); + 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("l", lvm_vg_get_seqno(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_size(vgobject *self) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_size(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_free_size(vgobject *self) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_free_size(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_extent_size(vgobject *self) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_extent_size(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_extent_count(vgobject *self) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_extent_count(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_free_extent_count(vgobject *self) +{ + VG_VALID(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) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_pv_count(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_max_pv(vgobject *self) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_max_pv(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_get_max_lv(vgobject *self) +{ + VG_VALID(self); + + return Py_BuildValue("l", lvm_vg_get_max_lv(self->vg)); +} + +static PyObject * +liblvm_lvm_vg_set_extent_size(vgobject *self, PyObject *args) +{ + uint32_t new_size; + int rval; + + VG_VALID(self); + + if (!PyArg_ParseTuple(args, "l", &new_size)) { + return NULL; + } + + if ((rval = lvm_vg_set_extent_size(self->vg, new_size)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +liblvm_lvm_vg_list_lvs(vgobject *vg) +{ + struct dm_list *lvs; + struct lvm_lv_list *lvl; + PyObject * pytuple; + lvobject * self; + int i = 0; + + VG_VALID(vg); + + /* unlike other LVM api calls, if there are no results, we get NULL */ + lvs = lvm_vg_list_lvs(vg->vg); + if (!lvs) + return Py_BuildValue("()"); + + pytuple = PyTuple_New(dm_list_size(lvs)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(lvl, lvs) { + /* Create and initialize the object */ + self = PyObject_New(lvobject, &LibLVMlvType); + if (!self) { + Py_DECREF(pytuple); + return NULL; + } + + self->lv = lvl->lv; + self->lvm_obj = vg->lvm_obj; + PyTuple_SET_ITEM(pytuple, i, (PyObject *) self); + i++; + } + + return pytuple; +} + +static PyObject * +liblvm_lvm_vg_get_tags(vgobject *self) +{ + struct dm_list *tags; + struct lvm_str_list *strl; + PyObject * pytuple; + int i = 0; + + VG_VALID(self); + + tags = lvm_vg_get_tags(self->vg); + if (!tags) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + pytuple = PyTuple_New(dm_list_size(tags)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(strl, tags) { + PyTuple_SET_ITEM(pytuple, i, PyString_FromString(strl->str)); + i++; + } + + return pytuple; +} + +static PyObject * +liblvm_lvm_vg_create_lv_linear(vgobject *vg, PyObject *args) +{ + const char *vgname; + uint64_t size; + lvobject *self; + + VG_VALID(vg); + + if (!PyArg_ParseTuple(args, "sl", &vgname, &size)) { + return NULL; + } + + if ((self = PyObject_New(lvobject, &LibLVMlvType)) == NULL) + return NULL; + + if ((self->lv = lvm_vg_create_lv_linear(vg->vg, vgname, size))== NULL) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(vg->lvm_obj)); + Py_DECREF(self); + return NULL; + } + self->lvm_obj = vg->lvm_obj; + + return (PyObject *)self; +} + +static void +liblvm_lv_dealloc(lvobject *self) +{ + PyObject_Del(self); +} + +static PyObject * +liblvm_lvm_vg_list_pvs(vgobject *vg) +{ + struct dm_list *pvs; + struct lvm_pv_list *pvl; + PyObject * pytuple; + pvobject * self; + int i = 0; + + VG_VALID(vg); + + /* unlike other LVM api calls, if there are no results, we get NULL */ + pvs = lvm_vg_list_pvs(vg->vg); + if (!pvs) + return Py_BuildValue("()"); + + pytuple = PyTuple_New(dm_list_size(pvs)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(pvl, pvs) { + /* Create and initialize the object */ + self = PyObject_New(pvobject, &LibLVMpvType); + if (!self) { + Py_DECREF(pytuple); + return NULL; + } + + self->pv = pvl->pv; + self->lvm_obj = vg->lvm_obj; + PyTuple_SET_ITEM(pytuple, i, (PyObject *) self); + 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; + 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) +{ + PyObject_Del(self); +} + +/* LV Methods */ + +#define LV_VALID(lvobject) \ + do { \ + if (!lvobject->lv) { \ + PyErr_SetString(PyExc_UnboundLocalError, "LV object invalid"); \ + return NULL; \ + } \ + } while (0) + + +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) +{ + int rval; + + LV_VALID(self); + + if ((rval = lvm_lv_activate(self->lv)) == -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_deactivate(lvobject *self) +{ + int rval; + + LV_VALID(self); + + if ((rval = lvm_lv_deactivate(self->lv)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +liblvm_lvm_vg_remove_lv(lvobject *self) +{ + int rval; + + LV_VALID(self); + + if ((rval = lvm_vg_remove_lv(self->lv)) == -1) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + 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(self->lvm_obj, &prop_value); +} + +static PyObject * +liblvm_lvm_lv_get_size(lvobject *self) +{ + LV_VALID(self); + + return Py_BuildValue("l", 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; + int rval; + + LV_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &tag)) { + return NULL; + } + + if ((rval = lvm_lv_add_tag(self->lv, tag)) == -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_remove_tag(lvobject *self, PyObject *args) +{ + const char *tag; + int rval; + + LV_VALID(self); + + if (!PyArg_ParseTuple(args, "s", &tag)) { + return NULL; + } + + if ((rval = lvm_lv_remove_tag(self->lv, tag)) == -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_get_tags(lvobject *self) +{ + struct dm_list *tags; + struct lvm_str_list *strl; + PyObject * pytuple; + int i = 0; + + LV_VALID(self); + + tags = lvm_lv_get_tags(self->lv); + if (!tags) { + PyErr_SetObject(LibLVMError, liblvm_get_last_error(self->lvm_obj)); + return NULL; + } + + pytuple = PyTuple_New(dm_list_size(tags)); + if (!pytuple) + return NULL; + + dm_list_iterate_items(strl, tags) { + PyTuple_SET_ITEM(pytuple, i, PyString_FromString(strl->str)); + i++; + } + + return pytuple; +} + +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; + int rval; + + LV_VALID(self); + + if (!PyArg_ParseTuple(args, "l", &new_size)) { + return NULL; + } + + if ((rval = lvm_lv_resize(self->lv, new_size)) == -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_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) +{ + return Py_BuildValue("s", lvm_pv_get_name(self->pv)); +} + +static PyObject * +liblvm_lvm_pv_get_uuid(pvobject *self) +{ + return Py_BuildValue("s", lvm_pv_get_uuid(self->pv)); +} + +static PyObject * +liblvm_lvm_pv_get_mda_count(pvobject *self) +{ + return Py_BuildValue("l", 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(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)); +} + +static PyObject * +liblvm_lvm_pv_get_size(pvobject *self) +{ + return Py_BuildValue("l", lvm_pv_get_size(self->pv)); +} + +static PyObject * +liblvm_lvm_pv_get_free(pvobject *self) +{ + return Py_BuildValue("l", lvm_pv_get_free(self->pv)); +} + +static PyObject * +liblvm_lvm_pv_resize(pvobject *self, PyObject *args) +{ + uint64_t new_size; + int rval; + + if (!PyArg_ParseTuple(args, "l", &new_size)) { + return NULL; + } + + if ((rval = lvm_pv_resize(self->pv, new_size)) == -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_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 + */ + +static PyMethodDef Liblvm_methods[] = { + /* LVM methods */ + { "getVersion", (PyCFunction)liblvm_library_get_version, METH_NOARGS }, + { "vgOpen", (PyCFunction)liblvm_lvm_vg_open, METH_VARARGS }, + { "vgCreate", (PyCFunction)liblvm_lvm_vg_create, METH_VARARGS }, + { "close", (PyCFunction)liblvm_close, METH_NOARGS }, + { "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 }, + { "percentToFloat", (PyCFunction)liblvm_lvm_percent_to_float, 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 }, + { "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 }, + { NULL, NULL} /* sentinel */ +}; + +static PyMethodDef liblvm_lv_methods[] = { + /* lv methods */ + { "getName", (PyCFunction)liblvm_lvm_lv_get_name, 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 }, + { NULL, NULL} /* sentinel */ +}; + +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_lv_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 LiblvmType = { + PyObject_HEAD_INIT(&PyType_Type) + .tp_name = "liblvm.Liblvm", + .tp_basicsize = sizeof(lvmobject), + .tp_new = PyType_GenericNew, + .tp_dealloc = (destructor)liblvm_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_doc = "Liblvm objects", + .tp_methods = Liblvm_methods, + .tp_init = (initproc)liblvm_init, +}; + +static PyTypeObject LibLVMvgType = { + PyObject_HEAD_INIT(&PyType_Type) + .tp_name = "liblvm.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 = { + PyObject_HEAD_INIT(&PyType_Type) + .tp_name = "liblvm.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 LibLVMpvType = { + PyObject_HEAD_INIT(&PyType_Type) + .tp_name = "liblvm.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 = { + 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) +{ + PyObject *m; + + if (PyType_Ready(&LiblvmType) < 0) + return; + if (PyType_Ready(&LibLVMvgType) < 0) + return; + if (PyType_Ready(&LibLVMlvType) < 0) + 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) + return; + + Py_INCREF(&LiblvmType); + PyModule_AddObject(m, "Liblvm", (PyObject *)&LiblvmType); + + LibLVMError = PyErr_NewException("Liblvm.LibLVMError", + NULL, NULL); + if (LibLVMError) { + /* Each call to PyModule_AddObject decrefs it; compensate: */ + Py_INCREF(LibLVMError); + Py_INCREF(LibLVMError); + PyModule_AddObject(m, "error", LibLVMError); + PyModule_AddObject(m, "LibLVMError", LibLVMError); + } + +} diff --git a/python/setup.py.in b/python/setup.py.in new file mode 100644 index 000000000..6a44482a6 --- /dev/null +++ b/python/setup.py.in @@ -0,0 +1,35 @@ +# +# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +# +# This file is part of LVM2. +# +# 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/>. + +from distutils.core import setup, Extension + +liblvm = Extension('lvm', + sources = ['liblvm_python.c'], + libraries= ['lvm2app'], + library_dirs= ['@top_builddir@/liblvm'], + include_dirs= ['@top_builddir@/include']) + +setup (name='lvm', + version=@LVM_VERSION@, + description='Python bindings for liblvm2', + license="LGPLv2+", + maintainer='LVM2 maintainers', + maintainer_email='linux-lvm@redhat.com', + url='http://sourceware.org/lvm2/', + ext_modules=[liblvm], +) |