[lxc-devel] [PATCH] Issue #278: lxc-start-ephemeral: add --cdir option for cow-mounts

overlay fs overlayfs at gmail.com
Wed Nov 26 17:11:43 UTC 2014


This is a copy of patch version 3 for issue #278 on the issue-tracker:

-Allow multiple bind-mounts (--bdir) and multiple cow-mounts (--cdir).

-Further fixes to permissions throughout lxc-start-ephemeral
(annotated in the code).

-Reduce start-up time by ~5 seconds; only wait for a network ip
address if really need it, ie if we are running a command.


Signed-off by: Oleg Freedholm <overlayfs at gmail.com>

--- /usr/bin/lxc-start-ephemeral    2014-11-21 17:48:49.000000000 +1100
+++ lxc-start-ephemeral 2014-11-27 00:30:42.095429007 +1100
@@ -84,9 +84,14 @@
 parser.add_argument("--name", "-n", type=str,
                     help=_("name of the target container"))

-parser.add_argument("--bdir", "-b", type=str,
+# edit: insert action="append"
+parser.add_argument("--bdir", "-b", type=str, action="append", default=[],
                     help=_("directory to bind mount into container"))

+# edit: add cdir
+parser.add_argument("--cdir", "-c", type=str, action="append", default=[],
+                    help=_("directory to cow mount into container"))
+
 parser.add_argument("--user", "-u", type=str,
                     help=_("the user to run the command as"))

@@ -156,6 +161,14 @@
 else:
     dest_path = tempfile.mkdtemp(prefix="%s-" % args.orig, dir=lxc_path)
 os.mkdir(os.path.join(dest_path, "rootfs"))
+# edit: set the permissions for an ephemeral container to the default
permissions for a non-ephemeral container, o770.
+#     : if the permissions are not set here, then they vary greatly,
depending upon the arguments.
+#     : sometimes permissions are too tight, so that the
(unprivileged) host user cannot list the container's host directory.
+#     : in this case, lxc-start-ephemeral fails to cleanup the
container upon termination.
+#     :           eg lxc-start-ephemeral -o trusty
+#     : othertimes permissions are too loose, so that every host user
can list the container's host directory.
+#     :           eg lxc-start-ephemeral -o trusty -n trusty_ephemeral
+os.chmod(dest_path, 0o770)

 # Setup the new container's configuration
 dest = lxc.Container(os.path.basename(dest_path), args.lxcpath)
@@ -206,6 +219,16 @@
                 # Setup an overlay for anything remaining
                 overlay_dirs += [(fields[0], dest_mount)]

+# edit: Setup an overlay for each cow mount
+for entry in args.cdir:
+    if not os.path.exists(entry):
+        print(_("Path '%s' doesn't exist, won't be cow-mounted.") %
+              entry)
+    else:
+        src_path = os.path.abspath(entry)
+        dst_path = "%s/rootfs/%s" % (dest_path, src_path)
+        overlay_dirs += [(src_path, dst_path)]
+
 # Generate pre-mount script
 with open(os.path.join(dest_path, "pre-mount"), "w+") as fd:
     os.fchmod(fd.fileno(), 0o755)
@@ -223,6 +246,17 @@
         if args.storage_type == "tmpfs":
             fd.write("mount -n -t tmpfs -o mode=0755 none %s\n" % (target))

+        # edit: attempt to fix permissions (setfacl) and optionally
ownership (chown)
+        #    - this is complicated, because we are inside an id_map,
and this confuses tools such as setfacl & chown.
+        #    - fixing permissions is essential.  Without the fix, an
unprivileged user in the container
+        #      cannot write to the top level of '--cdir' (though they
can write to subdirectories of --cdir).
+        #      setfacl seems to solve the problem.
+        #    - fixing ownership is optional, since acl permissions
trump ownership.
+        #      chown behaves strangely under the id_map, so it has
been commented out.
+        ###fd.write("chown --no-dereference --reference=%s %s %s\n" %
(entry[0], target, entry[1]))
+        fd.write("getfacl -a %s | setfacl --set-file=- %s\n" %
(entry[0], target))
+        fd.write("getfacl -a %s | setfacl --set-file=- %s\n" %
(entry[0], entry[1]))
+
         if args.union_type == "overlayfs":
             fd.write("mount -n -t overlayfs"
                      " -oupperdir=%s,lowerdir=%s none %s\n" % (
@@ -242,13 +276,13 @@
                          entry[1]))
         count += 1

-    if args.bdir:
-        if not os.path.exists(args.bdir):
+    for entry in args.bdir:
+        if not os.path.exists(entry):
             print(_("Path '%s' doesn't exist, won't be bind-mounted.") %
-                  args.bdir)
+                  entry)
         else:
-            src_path = os.path.abspath(args.bdir)
-            dst_path = "%s/rootfs/%s" % (dest_path, os.path.abspath(args.bdir))
+            src_path = os.path.abspath(entry)
+            dst_path = "%s/rootfs/%s" % (dest_path, os.path.abspath(entry))
             fd.write("mkdir -p %s\nmount -n --bind %s %s\n" % (
                      dst_path, src_path, dst_path))

@@ -295,7 +329,11 @@
     sys.exit(0)

 # Try to get the IP addresses
-ips = dest.get_ips(timeout=10)
+# edit: Only wait for the IP address if we really need it, ie if we
are executing a command.
+#     : This takes ~5 seconds, perhaps because it takes that long to
launch the network in the container.
+ips = []         # edit: ... ensure ips is defined
+if args.command: # edit: added if statement
+    ips = dest.get_ips(timeout=10)

 # Deal with the case where we just print info about the container
 if args.daemon:


More information about the lxc-devel mailing list