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-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel