[buildd-tools-devel] [Buildd-tools-devel] [PATCH 15/22] Filesystem union chroot options support

Roger Leigh rleigh at codelibre.net
Wed Apr 1 22:38:59 UTC 2009


On Thu, Mar 26, 2009 at 10:13:53PM +0100, Jan-Marek Glogowski wrote:
> Introduces a new type of chroot options.  This allows chroot
> sessions to be generated using an unioning filesystem like aufs
> or unionfs.  Per default this feature is disabled.  Check out
> schroot.conf.5 for further information.

I'm quite happy with this patch, but have a few comments I'd just
like to check.  A slightly modified copy of the patch (just docs
changed) is attached.


I fixed up some spelling/grammar problems in schroot.conf.5.in.

.B Note:
One can use the variables \[lq]${CHROOT_FS_UNION_OVERLAY_DIRECTORY}\[rq] and
\[lq]${CHROOT_MOUNT_LOCATION}\[rq] in this option string, which will be
replaced with the writeable session directory and the source chroot directory,
respectively.

Yikes!  While it's certainly possible to use shell fragments in the
configuration file to pass through to the setup scripts, this isn't a
use case I've ever considered.  I would rather not publicise this
fact, since it will make changing the internal scripting interface
rather more difficult if people depend upon it.

Are these values strictly required?  If they aren't defaulted, we
should do so if appropriate?

Also, I think we should document the need for kernel module installation.

10mount:

There are a number of bashisms in the script.  If you run checkbashisms
you can see where you are using BASH-specific features rather than plain
Bourne shell (which we require due to the #!/bin/sh).

Why are we using modprobe here?  Isn't kmod called to insert the module
at mount time?  My own brief testing with aufs shows this to be the case.
Personally, I'd rather we steered clear of modprobing things and just
let things happen automatically.  Was there a need for an explicit
modprobe on your system?

Why do we skip (continue) on failure if the filesystem isn't available
rather than failing immediately?

Why is MOUNT_RES initialised to 255 rather than 0?

Why does do_mount_fs_union() use "break" when we aren't in a loop?
Likewise use of "continue"

Where does the CHROOT_MOUNT_DEVICE get mounted?  I don't see this in
the script.

Why do we use set +e/-e to save error for later handling when all it does
is exit anyway?  If we don't do anything special, it will die on all
failures (which is what happens in the patch, just in a different place).

-- 
  .''`.  Roger Leigh
 : :' :  Debian GNU/Linux             http://people.debian.org/~rleigh/
 `. `'   Printing on GNU/Linux?       http://gutenprint.sourceforge.net/
   `-    GPG Public Key: 0x25BFB848   Please GPG sign your mail.
-------------- next part --------------
diff --git a/bin/schroot/Makefile.am b/bin/schroot/Makefile.am
index eb7f71b..0b251e3 100644
--- a/bin/schroot/Makefile.am
+++ b/bin/schroot/Makefile.am
@@ -75,3 +75,5 @@ install-data-hook:
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_MOUNT_DIR)
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_SESSION_DIR)
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_UNPACK_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_OVERLAY_DIR)
+
diff --git a/bin/schroot/schroot.conf.5.in b/bin/schroot/schroot.conf.5.in
index e677171..13c38ed 100644
--- a/bin/schroot/schroot.conf.5.in
+++ b/bin/schroot/schroot.conf.5.in
@@ -276,6 +276,34 @@ example, if the filesystem contains a chroot in \fI/chroot/sid\fP, you would
 specify \[lq]/chroot/sid\[rq] here.  If the chroot is the only thing on the
 filesystem, i.e. \fI/\fP is the root filesystem for the chroot, this option
 should be left blank, or omitted entirely.
+.SS Filesystem union chroot options
+Some chroots allow creation of a session using filesystem unions to overlay the
+real data and redirect all modifications to a session-dependant directory.  To
+activate this feature, set \f[CI]fs\-union\-type\fP to any supported value.  If
+enabled, the chroot will also be a \fBsource chroot\fP, which will provide
+additional options (see \[lq]\fISource chroot options\fP\[rq], above).  All
+entries are optional.
+.TP
+\f[CBI]fs\-union\-type=\fP\f[CI]type\fP
+Set the union filesystem type.  This is especially important if you use the
+\fIfs\-union\-branch\-config\fP option to specify different options.  Currently
+supported filesystems are \[oq]aufs\[cq] and \[oq]unionfs\[cq].  The default is
+\[oq]none\[cq], which disables this feature.
+.TP
+\f[CBI]fs\-union\-branch\-config=\fP\f[CI]branch-config\fP
+The branch configuration is used for the first filesystem in the
+\fIfs\-union-type\fP union filesystem list.  It replaces the complete
+\[lq]\-o\[rq] string for mount and allows for the creation of complex
+filesystem unions.
+.B Note:
+One can use the variables \[lq]${CHROOT_FS_UNION_OVERLAY_DIRECTORY}\[rq] and
+\[lq]${CHROOT_MOUNT_LOCATION}\[rq] in this option string, which will be
+replaced with the writeable session directory and the source chroot directory,
+respectively.
+.TP
+\f[CBI]fs\-union\-overlay\-base\fP\f[CI]=directory\fP
+Specify the base directory, where the session writeable directories will be
+created.  The default is \[oq]@SCHROOT_OVERLAY_DIR@\[cq].
 .SS Localisation
 .PP
 Some keys may be localised in multiple languages.  This is achieved by adding
diff --git a/bin/schroot/setup/00check b/bin/schroot/setup/00check
index e71239a..76388c1 100755
--- a/bin/schroot/setup/00check
+++ b/bin/schroot/setup/00check
@@ -51,6 +51,10 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
 	echo "CHROOT_MOUNT_LOCATION=$CHROOT_MOUNT_LOCATION"
 	echo "CHROOT_LOCATION=$CHROOT_LOCATION"
 	echo "CHROOT_PATH=$CHROOT_PATH"
+	if [ "x" != "x$CHROOT_FS_UNION_TYPE" ] && [ "$CHROOT_FS_UNION_TYPE" != "none" ]; then
+            echo "CHROOT_FS_UNION_TYPE=$CHROOT_FS_UNION_TYPE"
+            echo "CHROOT_FS_UNION_OVERLAY_DIRECTORY=$CHROOT_FS_UNION_OVERLAY_DIRECTORY"
+	fi
 	if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ]; then
 	    echo "CHROOT_DIRECTORY=$CHROOT_DIRECTORY"
 	elif [ "$CHROOT_TYPE" = "file" ]; then
@@ -99,7 +103,11 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
 
     # A basic safety check, so that the root filesystem doesn't get
     # toasted by accident.
-    if [ -z "$CHROOT_PATH" ] || [ "$CHROOT_PATH" = "/" ] || [ "$CHROOT_DIRECTORY" = "/" ]; then
+    if [ -z "$CHROOT_PATH" ] \
+	|| [ "$CHROOT_PATH" = "/" ] \
+	|| [ "$CHROOT_DIRECTORY" = "/" ] \
+	|| [ "$CHROOT_FS_UNION_OVERLAY_DIRECTORY" = "/" ]
+    then
 	echo "Invalid chroot mount path or directory"
 	exit 1
     fi
diff --git a/bin/schroot/setup/10mount b/bin/schroot/setup/10mount
index b8a23b7..179cb06 100755
--- a/bin/schroot/setup/10mount
+++ b/bin/schroot/setup/10mount
@@ -41,10 +41,13 @@ do_mount()
     fi
     if [ ! -d "$3" ]; then
 	echo "$3 does not exist, and could not be created"
-	exit 1
+	return 1
     fi
 
-    mount $VERBOSE $1 "$2" "$3"
+    RESULT=0
+    mount $VERBOSE $1 "$2" "$3" || RESULT=$?
+
+    return $RESULT
 }
 
 # Unmount all filesystems under specified location
@@ -65,6 +68,57 @@ do_umount_all()
     fi
 }
 
+# Mount a filesystem union
+# $1: read-only branch
+do_mount_fs_union()
+{
+    # Try loading the filesystem module if not already present
+    if ! grep -q "${CHROOT_FS_UNION_TYPE}$" /proc/filesystems; then
+	set +e
+	modprobe ${CHROOT_FS_UNION_TYPE} &> /dev/null
+	set -e
+    fi
+
+    # Skip fs if not available
+    if ! grep -q "${CHROOT_FS_UNION_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 $CHROOT_FS_UNION_TYPE in
+	unionfs)
+	    CHROOT_FS_UNION_BRANCH_CONFIG="dirs=${CHROOT_FS_UNION_OVERLAY_DIRECTORY}=rw,${1}=ro"
+	    ;;
+	aufs)
+	    CHROOT_FS_UNION_BRANCH_CONFIG="br:${CHROOT_FS_UNION_OVERLAY_DIRECTORY}:${1}=ro"
+	    ;;
+	esac
+    fi
+
+    # Try mounting fs
+    MOUNT_RES=0
+
+    mount -t $CHROOT_FS_UNION_TYPE -o "$CHROOT_FS_UNION_BRANCH_CONFIG" ${CHROOT_NAME} ${CHROOT_MOUNT_LOCATION} || MOUNT_RES=$?
+
+    if [ 0 -eq $MOUNT_RES ]; then
+	break
+    fi
+
+    if [ 0 -ne $MOUNT_RES ]; then
+	echo "Mounting filesystem union failed"
+	return 1
+    fi
+
+    if [ "$AUTH_VERBOSITY" = "verbose" ]; then
+	echo "Using '$TYPE' for filesystem union"
+    fi
+
+    return 0
+}
+
 if [ "$AUTH_VERBOSITY" = "verbose" ]; then
   VERBOSE="-v"
 #  FSCK_VERBOSE="-V"
@@ -72,6 +126,14 @@ fi
 
 if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "loopback" ] || [ "$CHROOT_TYPE" = "block-device" ] || [ "$CHROOT_TYPE" = "lvm-snapshot" ]; then
 
+    if [ "xnone" != "x${CHROOT_FS_UNION_TYPE:-none}" ] \
+	&& [ "$CHROOT_SESSION_PURGE" = "true" ];
+    then
+	CREATE_FS_UNION="yes"
+    else
+	CREATE_FS_UNION="no"
+    fi
+
     if [ "$CHROOT_TYPE" = "plain" ]; then
 	CHROOT_MOUNT_OPTIONS="--rbind"
 	CHROOT_MOUNT_DEVICE="$CHROOT_DIRECTORY"
@@ -110,7 +172,17 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
 	    do_umount_all "$CHROOT_MOUNT_LOCATION"
 	fi
 
-	do_mount "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE" "$CHROOT_MOUNT_LOCATION"
+	if [ "xyes" = "x${CREATE_FS_UNION}" ]; then
+	    if ! do_mount_fs_union "$CHROOT_FS_UNION_RO_BRANCH"
+	    then
+		exit 1
+	    fi
+	else
+	    if ! do_mount "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE" "$CHROOT_MOUNT_LOCATION"
+	    then
+		exit 1
+	    fi
+	fi
 
 	if [ "$CHROOT_TYPE" != "plain" ]; then
 	    if [ -n "$FSTAB" ]; then
diff --git a/bin/schroot/setup/Makefile.am b/bin/schroot/setup/Makefile.am
index 56fbe3c..16fc261 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/configure.ac b/configure.ac
index d919bf8..ddc44c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -415,6 +415,11 @@ AC_SUBST([SCHROOT_UNPACK_DIR])
 AH_TEMPLATE(SCHROOT_UNPACK_DIR, [schroot unpack directory])
 AC_DEFINE_UNQUOTED(SCHROOT_UNPACK_DIR, ["$SCHROOT_UNPACK_DIR"])
 
+SCHROOT_OVERLAY_DIR="${PACKAGE_LOCALSTATE_DIR}/lib/${PACKAGE}/overlay"
+AC_SUBST([SCHROOT_OVERLAY_DIR])
+AH_TEMPLATE(SCHROOT_OVERLAY_DIR, [schroot overlay directory])
+AC_DEFINE_UNQUOTED(SCHROOT_OVERLAY_DIR, ["$SCHROOT_OVERLAY_DIR"])
+
 dnl Set PACKAGE_SYSCONF_DIR in config.h.
 AH_TEMPLATE(PACKAGE_SYSCONF_DIR, [Package system configuration directory])
 if test "x${sysconfdir}" = 'x${prefix}/etc'; then
diff --git a/debian/control b/debian/control
index 8f12f46..1e570c4 100644
--- a/debian/control
+++ b/debian/control
@@ -88,7 +88,7 @@ Architecture: any
 Depends: ${shlibs:Depends}, schroot-common (=${source:Version})
 Conflicts: dchroot (<< 0.13)
 Enhances: sbuild
-Suggests: debootstrap, lvm2, unzip
+Suggests: debootstrap, lvm2, unzip, aufs-modules | unionfs-modules
 Description: Execute commands in a chroot environment
  schroot allows users to execute commands or interactive shells in
  different chroots.  Any number of named chroots may be created, and
diff --git a/sbuild/Makefile.am b/sbuild/Makefile.am
index 0e4fc33..400fcc0 100644
--- a/sbuild/Makefile.am
+++ b/sbuild/Makefile.am
@@ -36,6 +36,7 @@ sbuild_public_h_sources =		\
 	sbuild-chroot-block-device.h	\
 	sbuild-chroot-directory.h	\
 	sbuild-chroot-file.h		\
+	sbuild-chroot-fs-union.h	\
 	sbuild-chroot-loopback.h	\
 	sbuild-chroot-lvm-snapshot.h	\
 	sbuild-chroot-mountable.h	\
@@ -78,6 +79,7 @@ sbuild_public_cc_sources =		\
 	sbuild-chroot-block-device.cc	\
 	sbuild-chroot-directory.cc	\
 	sbuild-chroot-file.cc		\
+	sbuild-chroot-fs-union.cc	\
 	sbuild-chroot-loopback.cc	\
 	sbuild-chroot-lvm-snapshot.cc	\
 	sbuild-chroot-mountable.cc	\
diff --git a/sbuild/sbuild-chroot-fs-union.cc b/sbuild/sbuild-chroot-fs-union.cc
new file mode 100644
index 0000000..8ddd351
--- /dev/null
+++ b/sbuild/sbuild-chroot-fs-union.cc
@@ -0,0 +1,255 @@
+/* Copyright ? 2008-2009  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/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "sbuild-chroot-fs-union.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(),
+  chroot_source(),
+  fs_union_type("none"),
+  overlay_base_directory(SCHROOT_OVERLAY_DIR)
+{
+}
+
+chroot_fs_union::~chroot_fs_union ()
+{
+}
+
+bool
+chroot_fs_union::get_fs_union_configured () const
+{
+  std::string type = get_fs_union_type();
+  return (type != "none") ? true : false;
+}
+
+std::string const&
+chroot_fs_union::get_overlay_session_directory () const
+{
+  return overlay_session_directory;
+}
+
+void
+chroot_fs_union::set_overlay_session_directory 
+(std::string const& overlay_session_directory)
+{
+  if (!is_absname(overlay_session_directory))
+    throw chroot::error(overlay_session_directory, LOCATION_ABS);
+
+  this->overlay_session_directory = overlay_session_directory;
+}
+
+std::string const&
+chroot_fs_union::get_overlay_base_directory () const
+{
+  return overlay_base_directory;
+}
+
+void
+chroot_fs_union::set_overlay_base_directory
+(std::string const& overlay_base_drectory)
+{
+  if (!is_absname(overlay_base_directory))
+    throw chroot::error(overlay_base_directory, LOCATION_ABS);
+
+  this->overlay_base_directory = overlay_base_directory;
+}
+
+std::string const&
+chroot_fs_union::get_fs_union_type () const
+{
+  return fs_union_type;
+}
+
+void
+chroot_fs_union::set_fs_union_type (std::string const& fs_union_type)
+{
+  if ((fs_union_type == "aufs") || (fs_union_type == "unionfs"))
+    {
+      set_run_setup_scripts(true);
+      set_run_exec_scripts(true);
+      this->fs_union_type = fs_union_type;
+    }
+  else
+    {
+      if (fs_union_type == "none")
+	this->fs_union_type = fs_union_type;
+      else
+	throw error(fs_union_type, FS_TYPE_UNKNOWN);
+    }
+}
+
+std::string const&
+chroot_fs_union::get_fs_union_branch_config () const
+{
+  return fs_union_branch_config;
+}
+
+void
+chroot_fs_union::set_fs_union_branch_config 
+(std::string const& fs_union_branch_config)
+{
+  this->fs_union_branch_config = fs_union_branch_config;
+}
+
+void
+chroot_fs_union::setup_env (environment& env)
+{
+  chroot::setup_env(env);
+  chroot_source::setup_env(env);
+
+  env.add("CHROOT_FS_UNION_TYPE", get_fs_union_type());
+  if (get_fs_union_configured())
+    {
+      env.add("CHROOT_FS_UNION_OVERLAY_DIRECTORY", 
+        get_overlay_session_directory());
+      env.add("CHROOT_FS_UNION_BRANCH_CONFIG", 
+        get_fs_union_branch_config());
+    }
+}
+
+std::string
+chroot_fs_union::get_path() const
+{
+  if (get_fs_union_configured())
+    return get_mount_location();
+  else
+    return chroot::get_path();
+}
+
+sbuild::chroot::session_flags
+chroot_fs_union::get_session_flags () const
+{
+  std::string type = get_fs_union_type();
+  if (get_run_setup_scripts() == true) {
+    if (get_fs_union_configured()) 
+      return SESSION_CREATE | chroot_source::get_session_flags();
+    else
+      return SESSION_CREATE;
+  }
+  else
+    return SESSION_NOFLAGS;
+}
+
+void
+chroot_fs_union::get_details (format_detail& detail) const
+{
+  chroot::get_details(detail);
+  chroot_source::get_details(detail);
+
+  if (!this->overlay_session_directory.empty())
+    detail.add(_("Filesystem union overlay directory"),
+      get_overlay_session_directory());
+  if (!this->fs_union_branch_config.empty())
+    detail.add(_("Filesystem union branch config"), 
+      get_fs_union_branch_config());
+}
+
+void
+chroot_fs_union::get_keyfile (keyfile& keyfile) const
+{
+  chroot::get_keyfile(keyfile);
+  chroot_source::get_keyfile(keyfile);
+
+  keyfile::set_object_value(*this, &chroot_fs_union::get_fs_union_type,
+			    keyfile, get_name(), "fs-union-type");
+
+  keyfile::set_object_value(*this, 
+			    &chroot_fs_union::get_fs_union_branch_config,
+			    keyfile, get_name(), "fs-union-branch-config");
+
+  if (get_active())
+    keyfile::set_object_value(*this, 
+			      &chroot_fs_union::get_overlay_session_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-session-directory");
+  else
+    keyfile::set_object_value(*this, 
+			      &chroot_fs_union::get_overlay_base_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-base-directory");
+}
+
+void
+chroot_fs_union::set_keyfile (keyfile const& keyfile,
+			      string_list&   used_keys)
+{
+  chroot::set_keyfile(keyfile, used_keys);
+  chroot_source::set_keyfile(keyfile, used_keys);
+
+  keyfile::get_object_value(*this, &chroot_fs_union::set_fs_union_type,
+			    keyfile, get_name(), "fs-union-type",
+			    keyfile::PRIORITY_OPTIONAL);
+  used_keys.push_back("fs-union-type");
+
+  keyfile::get_object_value(*this, 
+			    &chroot_fs_union::set_fs_union_branch_config,
+			    keyfile, get_name(), "fs-union-branch-config",
+			    keyfile::PRIORITY_OPTIONAL);
+  used_keys.push_back("fs-union-branch-config");
+
+  if (get_active())
+    keyfile::get_object_value(*this, 
+			      &chroot_fs_union::set_overlay_session_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-session-directory",
+			      (get_fs_union_configured() ?
+			       keyfile::PRIORITY_REQUIRED :
+			       keyfile::PRIORITY_OPTIONAL));
+  else
+    keyfile::get_object_value(*this, 
+			      &chroot_fs_union::set_overlay_base_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-base-directory",
+			      keyfile::PRIORITY_OPTIONAL);
+
+  used_keys.push_back("fs-union-overlay-session-directory");
+  used_keys.push_back("fs-union-overlay-base-directory");
+}
+
diff --git a/sbuild/sbuild-chroot-fs-union.h b/sbuild/sbuild-chroot-fs-union.h
new file mode 100644
index 0000000..3e4bb4c
--- /dev/null
+++ b/sbuild/sbuild-chroot-fs-union.h
@@ -0,0 +1,183 @@
+/* Copyright ? 2008-2009  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/>.
+ *
+ *********************************************************************/
+
+#ifndef SBUILD_CHROOT_FS_UNION_H
+#define SBUILD_CHROOT_FS_UNION_H
+
+#include <sbuild/sbuild-chroot-source.h>
+
+namespace sbuild
+{
+  /**
+   * A chroot may offer session support using a union filesystem like
+   * aufs or unionfs.
+   *
+   * This interface can be implemented by any chroot wishing to provide such
+   * functionality.  It already includes sbuild::chroot_source support.
+   *
+   * At a minimum, the inheriting class has to implement the
+   * chroot_source::clone_source() function, depending on the
+   * setting of get_fs_union_configured().
+   */
+  class chroot_fs_union : public chroot_source
+  {
+  protected:
+    /// The constructor.
+    chroot_fs_union ();
+
+    friend class chroot;
+
+  public:
+    /// The destructor.
+    virtual ~chroot_fs_union ();
+
+    /// Error codes.
+    enum error_code
+      {
+	FS_TYPE_UNKNOWN      ///< Unknown union fs type
+      };
+
+    /// Exception type.
+    typedef custom_error<error_code> error;
+
+    /**
+     * Get fs union configured state.
+     *
+     * @returns if fs union is configured
+     */
+    bool
+    get_fs_union_configured () const;
+
+    /**
+     * Get the union filesystem type.
+     *
+     * @see set_fs_union_type
+     * @returns the union filesytem type.
+     */
+    virtual std::string const&
+    get_fs_union_type () const;
+
+    /**
+     * Get the union filesystem branch configuration.
+     *
+     * @see set_fs_union_branch_config
+     * @returns the union filesystem branch configuration.
+     */
+    virtual std::string const&
+    get_fs_union_branch_config () const;
+
+    /**
+     * Get the overlay base directory.
+     *
+     * @see set_overlay_base_directory
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_overlay_base_directory () const;
+
+    /**
+     * Get the writeable overlay directory of the session.
+     *
+     * @see set_overlay_session_directory
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_overlay_session_directory () const;
+
+    /**
+     * Set the union filesystem type.
+     *
+     * Currently supported values are aufs, unionfs and none.
+     *
+     * @param fs_union_type the filesystem type.
+     **/
+    virtual void
+    set_fs_union_type (std::string const& fs_union_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 string has to be constructed as 
+     * expected by the union filesystem type and is directly used as the mount
+     * '-o' option string.
+     *
+     * @param fs_union_branch_config a @fs_type specific branch description
+     **/
+    virtual void
+    set_fs_union_branch_config (std::string const& fs_union_branch_config);
+
+    /**
+     * Allows one to set the directory, where session overlay directories will
+     * be created.
+     *
+     * @param the absolute path of the overlay_base_directory.
+     **/
+    virtual void
+    set_overlay_base_directory 
+    (std::string const& overlay_base_directory);
+
+    /**
+     * Allows schrooot to set the session dependant overlay directory.
+     *
+     * @param the absolute path of the overlay_session_directory.
+     **/
+    virtual void
+    set_overlay_session_directory 
+    (std::string const& overlay_session_directory);
+
+    virtual std::string
+    get_path () const;
+
+    virtual void
+    setup_env (environment& env);
+
+    virtual session_flags
+    get_session_flags () const;
+
+  protected:
+    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_union_type;
+    /// Complex branch configuration to pass directly as mount option
+    std::string fs_union_branch_config;
+    /// Directory used as the overlay base directory
+    std::string overlay_base_directory;
+    /// Writeable directory used as the overlay write branch
+    std::string overlay_session_directory;
+  };
+}
+
+#endif /* SBUILD_CHROOT_FS_UNION_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/sbuild/sbuild-session.cc b/sbuild/sbuild-session.cc
index a497706..ab2fb93 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"
@@ -663,6 +664,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_directory();
+              dir += "/" + this->session_id;
+	      overlay->set_overlay_session_directory(dir);
+	    }
+
 	  try
 	    {
 	      /* Run setup-start chroot setup scripts. */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
Url : http://lists.alioth.debian.org/pipermail/buildd-tools-devel/attachments/20090401/32bfad31/attachment.pgp 


More information about the Buildd-tools-devel mailing list