And now for round two of this patch... On Wed, 2013-01-09 at 15:26 -0600, Serge Hallyn wrote: > Quoting Michael H. Warfield (m...@wittsend.com): > > Ok, all! > > > > Here's the patch I promised Serge in the "[PATCH] Support MS_SHARED /" > > thread to address the mayhem that calling MAKEDEV was causing. > > > > This is a straw-man patch. This is the first patch I've submitted to > > this project but I plagerized like hell, so I hope I got the coding > > style matched. Look it over and suggest changes. It adds some features > > and changes some features. If you don't like what I did, no problem. I > > probably did somethings that some people may consider "suboptimal". My > > feelings won't be hurt if you say so. > > > > This patch does several things... > > > > 1) Removes run_makedev() and the call to it from conf.c per discussion. > > > > 2) Adds an lxc.hook.autodev hook. > > > > Note: This hook is very close (one routine level abstracted) from where > > the run_makedev was called. Anyone really rrreeeaaalllyyy needing > > MAKEDEV can add it in with a small shim script to do whatever they want > > under whatever distro they're using, so no functionality is lost there. > > > > 3) Added a number of environment variables for all the hook scripts to > > reference to assist in execution. Things like LXC_ROOTFS_MOUNT could be > > very useful but others were added as well. Room for more if anyone has > > an itch. All in one spot in lxc_start.c. > > > > 4) clearenv and putenv( "container=lxc" ) calls were moved to just after > > the "start" hook in the container just prior to actually firing up the > > container so we could use environment variables prior to that and have > > them flushed them before firing up init. Nice side effect is that you > > can define environment variables and then call lxc-start and have them > > show up in those hooks scripts. > > > > 5) I actually DID update the man page for lxc.conf! I guess I lied when > > I said I wouldn't get that done. > > > > Now for the ugly side... > > > > I don't think where I stuck all those "setenv" calls is the best place > > in lxc_start.c but it's where all the variables I needed where set in
> Right, it should be done in start.c, since lxc-execute won't hit them > if they're in lxc-start.c > Perhaps you can get the logfile using readlink on > /proc/self/fd/$(lxc_conf->lxc_log_fd) ? The rcfile could be > added to struct conf for you to use. The lxc_conf.logfile and lxc_conf.loglevel in the lxc_conf structure do not seem to be related to the -l log priority or the -o log output. I've left them in for the time being but removed them from the documentation since the lxc.logfile and lxc.logpriority options in the config file appear to be undocumented. I added the rcfile to the lxc_conf structure as suggested and moved the setenv bundle from lxc-start.c over to start.c just prior to calling run_lxc_hooks for the pre-start hook. I also spotted an error on my part that I wasn't checking for NULLs in a couple of those setenv options that could have been NULL. Added checks for that. Glad I caught it first. I know better. > Other than that, patch looks great, thanks. Round 2 patch below my signature block. > -serge Regards, Mike -- Michael H. Warfield (AI4NB) | (770) 985-6132 | m...@wittsend.com /\/\|=mhw=|\/\/ | (678) 463-0932 | http://www.wittsend.com/mhw/ NIC whois: MHW9 | An optimist believes we live in the best of all PGP Key: 0x674627FF | possible worlds. A pessimist is sure of it! -- diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in index 96dea89..1298143 100644 --- a/doc/lxc.conf.sgml.in +++ b/doc/lxc.conf.sgml.in @@ -510,6 +510,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA rootfs. If lxc.autodev is set 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. + This is generally required when starting a container containing + a "systemd" based "init" but may be optional at other times. Addional + devices in the containers /dev directory may be created through the + use of the <option>lxc.hook.autodev</option> hook. </para> <variablelist> <varlistentry> @@ -737,6 +741,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA <variablelist> <varlistentry> <term> + <option>lxc.hook.autodev</option> + </term> + <listitem> + <para> + A hook to be run in the container's namespace after + mounting has been done and after any mount hooks have + run, but before the pivot_root, if + <option>lxc.autodev</option> == 1. + The purpose of this hook is to assist in populating the + /dev directory of the container when using the autodev + option for systemd based containers. The container's /dev + directory is relative to the + ${<option>LXC_ROOTFS_MOUNT</option>} environment + variable available when the hook is run. + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term> <option>lxc.hook.start</option> </term> <listitem> @@ -763,6 +788,103 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA </variablelist> </refsect2> + <refsect2> + <title>Startup hooks Environment Variables</title> + <para> + A number of environment variables are made available to the startup + hooks to provide configuration information and assist in the + functioning of the hooks. Not all variables are valid in all + contexts. In particular, all paths are relative to the host system + and, as such, not valid during the <option>lxc.hook.start</option> hook. + </para> + <variablelist> + <varlistentry> + <term> + <option>LXC_NAME</option> + </term> + <listitem> + <para> + The LXC name of the container. Useful for logging messages + in commmon log environments. [<option>-n</option>] + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term> + <option>LXC_CONFIG_FILE</option> + </term> + <listitem> + <para> + Host relative path to the container configuration file. This + gives the container to reference the original, top level, + configuration file for the container in order to locate any + addotional configuration information not otherwise made + available. [<option>-f</option>] + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term> + <option>LXC_CONSOLE</option> + </term> + <listitem> + <para> + The path to the console output of the container if not NULL. + [<option>-c</option>] [<option>lxc.console</option>] + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term> + <option>LXC_CONSOLE_LOGPATH</option> + </term> + <listitem> + <para> + The path to the console log output of the container if not NULL. + [<option>-L</option>] + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term> + <option>LXC_ROOTFS_MOUNT</option> + </term> + <listitem> + <para> + The mount location to which the container is initially bound. + This will be the host relative path to the container rootfs + for the container instance being started and is where changes + should be made for that instance. + [<option>lxc.rootfs.mount</option>] + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term> + <option>LXC_ROOTFS_PATH</option> + </term> + <listitem> + <para> + The host relative path to the container root which has been + mounted to the rootfs.mount location. + [<option>lxc.rootfs</option>] + </para> + </listitem> + </varlistentry> + </variablelist> + + </refsect2> + </refsect1> <refsect1> diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 1c02850..699011a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -116,7 +116,7 @@ lxc_log_define(lxc_conf, lxc); #endif char *lxchook_names[NUM_LXC_HOOKS] = { - "pre-start", "pre-mount", "mount", "start", "post-stop" }; + "pre-start", "pre-mount", "mount", "autodev", "start", "post-stop" }; extern int pivot_root(const char * new_root, const char * put_old); @@ -913,33 +913,6 @@ static int mount_autodev(char *root) return 0; } -/* - * Try to run MAKEDEV console in the container. If something fails, - * continue anyway as it should not be detrimental to the container. - * This makes sure that things like /dev/vcs* exist. - * (Pass devpath in to reduce stack usage) - */ -static void run_makedev(char *devpath) -{ - int curd; - int ret; - - curd = open(".", O_RDONLY); - if (curd < 0) - return; - ret = chdir(devpath); - if (ret) { - close(curd); - return; - } - if (run_buffer("/sbin/MAKEDEV console")) - INFO("Error running MAKEDEV console in %s", devpath); - ret = fchdir(curd); - if (ret) - INFO("Error returning to original directory: expect breakage"); - close(curd); -} - struct lxc_devs { char *name; mode_t mode; @@ -971,8 +944,7 @@ static int setup_autodev(char *root) if (ret < 0 || ret >= MAXPATHLEN) { ERROR("Error calculating container /dev location"); return -1; - } else - run_makedev(path); + } INFO("Populating /dev under %s\n", root); cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); @@ -2553,6 +2525,10 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf) } if (lxc_conf->autodev) { + if (run_lxc_hooks(name, "autodev", lxc_conf)) { + ERROR("failed to run autodev hooks for container '%s'.", name); + return -1; + } if (setup_autodev(lxc_conf->rootfs.mount)) { ERROR("failed to populate /dev in the container"); return -1; @@ -2628,6 +2604,8 @@ int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf) which = LXCHOOK_PREMOUNT; else if (strcmp(hook, "mount") == 0) which = LXCHOOK_MOUNT; + else if (strcmp(hook, "autodev") == 0) + which = LXCHOOK_AUTODEV; else if (strcmp(hook, "start") == 0) which = LXCHOOK_START; else if (strcmp(hook, "post-stop") == 0) diff --git a/src/lxc/conf.h b/src/lxc/conf.h index b576893..45161e1 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -213,8 +213,8 @@ struct lxc_rootfs { #endif */ enum lxchooks { - LXCHOOK_PRESTART, LXCHOOK_PREMOUNT, LXCHOOK_MOUNT, LXCHOOK_START, - LXCHOOK_POSTSTOP, NUM_LXC_HOOKS}; + LXCHOOK_PRESTART, LXCHOOK_PREMOUNT, LXCHOOK_MOUNT, LXCHOOK_AUTODEV, + LXCHOOK_START, LXCHOOK_POSTSTOP, NUM_LXC_HOOKS}; extern char *lxchook_names[NUM_LXC_HOOKS]; struct saved_nic { @@ -257,6 +257,7 @@ struct lxc_conf { #endif int maincmd_fd; int autodev; // if 1, mount and fill a /dev at start + char *rcfile; // Copy of the top level rcfile we read }; 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 1d87227..8cef8be 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -104,6 +104,7 @@ static struct lxc_config_t config[] = { { "lxc.hook.pre-start", config_hook }, { "lxc.hook.pre-mount", config_hook }, { "lxc.hook.mount", config_hook }, + { "lxc.hook.autodev", config_hook }, { "lxc.hook.start", config_hook }, { "lxc.hook.post-stop", config_hook }, { "lxc.network.type", config_network_type }, @@ -821,6 +822,8 @@ static int config_hook(const char *key, const char *value, return add_hook(lxc_conf, LXCHOOK_PRESTART, copy); else if (strcmp(key, "lxc.hook.pre-mount") == 0) return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy); + else if (strcmp(key, "lxc.hook.autodev") == 0) + return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy); else if (strcmp(key, "lxc.hook.mount") == 0) return add_hook(lxc_conf, LXCHOOK_MOUNT, copy); else if (strcmp(key, "lxc.hook.start") == 0) @@ -1265,6 +1268,10 @@ int lxc_config_readline(char *buffer, struct lxc_conf *conf) int lxc_config_read(const char *file, struct lxc_conf *conf) { + /* Catch only the top level config file name in the structure */ + if( ! conf->rcfile ) { + conf->rcfile = strdup( file ); + } return lxc_file_for_each_line(file, parse_line, conf); } diff --git a/src/lxc/lxc_start.c b/src/lxc/lxc_start.c index 184fb04..a97dcca 100644 --- a/src/lxc/lxc_start.c +++ b/src/lxc/lxc_start.c @@ -168,15 +168,6 @@ int main(int argc, char *argv[]) my_args.progname, my_args.quiet)) return err; - if (clearenv()) { - SYSERROR("failed to clear environment"); - /* don't error out though */ - } - if (putenv("container=lxc")) { - SYSERROR("failed to set environment variable"); - return err; - } - /* rcfile is specified in the cli option */ if (my_args.rcfile) rcfile = (char *)my_args.rcfile; diff --git a/src/lxc/start.c b/src/lxc/start.c index 82a74d8..f3a4bd3 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -391,6 +391,40 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf) goto out_free_name; } + /* Start of environment variable setup for hooks */ + if (setenv("LXC_NAME", name, 1)) { + SYSERROR("failed to set environment variable for container name"); + } + if (setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) { + SYSERROR("failed to set environment variable for config path"); + } + if (setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) { + SYSERROR("failed to set environment variable for rootfs mount"); + } + if (setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) { + SYSERROR("failed to set environment variable for rootfs mount"); + } + if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) { + SYSERROR("failed to set environment variable for console path"); + } + if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) { + SYSERROR("failed to set environment variable for console log"); + } + /* Not quite sure right now what these next two actually do but + * leaving them in, just not documenting them, for the moment just + * in case they are a work in progress somewhere else. */ + if (conf->logfile && setenv("LXC_LOGPATH", conf->logfile, 1)) { + SYSERROR("failed to set environment variable for console log"); + } + { + char loglevel[16]; + snprintf( loglevel, 14, "%d", conf->loglevel ); + if (setenv("LXC_LOGLEVEL", loglevel, 1)) { + SYSERROR("failed to set environment variable for log level mount"); + } + } + /* End of environment variable setup for hooks */ + if (run_lxc_hooks(name, "pre-start", conf)) { ERROR("failed to run pre-start hooks for container '%s'.", name); goto out_aborting; @@ -575,6 +609,21 @@ static int do_start(void *data) goto out_warn_father; } + /* The clearenv() and putenv() calls have been moved here + * to allow us to use enviroment variables passed to the various + * hooks, such as the start hook above. Not all of the + * variables like CONFIG_PATH or ROOTFS are valid in this + * context but others are. */ + if (clearenv()) { + SYSERROR("failed to clear environment"); + /* don't error out though */ + } + + if (putenv("container=lxc")) { + SYSERROR("failed to set environment variable"); + return -1; + } + close(handler->sigfd); /* after this call, we are in error because this
signature.asc
Description: This is a digitally signed message part
------------------------------------------------------------------------------ Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS, MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft MVPs and experts. ON SALE this month only -- learn more at: http://p.sf.net/sfu/learnmore_122712
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel