Quoting Michael H. Warfield (m...@wittsend.com):
> On Sat, 2012-10-27 at 13:51 -0400, Michael H. Warfield wrote:
> > On Sat, 2012-10-27 at 13:40 -0400, Michael H. Warfield wrote:
> > > /me erasing everything at this point and taking off the systemd crew,
> > > since this will have no relevance to them...
> > > 
> > > Testing the hook feature out using git rev (finally got it built)...
> > > 
> > > I added this line to my config...
> > > 
> > > lxc.mount.entry=tmpfs /srv/lxc/private/Plover/dev.tmp tmpfs defaults 0 0
> > > lxc.hook.mount = /var/lib/lxc/Plover/mount
> > > 
> > > In /var/lib/lxc/Plover/mount I have this:
> > > 
> > > -- 
> > > rsync -avAH /srv/lxc/private/Plover/dev.template/. 
> > > /srv/lxc/private/Plover/dev.tmp/
> > > -- 
> > 
> > > (This is just testing out the concepts.
> > 
> > > If I understand this correctly, lxc.hook.pre-mount runs BEFORE the
> > > mounting takes place and lxc.hook.mount takes place after the mount.
> > 
> > > Problem is, the result of that rsync is not showing up in the mounted
> > > tmpfs file system but is showing up in the underlying parent file system
> > > as if it were run pre-mount.  Something not right here...
> 
> > I changed it to "lxc.hook.start = /srv/lxc/mount" (where I put the
> > script in the container) which then works but that then requires the
> > template and the command to be in the container.  Suboptimal to say the
> > least.  But it gives me a way to test this tmpfs thing out.
> 
> > I also noticed that the .start hook runs, it appears, after caps are
> > dropped and I see a lot of bitching about mknod on certain devices.  I
> > had to thrown an exit 0 into that script so it would continue in spite
> > of the errors but, now, I can refine my template based on what it could
> > create.
> 
> Crap.  I've got a catch-22 here...  This is going to take some work.

Hey,

I've got a rather minimal patch (appended below) to add the support for
mounting and populating a minimal /dev working.  (A few hours were wasted
due to my not knowing that upstart was going to issue mounted-dev even though
/dev was mounted before upstart started - and the mounted-dev hook deletes
and recreates all consoles.  GAH)

> Yes, we can create the /dev directory with tmpfs from a template.
> Problem is that /dev/pts does not exist at the time we need to mount the
> devpts on /dev/pts for the pty's so that hurls chunks and dies.  We
> can't create the /dev/ directory contents prior to mounting in the
> pre-mount hook because we won't have tmpfs in place at the time.  We
> have to get tmpfs mounted on /dev and then create /dev/pts and then
> mount the ptys in there.  There has to be a mkdir in between those two
> mount actions.  Simplest solution would seem to be to add some logic to
> the mount logic that says "test if directory exists and, if not, create
> it."  I'm not sure of the consequences of that, though.
> 
> I don't see a way to make this happen with hooks.  It's almost like we
> need and on-mount per mount hook.

Should be moot given my patch, which I intend to push this week, but why
couldn't a lxc.hook.mount do the whole thing, mount /dev and and populate
it?  I wasn't thinking a lxc.hook.start, for the reasons you encountered,
but I assume you tried lxc.hook.mount and it failed?

Patch below:

Index: lxc-qp/src/lxc/conf.c
===================================================================
--- lxc-qp.orig/src/lxc/conf.c  2012-10-27 17:24:50.768383000 -0500
+++ lxc-qp/src/lxc/conf.c       2012-10-28 05:44:07.871228322 -0500
@@ -619,7 +619,7 @@
                        }
 
                        if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) 
{
-                               WARN("failed to mount '%s'->'%s'",
+                               SYSERROR("failed to mount '%s'->'%s'",
                                     pty_info->name, path);
                                continue;
                        }
@@ -636,7 +636,7 @@
                        }
                } else {
                        if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
-                               WARN("failed to mount '%s'->'%s'",
+                               SYSERROR("failed to mount '%s'->'%s'",
                                                pty_info->name, path);
                                continue;
                        }
@@ -842,6 +842,67 @@
        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)
@@ -2208,6 +2269,13 @@
                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;
Index: lxc-qp/src/lxc/conf.h
===================================================================
--- lxc-qp.orig/src/lxc/conf.h  2012-10-27 17:24:50.768383000 -0500
+++ lxc-qp/src/lxc/conf.h       2012-10-27 17:24:50.768383000 -0500
@@ -227,6 +227,7 @@
        struct lxc_list hooks[NUM_LXC_HOOKS];
        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);
Index: lxc-qp/src/lxc/confile.c
===================================================================
--- lxc-qp.orig/src/lxc/confile.c       2012-10-27 17:24:50.768383000 -0500
+++ lxc-qp/src/lxc/confile.c    2012-10-27 17:24:50.768383000 -0500
@@ -77,6 +77,7 @@
 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 *);
 
 typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
 
@@ -118,6 +119,7 @@
        { "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);
@@ -853,6 +855,16 @@
 
        return 0;
 }
+
+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_aa_profile(const char *key, char *value,
                          struct lxc_conf *lxc_conf)

------------------------------------------------------------------------------
WINDOWS 8 is here. 
Millions of people.  Your app in 30 days.
Visit The Windows 8 Center at Sourceforge for all your go to resources.
http://windows8center.sourceforge.net/
join-generation-app-and-make-money-coding-fast/
_______________________________________________
Lxc-users mailing list
Lxc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-users

Reply via email to