[Buildd-tools-devel] schroot: union filesystem based schroots

Jan-Marek Glogowski glogow at fbihome.de
Tue Jan 22 18:41:32 UTC 2008


Hi

The attached patch implements session chroots using a union filesystem
like aufs or unionfs.

It's a first implementation based on the code for LVM snapshots.
It's not well tested yet (just Etch and unionfs 1.4), but I want to get
some feedback, especially how to solve the following problem:

Old unionfs crashs, if you change any of it's branches not throught
unionfs while unionfs is overlaying them. Therefore I need some lock when
someone wants to enter the parent changeroot, while sessions are running.
This should block new sessions from startup, and should block the parent
until all sessions are closed.

Thanks for your comments

Jan-Marek
-------------- next part --------------
 bin/schroot/Makefile.am          |    4 +-
 bin/schroot/schroot.conf.5.in    |   44 +++++-
 bin/schroot/setup/00check        |    2 +-
 bin/schroot/setup/05fsunion      |   74 +++++++++
 bin/schroot/setup/Makefile.am    |    1 +
 bootstrap                        |    2 +
 configure.ac                     |    2 +-
 debian/control                   |    2 +-
 sbuild/Makefile.am               |    2 +
 sbuild/sbuild-chroot-fs-union.cc |  321 ++++++++++++++++++++++++++++++++++++++
 sbuild/sbuild-chroot-fs-union.h  |  195 +++++++++++++++++++++++
 sbuild/sbuild-chroot.cc          |    3 +
 sbuild/sbuild-session.cc         |   10 ++
 13 files changed, 653 insertions(+), 9 deletions(-)

diff --git a/bin/schroot/Makefile.am b/bin/schroot/Makefile.am
index 4567b93..572b11a 100644
--- a/bin/schroot/Makefile.am
+++ b/bin/schroot/Makefile.am
@@ -70,5 +70,5 @@ install-exec-hook:
 	chmod 4755 "$(DESTDIR)$(bindir)/schroot"
 
 install-data-hook:
-	$(MKINSTALLDIRS) $(DESTDIR)$(SCHROOT_MOUNT_DIR)
-	$(MKINSTALLDIRS) $(DESTDIR)$(SCHROOT_SESSION_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_MOUNT_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_SESSION_DIR)
diff --git a/bin/schroot/schroot.conf.5.in b/bin/schroot/schroot.conf.5.in
index 52c9172..6d184cd 100644
--- a/bin/schroot/schroot.conf.5.in
+++ b/bin/schroot/schroot.conf.5.in
@@ -43,8 +43,8 @@ This is then followed by several key-value pairs, one per line:
 .TP
 \f[CBI]type=\fP\f[CI]type\fP
 The type of the chroot.  Valid types are \[oq]plain\[cq], \[oq]directory\[cq],
-\[oq]file\[cq], \[oq]block\-device\[cq] and \[oq]lvm\-snapshot\[cq].  If empty
-or omitted, the default type is \[oq]plain\[cq].
+\[oq]file\[cq], \[oq]block\-device\[cq], \[oq]lvm\-snapshot\[cq] and 
+\[oq]fs\-union\[cq].  If empty or omitted, the default type is \[oq]plain\[cq].
 .TP
 \f[CBI]description=\fP\f[CI]description\fP
 A short description of the chroot.  This may be localised for different
@@ -187,8 +187,8 @@ They have additional options:
 This is the device name of the block device, including the absolute path.  For
 example, \[lq]/dev/sda5\[rq].
 .TP
-\f[CBI]mount-options=\fP\f[CI]mount_options\fP Mount options for the block
-device.  These are additional options to pass to
+\f[CBI]mount-options=\fP\f[CI]mount_options\fP
+Mount options for the block device.  These are additional options to pass to
 .BR mount (8).
 For example, \[lq]\-o atime,sync,user_xattr\[rq].
 .TP
@@ -219,6 +219,42 @@ example, \[lq]\-L 2g\[rq] to create a snapshot 2 GiB in size.
 .B Note:
 the LV name (\fI\-n\fP), the snapshot option (\fI\-s\fP) and the original LV
 path may not be specfied here; they are set automatically by schroot.
+.SS
+Filesystem union chroots
+.PP
+Chroots of type \[oq]fs\-union\[cq] use a union filesystem to merge two
+directories mounted at a third.  The source chroot is mounted as a read-only
+branch, which is overlayed by a writeable session directory.  At the end of
+the session, the union filesystem is unmounted and the session directory is
+deleted.  
+For each chroot of this type, a corresponding \[oq]directory\[cq] chroot will
+be created, with a \fI\-source\fP suffix appended to the chroot name and all
+its aliases; this is for convenient access to the read-only branch, i.e. to 
+update the chroot.
+.PP
+The chroots implement the \fBsource chroot\fP options (see \[lq]\fISource 
+chroot options\fP\[rq], below), and all the options for \[oq]directory\[cq], 
+plus some additional option:
+.TP
+\f[CBI]fs-type=\fP\f[CI]filesystem1,filesystem2,...,any\fP
+Allows to set the used filesystem.  This is especially important, if you use 
+the \fIfs-branch-config\fP option to specify different options. Currently
+supported filesystems are \[oq]aufs\[cq] and \[oq]unionfs\[cq].  The special
+flag \[oq]any\[cq] will be replaced by all supported, but not listed
+filesystems. Default is \[oq]any\[cq].
+.TP
+\f[CBI]fs-branch-config=\fP\f[CI]branch_config\fP
+The branch configuration is used for the first filesystem in the \fIfs-type\fP
+filesystem list.  It replaces the complete \[lq]\-o\[rq] string for mount and
+allows to make complex filesystem unions. 
+.B Note:
+You can use the variables \[lq]${CHROOT_FS_UNION_OVERLAY_DIRECTORY}\[rq] and 
+\[lq]${CHROOT_LOCATION}\[rq] in this option string, which will be replaced
+with the writeable session directory and the source-chroot directory.
+.TP
+\f[CBI]overlay-base=directory
+This specifies the base directory, where the session writeable directories
+will be created. Default is \[oq]$TEMP\[cq], fallback is \[oq]/tmp\[cq].
 .SS Source chroot options
 .PP
 Some chroots implement source chroots.  These are chroots which automatically
diff --git a/bin/schroot/setup/00check b/bin/schroot/setup/00check
index c76ee01..c4758c9 100755
--- a/bin/schroot/setup/00check
+++ b/bin/schroot/setup/00check
@@ -62,7 +62,7 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
     fi
 
     case "$CHROOT_TYPE" in
-	plain | directory)
+	plain | directory | fs-union)
 	    if [ ! -d "$CHROOT_LOCATION" ]; then
 		echo "Directory '$CHROOT_LOCATION' does not exist"
 		exit 1
diff --git a/bin/schroot/setup/05fsunion b/bin/schroot/setup/05fsunion
new file mode 100755
index 0000000..95fe29d
--- /dev/null
+++ b/bin/schroot/setup/05fsunion
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Copyright ?? 2008  Jan-Marek Glogowski <glogow at fbihome.de>
+#
+# schroot is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# schroot 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+#####################################################################
+
+set -e
+
+if [ -f "$CHROOT_SCRIPT_CONFIG" ]; then
+    . "$CHROOT_SCRIPT_CONFIG"
+fi
+
+if [ "$AUTH_VERBOSITY" = "verbose" ]; then
+    VERBOSE="-v"
+fi
+
+if [ "$CHROOT_TYPE" = "fs-union" ]; then
+
+    if [ $1 = "setup-start" ]; then
+	mkdir "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}"
+	mkdir "${CHROOT_MOUNT_LOCATION}"
+
+	for TYPE in $CHROOT_FS_UNION_TYPE; do
+
+	    # Try mounting the filesystem module
+	    if ! grep -q "${TYPE}$" /proc/filesystems; then
+		set +e
+		modprobe ${TYPE} &> /dev/null
+		set -e
+	    fi
+
+	    # Skip fs if not available
+	    if ! grep -q "${TYPE}$" /proc/filesystems; then
+		# branch config just works with the first fs
+		CHROOT_FS_UNION_BRANCH_CONFIG=""
+		continue
+	    fi
+
+	    # Prepare branch config for fs type
+	    if [ "x" = "x${CHROOT_FS_UNION_BRANCH_CONFIG}" ]; then
+		case $TYPE in
+		unionfs)
+                    CHROOT_FS_UNION_BRANCH_CONFIG="dirs=${CHROOT_FS_UNION_OVERLAY_DIRECTORY}=rw:${CHROOT_LOCATION}=ro"
+		    ;;
+		aufs)
+		    CHROOT_FS_UNION_BRANCH_CONFIG="br:${CHROOT_FS_UNION_OVERLAY_DIRECTORY}=rw,${CHROOT_LOCATION}=ro"
+		    ;;
+		esac
+	    fi
+
+            # Try mounting fs
+	    mount -t $TYPE -o $CHROOT_FS_UNION_BRANCH_CONFIG ${CHROOT_NAME} ${CHROOT_MOUNT_LOCATION}
+	done
+
+    elif [ $1 = "setup-stop" ]; then
+	umount ${CHROOT_NAME}
+	rm -rf ${CHROOT_FS_UNION_OVERLAY_DIRECTORY}
+    fi
+
+fi
+
diff --git a/bin/schroot/setup/Makefile.am b/bin/schroot/setup/Makefile.am
index 6549b09..5a0117f 100644
--- a/bin/schroot/setup/Makefile.am
+++ b/bin/schroot/setup/Makefile.am
@@ -27,6 +27,7 @@ setup_SCRIPTS =		\
 	00check		\
 	05lvm		\
 	05file		\
+	05fsunion	\
 	10mount		\
 	15killprocs	\
 	20copyfiles	\
diff --git a/bootstrap b/bootstrap
index 95176cd..53d052b 100755
--- a/bootstrap
+++ b/bootstrap
@@ -11,6 +11,8 @@ else
 fi
 sed -e "s/@RELEASE_DATE@/`date '+%d %b %Y'`/" -e "s/@RELEASE_UDATE@/`date '+%s'`/" scripts/schroot_release.m4.in > m4/schroot_release.m4
 
+echo "gettextize"
+gettextize --no-changelog
 echo "libtoolize"
 libtoolize --force --copy
 echo "autopoint"
diff --git a/configure.ac b/configure.ac
index 55e4726..5dc2580 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,7 +180,7 @@ AC_LANG([C++])
 AC_ENABLE_SHARED
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
-AM_GNU_GETTEXT_VERSION([0.14.5])
+AM_GNU_GETTEXT_VERSION([0.16.1])
 AM_GNU_GETTEXT([external])
 AC_PATH_PROG([FIND], [find])
 AC_PATH_PROG([XARGS], [xargs])
diff --git a/debian/control b/debian/control
index 26da01f..0e84b80 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,7 @@ Section: admin
 Priority: optional
 Maintainer: Debian buildd-tools Developers <buildd-tools-devel at lists.alioth.debian.org>
 Uploaders: Michael Banck <mbanck at debian.org>, Luk Claes <luk at debian.org>, Roger Leigh <rleigh at debian.org>, Francesco Paolo Lovergine <frankie at debian.org>
-Build-Depends: debhelper (>= 4.0.0), autotools-dev, pkg-config (>= 0.20), libpam0g-dev (>= 0.79-3.1), uuid-dev, liblockdev1-dev (>= 1.0.2-1), libboost-dev (>= 1.34.0-1), libboost-program-options-dev (>= 1.34.0-1), libboost-regex-dev (>= 1.34.0-1), gettext, libcppunit-dev
+Build-Depends: debhelper (>= 4.0.0), autotools-dev, pkg-config (>= 0.20), libpam0g-dev (>= 0.79-3.1), uuid-dev, liblockdev1-dev (>= 1.0.2-1), libboost-dev (>= 1.33.0-1), libboost-program-options-dev (>= 1.33.0-1), libboost-regex-dev (>= 1.33.0-1), gettext, libcppunit-dev
 Standards-Version: 3.7.2
 
 Package: schroot-common
diff --git a/sbuild/Makefile.am b/sbuild/Makefile.am
index a0080e9..1957100 100644
--- a/sbuild/Makefile.am
+++ b/sbuild/Makefile.am
@@ -40,6 +40,7 @@ sbuild_public_h_sources =		\
 	sbuild-chroot-plain.h		\
 	sbuild-chroot-source.h		\
 	sbuild-chroot-config.h		\
+	sbuild-chroot-fs-union.h	\
 	sbuild-ctty.h			\
 	sbuild-custom-error.h		\
 	sbuild-dirstream.h		\
@@ -80,6 +81,7 @@ sbuild_public_cc_sources =		\
 	sbuild-chroot-plain.cc		\
 	sbuild-chroot-source.cc		\
 	sbuild-chroot-config.cc		\
+	sbuild-chroot-fs-union.cc	\
 	sbuild-ctty.cc			\
 	sbuild-dirstream.cc		\
 	sbuild-environment.cc		\
diff --git a/sbuild/sbuild-chroot-fs-union.cc b/sbuild/sbuild-chroot-fs-union.cc
new file mode 100644
index 0000000..6c3172e
--- /dev/null
+++ b/sbuild/sbuild-chroot-fs-union.cc
@@ -0,0 +1,321 @@
+/* Copyright ?? 2005-2007  Roger Leigh <rleigh at debian.org>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "sbuild-chroot-fs-union.h"
+#include "sbuild-format-detail.h"
+#include "sbuild-lock.h"
+
+#include <cerrno>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
+using namespace sbuild;
+
+namespace
+{
+  typedef std::pair<chroot_fs_union::error_code,const char *> emap;
+
+  /**
+   * This is a list of the supported error codes.  It's used to
+   * construct the real error codes map.
+   */
+  emap init_errors[] =
+    {
+      // TRANSLATORS: %1% = chroot fs type
+      emap(chroot_fs_union::FS_TYPE_UNKNOWN,     N_("Unknown filesystem type '%1%'"))
+    };
+}
+
+template<>
+error<chroot_fs_union::error_code>::map_type
+error<chroot_fs_union::error_code>::error_strings
+(init_errors,
+ init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
+
+chroot_fs_union::chroot_fs_union ():
+  chroot_directory(),
+  chroot_source()
+{
+  char *tmpdir = getenv( "TEMP" );
+  if (tmpdir)
+    overlay_base = tmpdir;
+  else
+    overlay_base = "/tmp";
+
+  set_run_setup_scripts(true);
+  set_run_exec_scripts(true);
+}
+
+chroot_fs_union::~chroot_fs_union ()
+{
+}
+
+sbuild::chroot::ptr
+chroot_fs_union::clone () const
+{
+  return ptr(new chroot_fs_union(*this));
+}
+
+sbuild::chroot::ptr
+chroot_fs_union::clone_source () const
+{
+  ptr clone(new chroot_directory(*this));
+
+  chroot_source::clone_source_setup(clone);
+
+  return ptr(clone);
+}
+
+std::string const&
+chroot_fs_union::get_location () const
+{
+  return chroot::get_location();
+}
+
+void
+chroot_fs_union::set_location (std::string const& location)
+{
+  if (!is_absname(location))
+    throw chroot::error(location, LOCATION_ABS);
+
+  chroot::set_location(location);
+}
+
+std::string const&
+chroot_fs_union::get_overlay_directory () const
+{
+  return overlay_directory;
+}
+
+void
+chroot_fs_union::set_overlay_directory (std::string const& overlay_directory)
+{
+  if (!is_absname(overlay_directory))
+    throw chroot::error(overlay_directory, LOCATION_ABS);
+
+  this->overlay_directory = overlay_directory;
+}
+
+std::string const&
+chroot_fs_union::get_overlay_base () const
+{
+  return overlay_base;
+}
+
+void
+chroot_fs_union::set_overlay_base (std::string const& overlay_base)
+{
+  if (!is_absname(overlay_base))
+    throw chroot::error(overlay_base, LOCATION_ABS);
+
+  this->overlay_base = overlay_base;
+}
+
+std::string const&
+chroot_fs_union::get_fs_type () const
+{
+  return fs_type;
+}
+
+void
+chroot_fs_union::set_fs_type (std::string const& fs_type)
+{
+  enum FSTypes {
+    FS_AUFS,
+    FS_UNIONFS,
+    FS_ANY,
+    FS_MAX
+  };
+  const char* known_types[FS_MAX] = { "aufs", "unionfs", "any" };
+  bool        found_types[FS_MAX] = { false, };
+  std::string cleaned_string( "" );
+
+  // Remove multiple fs occurences and add fallbacks for any
+  string_list types = split_string(fs_type, " ");
+  for (string_list::const_iterator fs = types.begin();
+       fs != types.end();
+       ++fs) {
+
+    int i;
+    for (i = 0; i < FS_MAX; ++i) {
+      if (*fs == known_types[i] ) {
+        if (!found_types[i]) {
+	  if (i != FS_ANY)
+            cleaned_string += " " + *fs;
+          found_types[i] = true;
+        }
+        break;
+      }
+    }
+
+    // Throw exception for unknown fs
+    if (i == FS_MAX)
+      throw error(*fs, FS_TYPE_UNKNOWN);
+
+    // Add all non found alternatives
+    if (i == FS_ANY) {
+      for (i = 0; i < FS_ANY; ++i) {
+        if (!found_types[i]) {
+          cleaned_string += " ";
+	  cleaned_string += known_types[i];
+        }
+      }
+      break;
+    }
+  }
+
+  // Skip leading space from concat
+  if (cleaned_string.size() > 0) {
+    cleaned_string = cleaned_string.substr(1);
+  }
+  else
+    throw error(fs_type, FS_TYPE_UNKNOWN);
+  
+  this->fs_type = cleaned_string;
+}
+
+std::string const&
+chroot_fs_union::get_fs_branch_config () const
+{
+  return fs_branch_config;
+}
+
+void
+chroot_fs_union::set_fs_branch_config (std::string const& fs_branch_config)
+{
+  this->fs_branch_config = fs_branch_config;
+}
+
+std::string
+chroot_fs_union::get_path () const
+{
+  // When running setup scripts, we are session-capable, so the path
+  // is the bind-mounted location, rather than the original location.
+  if (get_run_setup_scripts() == true)
+    return get_mount_location();
+  else
+    return get_location();
+}
+
+std::string const&
+chroot_fs_union::get_chroot_type () const
+{
+  static const std::string type("fs-union");
+
+  return type;
+}
+
+void
+chroot_fs_union::setup_env (environment& env)
+{
+  chroot_directory::setup_env(env);
+  chroot_source::setup_env(env);
+
+  env.add("CHROOT_FS_UNION_TYPE", get_fs_type());
+  env.add("CHROOT_FS_UNION_OVERLAY_DIRECTORY", get_overlay_directory());
+  env.add("CHROOT_FS_UNION_BRANCH_CONFIG", get_fs_branch_config());
+}
+
+void
+chroot_fs_union::setup_lock (chroot::setup_type type,
+			      bool               lock,
+			      int                status)
+{
+  /* By default, directory chroots do no locking. */
+  /* Create or unlink session information. */
+  if ((type == SETUP_START && lock == true) ||
+      (type == SETUP_STOP && lock == false && status == 0))
+    {
+      bool start = (type == SETUP_START);
+      setup_session_info(start);
+    }
+}
+
+sbuild::chroot::session_flags
+chroot_fs_union::get_session_flags () const
+{
+  return SESSION_CREATE;
+}
+
+void
+chroot_fs_union::get_details (format_detail& detail) const
+{
+  chroot_directory::get_details(detail);
+  chroot_source::get_details(detail);
+
+  if (!this->overlay_directory.empty())
+    detail.add(_("Filesystem union overlay directory"), get_overlay_directory());
+  if (!this->fs_branch_config.empty())
+    detail.add(_("Filesystem union branch config"), get_fs_branch_config());
+}
+
+void
+chroot_fs_union::get_keyfile (keyfile& keyfile) const
+{
+  chroot_directory::get_keyfile(keyfile);
+  chroot_source::get_keyfile(keyfile);
+
+  keyfile::set_object_value(*this, &chroot_fs_union::get_location,
+			    keyfile, get_name(), "location");
+  keyfile::set_object_value(*this, &chroot_fs_union::get_overlay_directory,
+			    keyfile, get_name(), "overlay-directory");
+  keyfile::set_object_value(*this, &chroot_fs_union::get_overlay_base,
+			    keyfile, get_name(), "overlay-base");
+  keyfile::set_object_value(*this, &chroot_fs_union::get_fs_type,
+			    keyfile, get_name(), "fs-type");
+  keyfile::set_object_value(*this, &chroot_fs_union::get_fs_branch_config,
+			    keyfile, get_name(), "fs-branch-config");
+}
+
+void
+chroot_fs_union::set_keyfile (keyfile const& keyfile,
+			      string_list&   used_keys)
+{
+  chroot_directory::set_keyfile(keyfile, used_keys);
+  chroot_source::set_keyfile(keyfile, used_keys);
+
+  keyfile::get_object_value(*this, &chroot_fs_union::set_location,
+			    keyfile, get_name(), "location",
+			    keyfile::PRIORITY_REQUIRED);
+  keyfile::get_object_value(*this, &chroot_fs_union::set_overlay_directory,
+			    keyfile, get_name(), "overlay-directory",
+			    get_active() ?
+			    keyfile::PRIORITY_REQUIRED :
+			    keyfile::PRIORITY_OPTIONAL);
+  keyfile::get_object_value(*this, &chroot_fs_union::set_overlay_base,
+			    keyfile, get_name(), "overlay-base",
+			    keyfile::PRIORITY_OPTIONAL);
+  keyfile::get_object_value(*this, &chroot_fs_union::set_fs_type,
+			    keyfile, get_name(), "fs-type",
+			    keyfile::PRIORITY_REQUIRED);
+  keyfile::get_object_value(*this, &chroot_fs_union::set_fs_branch_config,
+			    keyfile, get_name(), "fs-branch-config",
+			    keyfile::PRIORITY_OPTIONAL);
+
+  used_keys.push_back("location");
+  used_keys.push_back("overlay-directory");
+  used_keys.push_back("overlay-base");
+  used_keys.push_back("fs-type");
+  used_keys.push_back("fs-branch-config");
+}
+
diff --git a/sbuild/sbuild-chroot-fs-union.h b/sbuild/sbuild-chroot-fs-union.h
new file mode 100644
index 0000000..e0959a5
--- /dev/null
+++ b/sbuild/sbuild-chroot-fs-union.h
@@ -0,0 +1,195 @@
+/* Copyright ?? 2005-2007  Roger Leigh <rleigh at debian.org>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#ifndef SBUILD_CHROOT_FS_UNION_H
+#define SBUILD_CHROOT_FS_UNION_H
+
+#include <sbuild/sbuild-chroot-directory.h>
+#include <sbuild/sbuild-chroot-source.h>
+
+namespace sbuild
+{
+  /**
+   * A chroot stored in a directory.
+   *
+   * A filesystem union will be created and mounted on demand.
+   */
+  class chroot_fs_union : public chroot_directory,
+                          public chroot_source
+  {
+  protected:
+    /// The constructor.
+    chroot_fs_union ();
+
+    friend class chroot;
+
+  public:
+    /// The destructor.
+    virtual ~chroot_fs_union ();
+
+    virtual chroot::ptr
+    clone () const;
+
+    virtual chroot::ptr
+    clone_source () const;
+
+    /// Error codes.
+    enum error_code
+      {
+	FS_TYPE_UNKNOWN      ///< Unknown union fs type
+      };
+
+    /// Exception type.
+    typedef custom_error<error_code> error;
+
+    /**
+     * Get the directory location of the chroot.
+     *
+     * @returns the location.
+     */
+    virtual std::string const&
+    get_location () const;
+
+    /**
+     * Get the union filesystem type.
+     *
+     * @see set_fs_type
+     * @returns the union filesytem type.
+     */
+    virtual std::string const&
+    get_fs_type () const;
+
+    /**
+     * Get the union filesystem branch configuration.
+     *
+     * @see set_fs_branch_config
+     * @returns the union filesystem branch configuration.
+     */
+    virtual std::string const&
+    get_fs_branch_config () const;
+
+    /**
+     * Get the overlay base directory.
+     *
+     * @see set_overlay_directory
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_overlay_base () const;
+
+    /**
+     * Get the writeable overlay directory of the session.
+     *
+     * @see set_overlay_directory
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_overlay_directory () const;
+
+    /**
+     * Set the directory location of the chroot.
+     *
+     * @param location the location.
+     */
+    virtual void
+    set_location (std::string const& location);
+
+    /**
+     * Set the union filesystem type.
+     * Currently supported values are aufs and unionfs.
+     *
+     * @param fs_type the filesystem type.
+     **/
+    virtual void
+    set_fs_type (std::string const& fs_type);
+
+    /**
+     * Set a complex branch configuration.
+     * Normally a temporary directory is used as the writeable branch, which is
+     * removed on session end. This allows to build a complex union chroot 
+     * which can merge multiple branches. The has to be provided as expected by
+     * the union filesystem type, as it is directly used as the mount option.
+     *
+     * @param fs_branch_config a @fs_type specific branch description
+     **/
+    virtual void
+    set_fs_branch_config (std::string const& fs_branch_config);
+
+    /**
+     * Allows one to set a fixed write directory.
+     *
+     * @param the absolute path of the overlay_base.
+     **/
+    virtual void
+    set_overlay_base (std::string const& overlay_base);
+
+    /**
+     * Allows one to set a fixed write directory.
+     *
+     * @param the absolute path of the overlay_directory.
+     **/
+    virtual void
+    set_overlay_directory (std::string const& overlay_directory);
+
+    virtual std::string
+    get_path () const;
+
+    virtual std::string const&
+    get_chroot_type () const;
+
+    virtual void
+    setup_env (environment& env);
+
+    virtual session_flags
+    get_session_flags () const;
+
+  protected:
+    virtual void
+    setup_lock (chroot::setup_type type,
+		bool               lock,
+		int                status);
+
+    virtual void
+    get_details (format_detail& detail) const;
+
+    virtual void
+    get_keyfile (keyfile& keyfile) const;
+
+    virtual void
+    set_keyfile (keyfile const& keyfile,
+                 string_list&   used_keys);
+
+  private:
+    /// Union filesystem type
+    std::string fs_type;
+    /// Complex branch configuration to pass directly as mount option
+    std::string fs_branch_config;
+    /// Directory used as the overlay base
+    std::string overlay_base;
+    /// Writeable directory used as the overlay
+    std::string overlay_directory;
+  };
+}
+
+#endif /* SBUILD_CHROOT_FS_UNION_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/sbuild/sbuild-chroot.cc b/sbuild/sbuild-chroot.cc
index 039edb8..8d516f7 100644
--- a/sbuild/sbuild-chroot.cc
+++ b/sbuild/sbuild-chroot.cc
@@ -24,6 +24,7 @@
 #include "sbuild-chroot-file.h"
 #include "sbuild-chroot-block-device.h"
 #include "sbuild-chroot-lvm-snapshot.h"
+#include "sbuild-chroot-fs-union.h"
 #include "sbuild-lock.h"
 
 #include <cerrno>
@@ -128,6 +129,8 @@ sbuild::chroot::create (std::string const& type)
     new_chroot = new chroot_block_device();
   else if (type == "lvm-snapshot")
     new_chroot = new chroot_lvm_snapshot();
+  else if (type == "fs-union")
+    new_chroot = new chroot_fs_union();
   else
     throw error(type, CHROOT_TYPE);
 
diff --git a/sbuild/sbuild-session.cc b/sbuild/sbuild-session.cc
index 220a4fa..9935b5f 100644
--- a/sbuild/sbuild-session.cc
+++ b/sbuild/sbuild-session.cc
@@ -20,6 +20,7 @@
 
 #include "sbuild-chroot-plain.h"
 #include "sbuild-chroot-lvm-snapshot.h"
+#include "sbuild-chroot-fs-union.h"
 #include "sbuild-ctty.h"
 #include "sbuild-run-parts.h"
 #include "sbuild-session.h"
@@ -592,6 +593,15 @@ session::run_impl ()
 	      snapshot->set_snapshot_device(device);
 	    }
 
+	  /* Filesystem unions need the overlay directory specifying. */
+	  chroot_fs_union *overlay = 0;
+	  if ((overlay = dynamic_cast<chroot_fs_union *>(chroot.get())) != 0)
+	    {
+	      std::string dir = overlay->get_overlay_base();
+              dir += "/" + this->session_id;
+	      overlay->set_overlay_directory(dir);
+	    }
+
 	  try
 	    {
 	      /* Run setup-start chroot setup scripts. */


More information about the Buildd-tools-devel mailing list