From: "Daniel P. Berrange" <berrange(a)redhat.com>
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.
The actual APIs are
int virDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags);
int virDomainLxcEnterNamespace(virDomainPtr domain,
unsigned int flags);
which provide a way to use the setns() system call to move the
calling process into the container's namespace. This is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
.gitignore | 4 +
cfg.mk | 3 +-
configure.ac | 5 +-
daemon/remote.c | 1 +
docs/Makefile.am | 21 ++++-
docs/apibuild.py | 10 ++-
docs/hvsupport.pl | 40 +++++++++
include/libvirt/Makefile.am | 1 +
include/libvirt/libvirt-lxc.h | 50 +++++++++++
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 10 +++
python/Makefile.am | 35 ++++++--
python/generator.py | 172 +++++++++++++++++++++++++++++++++++-
python/libvirt-lxc-override-api.xml | 19 ++++
python/libvirt-lxc-override.c | 141 +++++++++++++++++++++++++++++
src/Makefile.am | 18 +++-
src/driver.h | 6 ++
src/internal.h | 1 +
src/libvirt-lxc.c | 165 ++++++++++++++++++++++++++++++++++
src/libvirt_lxc.syms | 17 ++++
src/lxc/lxc_driver.c | 1 +
tools/virsh.c | 1 +
22 files changed, 708 insertions(+), 14 deletions(-)
create mode 100644 include/libvirt/libvirt-lxc.h
create mode 100644 python/libvirt-lxc-override-api.xml
create mode 100644 python/libvirt-lxc-override.c
create mode 100644 src/libvirt-lxc.c
create mode 100644 src/libvirt_lxc.syms
diff --git a/.gitignore b/.gitignore
index 882ae4c..579b324 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,6 +64,7 @@
/docs/hvsupport.html.in
/docs/libvirt-api.xml
/docs/libvirt-qemu-*.xml
+/docs/libvirt-lxc-*.xml
/docs/libvirt-refs.xml
/docs/search.php
/docs/todo.html.in
@@ -92,10 +93,13 @@
/python/generated.stamp
/python/generator.py.stamp
/python/libvirt-export.c
+/python/libvirt-lxc-export.c
+/python/libvirt-lxc.[ch]
/python/libvirt-qemu-export.c
/python/libvirt-qemu.[ch]
/python/libvirt.[ch]
/python/libvirt.py
+/python/libvirt_lxc.py
/python/libvirt_qemu.py
/run
/sc_*
diff --git a/cfg.mk b/cfg.mk
index f9270b0..a98b3f1 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -302,6 +302,7 @@ sc_flags_usage:
@test "$$(cat $(srcdir)/include/libvirt/libvirt.h.in \
$(srcdir)/include/libvirt/virterror.h \
$(srcdir)/include/libvirt/libvirt-qemu.h \
+ $(srcdir)/include/libvirt/libvirt-lxc.h \
| grep -c '\(long\|unsigned\) flags')" != 4 && \
{ echo '$(ME): new API should use "unsigned int flags"'
1>&2; \
exit 1; } || :
@@ -767,7 +768,7 @@ exclude_file_name_regexp--sc_prohibit_VIR_ERR_NO_MEMORY = \
exclude_file_name_regexp--sc_prohibit_access_xok = ^src/util/virutil\.c$$
exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \
- ^python/(libvirt-(qemu-)?override|typewrappers)\.c$$
+ ^python/(libvirt-(lxc-|qemu-)?override|typewrappers)\.c$$
exclude_file_name_regexp--sc_prohibit_asprintf = \
^(bootstrap.conf$$|src/util/virutil\.c$$|examples/domain-events/events-c/event-test\.c$$)
diff --git a/configure.ac b/configure.ac
index 3c97e4f..5a15531 100644
--- a/configure.ac
+++ b/configure.ac
@@ -174,7 +174,7 @@ dnl Availability of various common functions (non-fatal if missing),
dnl and various less common threadsafe functions
AC_CHECK_FUNCS_ONCE([cfmakeraw geteuid getgid getgrnam_r getmntent_r \
getpwuid_r getuid initgroups kill mmap newlocale posix_fallocate \
- posix_memalign regexec sched_getaffinity])
+ posix_memalign regexec sched_getaffinity setns])
dnl Availability of pthread functions (if missing, win32 threading is
dnl assumed). Because of $LIB_PTHREAD, we cannot use AC_CHECK_FUNCS_ONCE.
@@ -2639,6 +2639,7 @@ CYGWIN_EXTRA_PYTHON_LIBADD=
MINGW_EXTRA_LDFLAGS=
WIN32_EXTRA_CFLAGS=
LIBVIRT_SYMBOL_FILE=libvirt.syms
+LIBVIRT_LXC_SYMBOL_FILE='$(srcdir)/libvirt_lxc.syms'
LIBVIRT_QEMU_SYMBOL_FILE='$(srcdir)/libvirt_qemu.syms'
MSCOM_LIBS=
case "$host" in
@@ -2672,6 +2673,7 @@ case "$host" in
# Also set the symbol file to .def, so src/Makefile generates libvirt.def
# from libvirt.syms and passes libvirt.def instead of libvirt.syms to the linker
LIBVIRT_SYMBOL_FILE=libvirt.def
+ LIBVIRT_LXC_SYMBOL_FILE=libvirt_lxc.def
LIBVIRT_QEMU_SYMBOL_FILE=libvirt_qemu.def
# mingw's ld has the --version-script parameter, but it requires a .def file
# instead to work properly, therefore clear --version-script here and use
@@ -2687,6 +2689,7 @@ AC_SUBST([CYGWIN_EXTRA_PYTHON_LIBADD])
AC_SUBST([MINGW_EXTRA_LDFLAGS])
AC_SUBST([WIN32_EXTRA_CFLAGS])
AC_SUBST([LIBVIRT_SYMBOL_FILE])
+AC_SUBST([LIBVIRT_LXC_SYMBOL_FILE])
AC_SUBST([LIBVIRT_QEMU_SYMBOL_FILE])
AC_SUBST([VERSION_SCRIPT_FLAGS])
AC_SUBST([MSCOM_LIBS])
diff --git a/daemon/remote.c b/daemon/remote.c
index 8767c18..a69dc5d 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -39,6 +39,7 @@
#include "stream.h"
#include "viruuid.h"
#include "libvirt/libvirt-qemu.h"
+#include "libvirt/libvirt-lxc.h"
#include "vircommand.h"
#include "intprops.h"
#include "virnetserverservice.h"
diff --git a/docs/Makefile.am b/docs/Makefile.am
index cba9d4b..6bd5681 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -95,8 +95,12 @@ qemu_xml = \
libvirt-qemu-api.xml \
libvirt-qemu-refs.xml
+lxc_xml = \
+ libvirt-lxc-api.xml \
+ libvirt-lxc-refs.xml
+
apidir = $(pkgdatadir)/api
-api_DATA = libvirt-api.xml libvirt-qemu-api.xml
+api_DATA = libvirt-api.xml libvirt-qemu-api.xml libvirt-lxc-api.xml
fig = \
libvirt-net-logical.fig \
@@ -133,6 +137,7 @@ all-am: web
api: $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml
qemu_api: $(srcdir)/libvirt-qemu-api.xml $(srcdir)/libvirt-qemu-refs.xml
+lxc_api: $(srcdir)/libvirt-lxc-api.xml $(srcdir)/libvirt-lxc-refs.xml
web: $(dot_html) $(internals_html) html/index.html devhelp/index.html \
$(dot_php)
@@ -152,7 +157,8 @@ todo:
$(MAKE) todo.html
hvsupport.html.in: $(srcdir)/hvsupport.pl $(srcdir)/../src/libvirt_public.syms \
- $(srcdir)/../src/libvirt_qemu.syms $(srcdir)/../src/driver.h
+ $(srcdir)/../src/libvirt_qemu.syms $(srcdir)/../src/libvirt_lxc.syms \
+ $(srcdir)/../src/driver.h
$(AM_V_GEN)$(PERL) $(srcdir)/hvsupport.pl $(srcdir)/../src > $@ || { rm $@ &&
exit 1; }
.PHONY: todo
@@ -220,12 +226,16 @@ $(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml
$(devhelpxsl)
python_generated_files = \
$(srcdir)/html/libvirt-libvirt.html \
+ $(srcdir)/html/libvirt-libvirt-lxc.html \
$(srcdir)/html/libvirt-libvirt-qemu.html \
$(srcdir)/html/libvirt-virterror.html \
$(srcdir)/libvirt-api.xml \
$(srcdir)/libvirt-refs.xml \
+ $(srcdir)/libvirt-lxc-api.xml \
+ $(srcdir)/libvirt-lxc-refs.xml \
$(srcdir)/libvirt-qemu-api.xml \
- $(srcdir)/libvirt-qemu-refs.xml
+ $(srcdir)/libvirt-qemu-refs.xml \
+ $(NULL)
APIBUILD=$(srcdir)/apibuild.py
APIBUILD_STAMP=$(APIBUILD).stamp
@@ -235,9 +245,11 @@ $(python_generated_files): $(APIBUILD_STAMP)
$(APIBUILD_STAMP): $(srcdir)/apibuild.py \
$(srcdir)/../include/libvirt/libvirt.h.in \
+ $(srcdir)/../include/libvirt/libvirt-lxc.h \
$(srcdir)/../include/libvirt/libvirt-qemu.h \
$(srcdir)/../include/libvirt/virterror.h \
$(srcdir)/../src/libvirt.c \
+ $(srcdir)/../src/libvirt-lxc.c \
$(srcdir)/../src/libvirt-qemu.c \
$(srcdir)/../src/util/virerror.c
$(AM_V_GEN)srcdir=$(srcdir) $(PYTHON) $(APIBUILD)
@@ -252,9 +264,10 @@ clean-local:
maintainer-clean-local: clean-local
rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml todo.html.in
hvsupport.html.in
rm -rf $(srcdir)/libvirt-qemu-api.xml $(srcdir)/libvirt-qemu-refs.xml
+ rm -rf $(srcdir)/libvirt-lxc-api.xml $(srcdir)/libvirt-lxc-refs.xml
rm -rf $(APIBUILD_STAMP)
-rebuild: api qemu_api all
+rebuild: api qemu_api lxc_api all
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)
diff --git a/docs/apibuild.py b/docs/apibuild.py
index e73a85d..eb8ddb2 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -32,6 +32,11 @@ qemu_included_files = {
"libvirt-qemu.c": "Implementations for the QEMU specific APIs",
}
+lxc_included_files = {
+ "libvirt-lxc.h": "header with LXC specific API definitions",
+ "libvirt-lxc.c": "Implementations for the LXC specific APIs",
+}
+
ignored_words = {
"ATTRIBUTE_UNUSED": (0, "macro keyword"),
"ATTRIBUTE_SENTINEL": (0, "macro keyword"),
@@ -1955,6 +1960,8 @@ class docBuilder:
self.includes = includes + included_files.keys()
elif name == "libvirt-qemu":
self.includes = includes + qemu_included_files.keys()
+ elif name == "libvirt-lxc":
+ self.includes = includes + lxc_included_files.keys()
self.modules = {}
self.headers = {}
self.idx = index()
@@ -2473,7 +2480,7 @@ class docBuilder:
def rebuild(name):
- if name not in ["libvirt", "libvirt-qemu"]:
+ if name not in ["libvirt", "libvirt-qemu",
"libvirt-lxc"]:
self.warning("rebuild() failed, unknown module %s") % name
return None
builder = None
@@ -2516,6 +2523,7 @@ if __name__ == "__main__":
else:
rebuild("libvirt")
rebuild("libvirt-qemu")
+ rebuild("libvirt-lxc")
if warnings > 0:
sys.exit(2)
else:
diff --git a/docs/hvsupport.pl b/docs/hvsupport.pl
index 4871739..6230e3c 100755
--- a/docs/hvsupport.pl
+++ b/docs/hvsupport.pl
@@ -11,6 +11,7 @@ my $srcdir = shift @ARGV;
my $symslibvirt = "$srcdir/libvirt_public.syms";
my $symsqemu = "$srcdir/libvirt_qemu.syms";
+my $symslxc = "$srcdir/libvirt_lxc.syms";
my $drivertable = "$srcdir/driver.h";
my %groupheaders = (
@@ -112,6 +113,45 @@ while (defined($line = <FILE>)) {
close FILE;
+# And the same for the LXC specific APIs
+
+open FILE, "<$symslxc"
+ or die "cannot read $symslxc: $!";
+
+$prevvers = undef;
+$vers = undef;
+while (defined($line = <FILE>)) {
+ chomp $line;
+ next if $line =~ /^\s*#/;
+ next if $line =~ /^\s*$/;
+ next if $line =~ /^\s*(global|local):/;
+ if ($line =~ /^\s*LIBVIRT_LXC_(\d+\.\d+\.\d+)\s*{\s*$/) {
+ if (defined $vers) {
+ die "malformed syms file";
+ }
+ $vers = $1;
+ } elsif ($line =~ /\s*}\s*;\s*$/) {
+ if (defined $prevvers) {
+ die "malformed syms file";
+ }
+ $prevvers = $vers;
+ $vers = undef;
+ } elsif ($line =~ /\s*}\s*LIBVIRT_LXC_(\d+\.\d+\.\d+)\s*;\s*$/) {
+ if ($1 ne $prevvers) {
+ die "malformed syms file $1 != $vers";
+ }
+ $prevvers = $vers;
+ $vers = undef;
+ } elsif ($line =~ /\s*(\w+)\s*;\s*$/) {
+ $apis{$1} = $vers;
+ } else {
+ die "unexpected data $line\n";
+ }
+}
+
+close FILE;
+
+
# Some special things which aren't public APIs,
# but we want to report
$apis{virConnectDrvSupportsFeature} = "0.3.2";
diff --git a/include/libvirt/Makefile.am b/include/libvirt/Makefile.am
index 8f36ae8..0ec7f04 100644
--- a/include/libvirt/Makefile.am
+++ b/include/libvirt/Makefile.am
@@ -6,6 +6,7 @@
virincdir = $(includedir)/libvirt
virinc_HEADERS = libvirt.h \
+ libvirt-lxc.h \
libvirt-qemu.h \
virterror.h
diff --git a/include/libvirt/libvirt-lxc.h b/include/libvirt/libvirt-lxc.h
new file mode 100644
index 0000000..f21538f
--- /dev/null
+++ b/include/libvirt/libvirt-lxc.h
@@ -0,0 +1,50 @@
+/* -*- c -*-
+ * libvirt-lxc.h: Interfaces specific for LXC driver
+ * Summary: lxc specific interfaces
+ * Description: Provides the interfaces of the libvirt library to handle
+ * LXC specific methods
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library 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 library 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 library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __VIR_LXC_H__
+# define __VIR_LXC_H__
+
+# include "libvirt/libvirt.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int virDomainLxcOpenNamespace(virDomainPtr domain,
+ int **fdlist,
+ unsigned int flags);
+
+int virDomainLxcEnterNamespace(virDomainPtr domain,
+ unsigned int nfdlist,
+ int *fdlist,
+ unsigned int *noldfdlist,
+ int **oldfdlist,
+ unsigned int flags);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* __VIR_LXC_H__ */
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 3aaef02..e76c4db 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1970,6 +1970,7 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd
%dir %{_datadir}/libvirt/api/
%{_datadir}/libvirt/api/libvirt-api.xml
%{_datadir}/libvirt/api/libvirt-qemu-api.xml
+%{_datadir}/libvirt/api/libvirt-lxc-api.xml
%doc docs/*.html docs/html docs/*.gif
%doc docs/libvirt-api.xml
diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in
index 4695895..eaccfe6 100644
--- a/mingw-libvirt.spec.in
+++ b/mingw-libvirt.spec.in
@@ -189,10 +189,12 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%{mingw32_bindir}/virt-xml-validate
%{mingw32_bindir}/virt-pki-validate
%{mingw32_bindir}/virt-host-validate.exe
+%{mingw32_bindir}/libvirt-lxc-0.dll
%{mingw32_bindir}/libvirt-qemu-0.dll
%{mingw32_libdir}/libvirt.dll.a
%{mingw32_libdir}/pkgconfig/libvirt.pc
+%{mingw32_libdir}/libvirt-lxc.dll.a
%{mingw32_libdir}/libvirt-qemu.dll.a
%dir %{mingw32_datadir}/libvirt/
@@ -213,6 +215,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%{mingw32_datadir}/libvirt/schemas/storagevol.rng
%dir %{mingw32_datadir}/libvirt/api/
%{mingw32_datadir}/libvirt/api/libvirt-api.xml
+%{mingw32_datadir}/libvirt/api/libvirt-lxc-api.xml
%{mingw32_datadir}/libvirt/api/libvirt-qemu-api.xml
%{mingw32_datadir}/libvirt/cpu_map.xml
@@ -222,6 +225,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%dir %{mingw32_includedir}/libvirt
%{mingw32_includedir}/libvirt/libvirt.h
%{mingw32_includedir}/libvirt/virterror.h
+%{mingw32_includedir}/libvirt/libvirt-lxc.h
%{mingw32_includedir}/libvirt/libvirt-qemu.h
%{mingw32_mandir}/man1/virsh.1*
@@ -231,6 +235,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%files -n mingw32-libvirt-static
%{mingw32_libdir}/libvirt.a
+%{mingw32_libdir}/libvirt-lxc.a
%{mingw32_libdir}/libvirt-qemu.a
# Mingw64
@@ -243,10 +248,12 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%{mingw64_bindir}/virt-xml-validate
%{mingw64_bindir}/virt-pki-validate
%{mingw64_bindir}/virt-host-validate.exe
+%{mingw64_bindir}/libvirt-lxc-0.dll
%{mingw64_bindir}/libvirt-qemu-0.dll
%{mingw64_libdir}/libvirt.dll.a
%{mingw64_libdir}/pkgconfig/libvirt.pc
+%{mingw64_libdir}/libvirt-lxc.dll.a
%{mingw64_libdir}/libvirt-qemu.dll.a
%dir %{mingw64_datadir}/libvirt/
@@ -267,6 +274,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%{mingw64_datadir}/libvirt/schemas/storagevol.rng
%dir %{mingw64_datadir}/libvirt/api/
%{mingw64_datadir}/libvirt/api/libvirt-api.xml
+%{mingw64_datadir}/libvirt/api/libvirt-lxc-api.xml
%{mingw64_datadir}/libvirt/api/libvirt-qemu-api.xml
%{mingw64_datadir}/libvirt/cpu_map.xml
@@ -276,6 +284,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%dir %{mingw64_includedir}/libvirt
%{mingw64_includedir}/libvirt/libvirt.h
%{mingw64_includedir}/libvirt/virterror.h
+%{mingw64_includedir}/libvirt/libvirt-lxc.h
%{mingw64_includedir}/libvirt/libvirt-qemu.h
%{mingw64_mandir}/man1/virsh.1*
@@ -285,6 +294,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
%files -n mingw64-libvirt-static
%{mingw64_libdir}/libvirt.a
+%{mingw64_libdir}/libvirt-lxc.a
%{mingw64_libdir}/libvirt-qemu.a
diff --git a/python/Makefile.am b/python/Makefile.am
index 97f21c3..dd69600 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -35,6 +35,8 @@ EXTRA_DIST = \
libvirt-override.c \
libvirt-override.py \
libvirt-override-api.xml \
+ libvirt-lxc-override.c \
+ libvirt-lxc-override-api.xml \
libvirt-qemu-override.c \
libvirt-qemu-override-api.xml \
$(CLASSES_EXTRA) \
@@ -47,10 +49,13 @@ mylibs = \
myqemulibs = \
$(top_builddir)/src/libvirt-qemu.la \
$(top_builddir)/gnulib/lib/libgnu.la
+mylxclibs = \
+ $(top_builddir)/src/libvirt-lxc.la \
+ $(top_builddir)/gnulib/lib/libgnu.la
-all-local: libvirt.py libvirt_qemu.py
+all-local: libvirt.py libvirt_qemu.py libvirt_lxc.py
-pyexec_LTLIBRARIES = libvirtmod.la libvirtmod_qemu.la
+pyexec_LTLIBRARIES = libvirtmod.la libvirtmod_qemu.la libvirtmod_lxc.la
libvirtmod_la_SOURCES = libvirt-override.c typewrappers.c
nodist_libvirtmod_la_SOURCES = libvirt.c libvirt.h
@@ -74,6 +79,17 @@ libvirtmod_qemu_la_LDFLAGS = -module -avoid-version -shared
-L$(top_builddir)/sr
libvirtmod_qemu_la_LIBADD = $(myqemulibs) \
$(CYGWIN_EXTRA_LIBADD) $(CYGWIN_EXTRA_PYTHON_LIBADD)
+libvirtmod_lxc_la_SOURCES = libvirt-lxc-override.c typewrappers.c
+nodist_libvirtmod_lxc_la_SOURCES = libvirt-lxc.c libvirt-lxc.h
+# Python <= 2.4 header files contain a redundant decl, hence we
+# need extra flags here
+libvirtmod_lxc_la_CFLAGS = $(WARN_PYTHON_CFLAGS)
+
+libvirtmod_lxc_la_LDFLAGS = -module -avoid-version -shared -L$(top_builddir)/src/.libs \
+ $(CYGWIN_EXTRA_LDFLAGS)
+libvirtmod_lxc_la_LIBADD = $(mylxclibs) \
+ $(CYGWIN_EXTRA_LIBADD) $(CYGWIN_EXTRA_PYTHON_LIBADD)
+
GENERATE = generator.py
API_DESC = $(top_srcdir)/docs/libvirt-api.xml $(srcdir)/libvirt-override-api.xml
GENERATED= libvirt-export.c \
@@ -87,18 +103,26 @@ QEMU_GENERATED= libvirt-qemu-export.c \
libvirt-qemu.h \
libvirt_qemu.py
-$(GENERATE).stamp: $(srcdir)/$(GENERATE) $(API_DESC) $(QEMU_API_DESC)
+LXC_API_DESC = $(top_srcdir)/docs/libvirt-lxc-api.xml
$(srcdir)/libvirt-lxc-override-api.xml
+LXC_GENERATED= libvirt-lxc-export.c \
+ libvirt-lxc.c \
+ libvirt-lxc.h \
+ libvirt_lxc.py
+
+$(GENERATE).stamp: $(srcdir)/$(GENERATE) $(API_DESC) $(QEMU_API_DESC) $(LXC_API_DESC)
$(AM_V_GEN)$(PYTHON) $(srcdir)/$(GENERATE) $(PYTHON) && \
touch $@
-$(GENERATED) $(QEMU_GENERATED): $(GENERATE).stamp
+$(GENERATED) $(QEMU_GENERATED) $(LXC_GENERATED): $(GENERATE).stamp
$(libvirtmod_la_OBJECTS): $(GENERATED)
$(libvirtmod_qemu_la_OBJECTS): $(QEMU_GENERATED)
+$(libvirtmod_lxc_la_OBJECTS): $(LXC_GENERATED)
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(pyexecdir)
$(INSTALL) -m 0644 libvirt.py $(DESTDIR)$(pyexecdir)
+ $(INSTALL) -m 0644 libvirt_lxc.py $(DESTDIR)$(pyexecdir)
$(INSTALL) -m 0644 libvirt_qemu.py $(DESTDIR)$(pyexecdir)
$(mkinstalldirs) $(DESTDIR)$(DOCS_DIR)
@(for doc in $(DOCS) ; \
@@ -106,9 +130,10 @@ install-data-local:
uninstall-local:
rm -f $(DESTDIR)$(pyexecdir)/libvirt.py
+ rm -f $(DESTDIR)$(pyexecdir)/libvirt_lxc.py
rm -f $(DESTDIR)$(pyexecdir)/libvirt_qemu.py
-CLEANFILES= $(GENERATED) $(QEMU_GENERATED) $(GENERATE).stamp
+CLEANFILES= $(GENERATED) $(QEMU_GENERATED) $(LXC_GENERATED) $(GENERATE).stamp
else
all:
diff --git a/python/generator.py b/python/generator.py
index e9b9270..902d5d0 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -4,8 +4,10 @@
#
functions = {}
+lxc_functions = {}
qemu_functions = {}
enums = {} # { enumType: { enumConstant: enumValue } }
+lxc_enums = {} # { enumType: { enumConstant: enumValue } }
qemu_enums = {} # { enumType: { enumConstant: enumValue } }
import os
@@ -123,6 +125,8 @@ class docParser(xml.sax.handler.ContentHandler):
if (attrs['file'] == "libvirt" or
attrs['file'] == "virterror"):
enum(attrs['type'],attrs['name'],attrs['value'])
+ elif attrs['file'] == "libvirt-lxc":
+
lxc_enum(attrs['type'],attrs['name'],attrs['value'])
elif attrs['file'] == "libvirt-qemu":
qemu_enum(attrs['type'],attrs['name'],attrs['value'])
@@ -138,6 +142,11 @@ class docParser(xml.sax.handler.ContentHandler):
self.function_return, self.function_args,
self.function_file, self.function_module,
self.function_cond)
+ elif self.function_module == "libvirt-lxc":
+ lxc_function(self.function, self.function_descr,
+ self.function_return, self.function_args,
+ self.function_file, self.function_module,
+ self.function_cond)
elif self.function_module == "libvirt-qemu":
qemu_function(self.function, self.function_descr,
self.function_return, self.function_args,
@@ -148,6 +157,11 @@ class docParser(xml.sax.handler.ContentHandler):
self.function_return, self.function_args,
self.function_file, self.function_module,
self.function_cond)
+ elif self.function_file == "python-lxc":
+ lxc_function(self.function, self.function_descr,
+ self.function_return, self.function_args,
+ self.function_file, self.function_module,
+ self.function_cond)
elif self.function_file == "python-qemu":
qemu_function(self.function, self.function_descr,
self.function_return, self.function_args,
@@ -184,6 +198,9 @@ def function(name, desc, ret, args, file, module, cond):
def qemu_function(name, desc, ret, args, file, module, cond):
qemu_functions[name] = (desc, ret, args, file, module, cond)
+def lxc_function(name, desc, ret, args, file, module, cond):
+ lxc_functions[name] = (desc, ret, args, file, module, cond)
+
def enum(type, name, value):
if not enums.has_key(type):
enums[type] = {}
@@ -208,6 +225,11 @@ def enum(type, name, value):
if name[-5:] != '_LAST':
enums[type][name] = value
+def lxc_enum(type, name, value):
+ if not lxc_enums.has_key(type):
+ lxc_enums[type] = {}
+ lxc_enums[type][name] = value
+
def qemu_enum(type, name, value):
if not qemu_enums.has_key(type):
qemu_enums[type] = {}
@@ -222,10 +244,12 @@ def qemu_enum(type, name, value):
#######################################################################
functions_failed = []
+lxc_functions_failed = []
qemu_functions_failed = []
functions_skipped = [
"virConnectListDomains",
]
+lxc_functions_skipped = []
qemu_functions_skipped = []
skipped_modules = {
@@ -430,6 +454,10 @@ skip_impl = (
'virNodeGetCPUMap',
)
+lxc_skip_impl = (
+ 'virDomainLxcOpenNamespace',
+)
+
qemu_skip_impl = (
'virDomainQemuMonitorCommand',
'virDomainQemuAgentCommand',
@@ -501,6 +529,8 @@ skip_function = (
"virStorageVolGetConnect",
)
+lxc_skip_function = (
+)
qemu_skip_function = (
#"virDomainQemuAttach",
)
@@ -511,6 +541,7 @@ function_skip_python_impl = (
# be exposed in bindings
)
+lxc_function_skip_python_impl = ()
qemu_function_skip_python_impl = ()
function_skip_index_one = (
@@ -521,6 +552,7 @@ def print_function_wrapper(module, name, output, export, include):
global py_types
global unknown_types
global functions
+ global lxc_functions
global qemu_functions
global skipped_modules
global function_skip_python_impl
@@ -528,6 +560,8 @@ def print_function_wrapper(module, name, output, export, include):
try:
if module == "libvirt":
(desc, ret, args, file, mod, cond) = functions[name]
+ if module == "libvirt-lxc":
+ (desc, ret, args, file, mod, cond) = lxc_functions[name]
if module == "libvirt-qemu":
(desc, ret, args, file, mod, cond) = qemu_functions[name]
except:
@@ -543,6 +577,12 @@ def print_function_wrapper(module, name, output, export, include):
if name in skip_impl:
# Don't delete the function entry in the caller.
return 1
+ elif module == "libvirt-lxc":
+ if name in lxc_skip_function:
+ return 0
+ if name in lxc_skip_impl:
+ # Don't delete the function entry in the caller.
+ return 1
elif module == "libvirt-qemu":
if name in qemu_skip_function:
return 0
@@ -643,6 +683,10 @@ def print_function_wrapper(module, name, output, export, include):
include.write("libvirt_%s(PyObject *self, PyObject *args);\n" %
(name));
export.write(" { (char *)\"%s\", libvirt_%s, METH_VARARGS, NULL
},\n" %
(name, name))
+ elif module == "libvirt-lxc":
+ include.write("libvirt_lxc_%s(PyObject *self, PyObject *args);\n" %
(name));
+ export.write(" { (char *)\"%s\", libvirt_lxc_%s, METH_VARARGS,
NULL },\n" %
+ (name, name))
elif module == "libvirt-qemu":
include.write("libvirt_qemu_%s(PyObject *self, PyObject *args);\n" %
(name));
export.write(" { (char *)\"%s\", libvirt_qemu_%s, METH_VARARGS,
NULL },\n" %
@@ -666,6 +710,8 @@ def print_function_wrapper(module, name, output, export, include):
output.write("PyObject *\n")
if module == "libvirt":
output.write("libvirt_%s(PyObject *self ATTRIBUTE_UNUSED," % (name))
+ elif module == "libvirt-lxc":
+ output.write("libvirt_lxc_%s(PyObject *self ATTRIBUTE_UNUSED," %
(name))
elif module == "libvirt-qemu":
output.write("libvirt_qemu_%s(PyObject *self ATTRIBUTE_UNUSED," %
(name))
output.write(" PyObject *args")
@@ -698,6 +744,9 @@ def print_function_wrapper(module, name, output, export, include):
if module == "libvirt":
if name in function_skip_python_impl:
return 0
+ elif module == "libvirt-lxc":
+ if name in lxc_function_skip_python_impl:
+ return 0
elif module == "libvirt-qemu":
if name in qemu_function_skip_python_impl:
return 0
@@ -708,7 +757,7 @@ def buildStubs(module):
global py_return_types
global unknown_types
- if module not in ["libvirt", "libvirt-qemu"]:
+ if module not in ["libvirt", "libvirt-qemu",
"libvirt-lxc"]:
print "ERROR: Unknown module type: %s" % module
return None
@@ -716,6 +765,10 @@ def buildStubs(module):
funcs = functions
funcs_failed = functions_failed
funcs_skipped = functions_skipped
+ elif module == "libvirt-lxc":
+ funcs = lxc_functions
+ funcs_failed = lxc_functions_failed
+ funcs_skipped = functions_skipped
elif module == "libvirt-qemu":
funcs = qemu_functions
funcs_failed = qemu_functions_failed
@@ -1111,6 +1164,8 @@ def functionCompare(info1, info2):
def writeDoc(module, name, args, indent, output):
if module == "libvirt":
funcs = functions
+ elif module == "libvirt-lxc":
+ funcs = lxc_functions
elif module == "libvirt-qemu":
funcs = qemu_functions
if funcs[name][0] is None or funcs[name][0] == "":
@@ -1762,11 +1817,126 @@ def qemuBuildWrappers(module):
fd.close()
+def lxcBuildWrappers(module):
+ global lxc_functions
+
+ if not module == "libvirt-lxc":
+ print "ERROR: only libvirt-lxc is supported"
+ return None
+
+ extra_file = os.path.join(srcPref, "%s-override.py" % module)
+ extra = None
+
+ fd = open("libvirt_lxc.py", "w")
+
+ if os.path.exists(extra_file):
+ extra = open(extra_file, "r")
+ fd.write("#! " + python + " -i\n")
+ fd.write("#\n")
+ fd.write("# WARNING WARNING WARNING WARNING\n")
+ fd.write("#\n")
+ fd.write("# This file is automatically written by generator.py. Any
changes\n")
+ fd.write("# made here will be lost.\n")
+ fd.write("#\n")
+ fd.write("# To change the manually written methods edit " + module +
"-override.py\n")
+ fd.write("# To change the automatically written methods edit
generator.py\n")
+ fd.write("#\n")
+ fd.write("# WARNING WARNING WARNING WARNING\n")
+ fd.write("#\n")
+ if extra != None:
+ fd.writelines(extra.readlines())
+ fd.write("#\n")
+ fd.write("# WARNING WARNING WARNING WARNING\n")
+ fd.write("#\n")
+ fd.write("# Automatically written part of python bindings for libvirt\n")
+ fd.write("#\n")
+ fd.write("# WARNING WARNING WARNING WARNING\n")
+ if extra != None:
+ extra.close()
+
+ fd.write("try:\n")
+ fd.write(" import libvirtmod_lxc\n")
+ fd.write("except ImportError, lib_e:\n")
+ fd.write(" try:\n")
+ fd.write(" import cygvirtmod_lxc as libvirtmod_lxc\n")
+ fd.write(" except ImportError, cyg_e:\n")
+ fd.write(" if str(cyg_e).count(\"No module named\"):\n")
+ fd.write(" raise lib_e\n\n")
+
+ fd.write("import libvirt\n\n");
+ fd.write("#\n# Functions from module %s\n#\n\n" % module)
+ #
+ # Generate functions directly, no classes
+ #
+ for name in lxc_functions.keys():
+ func = nameFixup(name, 'None', None, None)
+ (desc, ret, args, file, mod, cond) = lxc_functions[name]
+ fd.write("def %s(" % func)
+ n = 0
+ for arg in args:
+ if n != 0:
+ fd.write(", ")
+ fd.write("%s" % arg[0])
+ n = n + 1
+ fd.write("):\n")
+ writeDoc(module, name, args, ' ', fd);
+
+ if ret[0] != "void":
+ fd.write(" ret = ");
+ else:
+ fd.write(" ");
+ fd.write("libvirtmod_lxc.%s(" % name)
+ n = 0
+
+ conn = None
+
+ for arg in args:
+ if arg[1] == "virConnectPtr":
+ conn = arg[0]
+
+ if n != 0:
+ fd.write(", ");
+ if arg[1] in ["virDomainPtr", "virConnectPtr"]:
+ # FIXME: This might have problem if the function
+ # has multiple args which are objects.
+ fd.write("%s.%s" % (arg[0], "_o"))
+ else:
+ fd.write("%s" % arg[0])
+ n = n + 1
+ fd.write(")\n");
+
+ if ret[0] != "void":
+ fd.write(" if ret is None: raise libvirt.libvirtError('" +
name + "() failed')\n")
+ if ret[0] == "virDomainPtr":
+ fd.write(" __tmp = virDomain(" + conn +
",_obj=ret)\n")
+ fd.write(" return __tmp\n")
+ else:
+ fd.write(" return ret\n")
+
+ fd.write("\n")
+
+ #
+ # Generate enum constants
+ #
+ for type,enum in lxc_enums.items():
+ fd.write("# %s\n" % type)
+ items = enum.items()
+ items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1])))
+ for name,value in items:
+ fd.write("%s = %s\n" % (name,value))
+ fd.write("\n");
+
+ fd.close()
+
+
quiet = 0
if buildStubs("libvirt") < 0:
sys.exit(1)
+if buildStubs("libvirt-lxc") < 0:
+ sys.exit(1)
if buildStubs("libvirt-qemu") < 0:
sys.exit(1)
buildWrappers("libvirt")
+lxcBuildWrappers("libvirt-lxc")
qemuBuildWrappers("libvirt-qemu")
sys.exit(0)
diff --git a/python/libvirt-lxc-override-api.xml b/python/libvirt-lxc-override-api.xml
new file mode 100644
index 0000000..db0d45d
--- /dev/null
+++ b/python/libvirt-lxc-override-api.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<api name='libvir-lxc-python'>
+ <symbols>
+ <function name='virDomainLxcOpenNamespace' file='python-lxc'>
+ <info><![CDATA[This API is LXC specific, so it will only work with
hypervisor
+connections to the LXC driver.
+
+Open the namespaces associated with the container @domain
+and return a list of file descriptors associated with the
+container.
+
+The returned file descriptors are intended to be used with
+the setns() system call.]]></info>
+ <return type='int' info='the list of open file descriptors, or -1 on
error'/>
+ <arg name='domain' type='virDomainPtr' info='a domain
object'/>
+ <arg name='flags' type='unsigned int' info='currently
unused, pass 0'/>
+ </function>
+ </symbols>
+</api>
diff --git a/python/libvirt-lxc-override.c b/python/libvirt-lxc-override.c
new file mode 100644
index 0000000..33c9c0a
--- /dev/null
+++ b/python/libvirt-lxc-override.c
@@ -0,0 +1,141 @@
+/*
+ * libvir.c: this modules implements the main part of the glue of the
+ * libvir library and the Python interpreter. It provides the
+ * entry points where an automatically generated stub is
+ * unpractical
+ *
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * Daniel Veillard <veillard(a)redhat.com>
+ */
+
+#include <config.h>
+
+/* Horrible kludge to work around even more horrible name-space pollution
+ via Python.h. That file includes /usr/include/python2.5/pyconfig*.h,
+ which has over 180 autoconf-style HAVE_* definitions. Shame on them. */
+#undef HAVE_PTHREAD_H
+
+#include <Python.h>
+#include "libvirt/libvirt-lxc.h"
+#include "libvirt/virterror.h"
+#include "typewrappers.h"
+#include "libvirt-lxc.h"
+#include "viralloc.h"
+#include "virfile.h"
+
+#ifndef __CYGWIN__
+extern void initlibvirtmod_lxc(void);
+#else
+extern void initcygvirtmod_lxc(void);
+#endif
+
+#if 0
+# define DEBUG_ERROR 1
+#endif
+
+#if DEBUG_ERROR
+# define DEBUG(fmt, ...) \
+ printf(fmt, __VA_ARGS__)
+#else
+# define DEBUG(fmt, ...) \
+ do {} while (0)
+#endif
+
+/* The two-statement sequence "Py_INCREF(Py_None); return Py_None;"
+ is so common that we encapsulate it here. Now, each use is simply
+ return VIR_PY_NONE; */
+#define VIR_PY_NONE (Py_INCREF (Py_None), Py_None)
+#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
+#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
+
+/************************************************************************
+ * *
+ * Statistics *
+ * *
+ ************************************************************************/
+
+static PyObject *
+libvirt_lxc_virDomainLxcOpenNamespace(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ PyObject *py_retval;
+ virDomainPtr domain;
+ PyObject *pyobj_domain;
+ unsigned int flags;
+ int c_retval;
+ int *fdlist = NULL;
+ int i;
+
+ if (!PyArg_ParseTuple(args, (char *)"Oi:virDomainLxcOpenNamespace",
+ &pyobj_domain, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if (domain == NULL)
+ return VIR_PY_NONE;
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virDomainLxcOpenNamespace(domain, &fdlist, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ py_retval = PyList_New(c_retval);
+ for (i = 0 ; i < c_retval ; i++) {
+ PyObject *item = NULL;
+
+ if ((item = PyInt_FromLong(fdlist[i])) == NULL)
+ goto error;
+
+ if (PyList_Append(py_retval, item) < 0) {
+ Py_DECREF(item);
+ goto error;
+ }
+ }
+ return py_retval;
+
+error:
+ for (i = 0 ; i < c_retval ; i++) {
+ VIR_FORCE_CLOSE(fdlist[i]);
+ }
+ VIR_FREE(fdlist);
+ return VIR_PY_NONE;
+}
+/************************************************************************
+ * *
+ * The registration stuff *
+ * *
+ ************************************************************************/
+static PyMethodDef libvirtLxcMethods[] = {
+#include "libvirt-lxc-export.c"
+ {(char *) "virDomainLxcOpenNamespace",
libvirt_lxc_virDomainLxcOpenNamespace, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL}
+};
+
+void
+#ifndef __CYGWIN__
+initlibvirtmod_lxc
+#else
+initcygvirtmod_lxc
+#endif
+ (void)
+{
+ static int initialized = 0;
+
+ if (initialized != 0)
+ return;
+
+ if (virInitialize() < 0)
+ return;
+
+ /* initialize the python extension module */
+ Py_InitModule((char *)
+#ifndef __CYGWIN__
+ "libvirtmod_lxc"
+#else
+ "cygvirtmod_lxc"
+#endif
+ , libvirtLxcMethods);
+
+ initialized = 1;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 494c184..13b7e30 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,7 +36,7 @@ if WITH_NETWORK
UUID=$(shell uuidgen 2>/dev/null)
endif
-lib_LTLIBRARIES = libvirt.la libvirt-qemu.la
+lib_LTLIBRARIES = libvirt.la libvirt-qemu.la libvirt-lxc.la
moddir = $(libdir)/libvirt/connection-driver
mod_LTLIBRARIES =
@@ -1480,6 +1480,13 @@ libvirt_qemu.def: $(srcdir)/libvirt_qemu.syms
chmod a-w $@-tmp && \
mv $@-tmp libvirt_qemu.def
+libvirt_lxc.def: $(srcdir)/libvirt_lxc.syms
+ $(AM_V_GEN)rm -f -- $@-tmp $@ ; \
+ printf 'EXPORTS\n' > $@-tmp && \
+ sed -e '/^$$/d; /#/d; /:/d; /}/d; /\*/d; /LIBVIRT_/d; s/[ ]*\(.*\)\;/ \1/g'
$^ >> $@-tmp && \
+ chmod a-w $@-tmp && \
+ mv $@-tmp libvirt_lxc.def
+
# Empty source list - it merely links a bunch of convenience libs together
libvirt_la_SOURCES =
libvirt_la_LDFLAGS = $(VERSION_SCRIPT_FLAGS)$(LIBVIRT_SYMBOL_FILE) \
@@ -1566,6 +1573,15 @@ libvirt_qemu_la_CFLAGS = $(AM_CFLAGS)
libvirt_qemu_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE)
+libvirt_lxc_la_SOURCES = libvirt-lxc.c
+libvirt_lxc_la_LDFLAGS = $(VERSION_SCRIPT_FLAGS)$(LIBVIRT_LXC_SYMBOL_FILE) \
+ -version-info $(LIBVIRT_VERSION_INFO) \
+ $(CYGWIN_EXTRA_LDFLAGS) $(MINGW_EXTRA_LDFLAGS) \
+ $(AM_LDFLAGS)
+libvirt_lxc_la_CFLAGS = $(AM_CFLAGS)
+libvirt_lxc_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
+EXTRA_DIST += $(LIBVIRT_LXC_SYMBOL_FILE)
+
lockdriverdir = $(libdir)/libvirt/lock-driver
lockdriver_LTLIBRARIES =
diff --git a/src/driver.h b/src/driver.h
index 64d652f..80f06bd 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -915,6 +915,11 @@ typedef int
unsigned long long minimum,
unsigned int flags);
+typedef int
+ (*virDrvDomainLxcOpenNamespace)(virDomainPtr dom,
+ int **fdlist,
+ unsigned int flags);
+
/**
* _virDriver:
*
@@ -1107,6 +1112,7 @@ struct _virDriver {
virDrvNodeGetCPUMap nodeGetCPUMap;
virDrvDomainFSTrim domainFSTrim;
virDrvDomainSendProcessSignal domainSendProcessSignal;
+ virDrvDomainLxcOpenNamespace domainLxcOpenNamespace;
};
typedef int
diff --git a/src/internal.h b/src/internal.h
index 8d96660..ebc91c7 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -40,6 +40,7 @@
# define N_(str) str
# include "libvirt/libvirt.h"
+# include "libvirt/libvirt-lxc.h"
# include "libvirt/libvirt-qemu.h"
# include "libvirt/virterror.h"
diff --git a/src/libvirt-lxc.c b/src/libvirt-lxc.c
new file mode 100644
index 0000000..0de498b
--- /dev/null
+++ b/src/libvirt-lxc.c
@@ -0,0 +1,165 @@
+/*
+ * libvirt-lxc.c: Interfaces for the libvirt library to handle lxc-specific
+ * APIs.
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library 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 library 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 library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virprocess.h"
+#include "datatypes.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#define virLibConnError(conn, error, info) \
+ virReportErrorHelper(VIR_FROM_NONE, error, NULL, __FUNCTION__, \
+ __LINE__, info)
+
+#define virLibDomainError(domain, error, info) \
+ virReportErrorHelper(VIR_FROM_DOM, error, NULL, __FUNCTION__, \
+ __LINE__, info)
+
+/**
+ * virDomainLxcOpenNamespace:
+ * @domain: a domain object
+ * @fdlist: pointer to an array to be filled with FDs
+ * @flags: currently unused, pass 0
+ *
+ * This API is LXC specific, so it will only work with hypervisor
+ * connections to the LXC driver.
+ *
+ * Open the namespaces associated with the container @domain.
+ * The @fdlist array will be allocated to a suitable size,
+ * and filled with file descriptors for the namespaces. It
+ * is the caller's responsibility to close the file descriptors
+ *
+ * The returned file descriptors are intended to be used with
+ * the setns() system call.
+ *
+ * Returns the number of opened file descriptors, or -1 on error
+ */
+int
+virDomainLxcOpenNamespace(virDomainPtr domain,
+ int **fdlist,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("domain=%p, fdlist=%p flags=%x",
+ domain, fdlist, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = domain->conn;
+
+ virCheckNonNullArgGoto(fdlist, error);
+
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->driver->domainLxcOpenNamespace) {
+ int ret;
+ ret = conn->driver->domainLxcOpenNamespace(domain,
+ fdlist,
+ flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
+ * virDomainLxcEnterNamespace:
+ * @domain: a domain object
+ * @nfdlist: number of FDs in @fdlist
+ * @fdlist: list of namespace file descriptors
+ * @noldfdlist: filled with number of old FDs
+ * @oldfdlist: pointer to hold list of old namespace file descriptors
+ * @flags: currently unused, pass 0
+ *
+ * This API is LXC specific, so it will only work with hypervisor
+ * connections to the LXC driver.
+ *
+ * Attaches the process to the namespaces associated
+ * with the FDs in @fdlist
+ *
+ * If @oldfdlist is non-NULL, it will be populated with file
+ * descriptors representing the old namespace. This allows
+ * the caller to switch back to its current namespace later
+ *
+ * Returns 0 on success, -1 on error
+ */
+int
+virDomainLxcEnterNamespace(virDomainPtr domain,
+ unsigned int nfdlist,
+ int *fdlist,
+ unsigned int *noldfdlist,
+ int **oldfdlist,
+ unsigned int flags)
+{
+ int i;
+
+ virCheckFlags(0, -1);
+
+ if (noldfdlist && oldfdlist) {
+ size_t nfds;
+ if (virProcessGetNamespaces(getpid(),
+ &nfds,
+ oldfdlist) < 0)
+ goto error;
+ *noldfdlist = nfds;
+ }
+
+ if (virProcessSetNamespaces(nfdlist, fdlist) < 0) {
+ if (oldfdlist && noldfdlist) {
+ for (i = 0 ; i < *noldfdlist ; i++) {
+ VIR_FORCE_CLOSE((*oldfdlist)[i]);
+ }
+ VIR_FREE(*oldfdlist);
+ *noldfdlist = 0;
+ }
+ goto error;
+ }
+
+ return 0;
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+}
diff --git a/src/libvirt_lxc.syms b/src/libvirt_lxc.syms
new file mode 100644
index 0000000..b5be18b
--- /dev/null
+++ b/src/libvirt_lxc.syms
@@ -0,0 +1,17 @@
+#
+# Officially exported symbols, for which header
+# file definitions are installed in /usr/include/libvirt
+# from libvirt-lxc.h
+#
+# Versions here are *fixed* to match the libvirt version
+# at which the symbol was introduced. This ensures that
+# a new client app requiring symbol foo() can't accidentally
+# run with old libvirt-lxc.so not providing foo() - the global
+# soname version info can't enforce this since we never
+# change the soname
+#
+LIBVIRT_LXC_1.0.2 {
+ global:
+ virDomainLxcEnterNamespace;
+ virDomainLxcOpenNamespace;
+};
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 8050ce6..025c35f 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -4544,6 +4544,7 @@ static virDriver lxcDriver = {
.domainShutdown = lxcDomainShutdown, /* 1.0.1 */
.domainShutdownFlags = lxcDomainShutdownFlags, /* 1.0.1 */
.domainReboot = lxcDomainReboot, /* 1.0.1 */
+ .domainLxcOpenNamespace = lxcDomainOpenNamespace, /* 1.0.2 */
};
static virStateDriver lxcStateDriver = {
diff --git a/tools/virsh.c b/tools/virsh.c
index 283194a..51615ec 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -62,6 +62,7 @@
#include "viralloc.h"
#include "virxml.h"
#include "libvirt/libvirt-qemu.h"
+#include "libvirt/libvirt-lxc.h"
#include "virfile.h"
#include "configmake.h"
#include "virthread.h"
--
1.7.11.7