From: "Daniel P. Berrange" <berra...@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 <berra...@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 <berra...@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 <veill...@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 <berra...@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 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list