Add a container config option to mount and populate /dev in a container.

We might want to add options to specify a max size for /dev other than
the default 100k, and to specify other devices to create.  And maybe
someone can think of a better name than autodev.

Changelog: Don't error out if we couldn't mknod a /dev/ttyN.
Changelog: Describe the option in lxc.conf manpage.

Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
---
 doc/lxc.conf.sgml.in |   25 ++++++++++++++++
 src/lxc/conf.c       |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/conf.h       |    1 +
 src/lxc/confile.c    |   12 ++++++++
 4 files changed, 115 insertions(+)

diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
index 6c3d7b2..eed07fc 100644
--- a/doc/lxc.conf.sgml.in
+++ b/doc/lxc.conf.sgml.in
@@ -502,6 +502,31 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
02111-1307 USA
     </refsect2>
 
     <refsect2>
+      <title>/dev directory</title>
+      <para>
+       By default, lxc does nothing with the container's
+       <filename>/dev</filename>.  This allows the container's
+       <filename>/dev</filename> to be set up as needed in the container
+       rootfs.  If lxc.autodev is to 1, then after mounting the container's
+       rootfs LXC will mount a fresh tmpfs under <filename>/dev</filename>
+       (limited to 100k) and fill in a minimal set of initial devices.
+      </para>
+      <variablelist>
+       <varlistentry>
+         <term>
+           <option>lxc.autodev</option>
+         </term>
+         <listitem>
+           <para>
+             Set this to 1 to have LXC mount and populate a minimal
+             <filename>/dev</filename> when starting the container.
+           </para>
+         </listitem>
+       </varlistentry>
+      </variablelist>
+    </refsect2>
+
+    <refsect2>
       <title>Mount points</title>
       <para>
        The mount points section specifies the different places to be
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index fe574ac..f1c41f1 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -653,6 +653,15 @@ static int setup_tty(const struct lxc_rootfs *rootfs,
                                return -1;
                        }
                } else {
+                       /* If we populated /dev, then we need to create 
/dev/ttyN */
+                       if (access(path, F_OK)) {
+                               ret = creat(path, 0660);
+                               if (ret==-1) {
+                                       SYSERROR("error creating %s\n", path);
+                                       /* this isn't fatal, continue */
+                               } else
+                                       close(ret);
+                       }
                        if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
                                WARN("failed to mount '%s'->'%s'",
                                                pty_info->name, path);
@@ -860,6 +869,67 @@ static int setup_rootfs_pivot_root(const char *rootfs, 
const char *pivotdir)
        return 0;
 }
 
+struct lxc_devs {
+       char *name;
+       mode_t mode;
+       int maj;
+       int min;
+};
+
+struct lxc_devs lxc_devs[] = {
+       { "null",       S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3     },
+       { "zero",       S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5     },
+       { "full",       S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7     },
+       { "urandom",    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9     },
+       { "random",     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8     },
+       { "tty",        S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0     },
+       { "console",    S_IFCHR | S_IRUSR | S_IWUSR,           5, 1     },
+};
+
+/*
+ * Do we want to add options for max size of /dev and a file to
+ * specify which devices to create?
+ */
+static int setup_autodev(char *root)
+{
+       int ret;
+       struct lxc_devs *d;
+       char path[MAXPATHLEN];
+       int i;
+
+       INFO("Creating and populating /dev under %s\n", root);
+       ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
+       if (ret < 0 || ret > MAXPATHLEN)
+               return -1;
+       ret = mount("none", path, "tmpfs", 0, "size=100000");
+       if (ret) {
+               SYSERROR("Failed to mount /dev at %s\n", root);
+               return -1;
+       }
+       for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
+               d = &lxc_devs[i];
+               ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name);
+               if (ret < 0 || ret >= MAXPATHLEN)
+                       return -1;
+               ret = mknod(path, d->mode, makedev(d->maj, d->min));
+               if (ret) {
+                       SYSERROR("Error creating %s\n", d->name);
+                       return -1;
+               }
+       }
+       ret = snprintf(path, MAXPATHLEN, "%s/dev/pts", root);
+       if (ret < 0 || ret >= MAXPATHLEN)
+               return -1;
+       ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+       if (ret) {
+               SYSERROR("Failed to create /dev/pts in container");
+               return -1;
+       }
+
+       INFO("Populated /dev under %s\n", root);
+       return 0;
+}
+
 static int setup_rootfs(const struct lxc_rootfs *rootfs)
 {
        if (!rootfs->path)
@@ -2265,6 +2335,13 @@ int lxc_setup(const char *name, struct lxc_conf 
*lxc_conf)
                return -1;
        }
 
+       if (lxc_conf->autodev) {
+               if (setup_autodev(lxc_conf->rootfs.mount)) {
+                       ERROR("failed to set up /dev in the container");
+                       return -1;
+               }
+       }
+
        if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
                ERROR("failed to setup the mounts for '%s'", name);
                return -1;
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index dccc176..76bf19d 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -237,6 +237,7 @@ struct lxc_conf {
 #endif
        char *seccomp;  // filename with the seccomp rules
        int maincmd_fd;
+       int autodev;  // if 1, mount and fill a /dev at start
 };
 
 int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf);
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index cf1c891..3d9f36e 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -79,6 +79,7 @@ static int config_console(const char *, char *, struct 
lxc_conf *);
 static int config_seccomp(const char *, char *, struct lxc_conf *);
 static int config_includefile(const char *, char *, struct lxc_conf *);
 static int config_network_nic(const char *, char *, struct lxc_conf *);
+static int config_autodev(const char *, char *, struct lxc_conf *);
 
 static struct lxc_config_t config[] = {
 
@@ -121,6 +122,7 @@ static struct lxc_config_t config[] = {
        { "lxc.console",              config_console              },
        { "lxc.seccomp",              config_seccomp              },
        { "lxc.include",              config_includefile          },
+       { "lxc.autodev",              config_autodev              },
 };
 
 static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
@@ -881,6 +883,16 @@ static int config_aa_profile(const char *key, char *value, 
struct lxc_conf *lxc_
 }
 #endif
 
+static int config_autodev(const char *key, char *value,
+                         struct lxc_conf *lxc_conf)
+{
+       int v = atoi(value);
+
+       lxc_conf->autodev = v;
+
+       return 0;
+}
+
 static int config_cgroup(const char *key, char *value, struct lxc_conf 
*lxc_conf)
 {
        char *token = "lxc.cgroup.";
-- 
1.7.9.5


------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to