diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
index 96dea89f3..1298143da 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 /dev
(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 hook.
@@ -734,6 +738,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+
+
+
+
+ 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
+ == 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
+ ${} environment
+ variable available when the hook is run.
+
+
+
+
@@ -763,6 +788,103 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Startup hooks Environment Variables
+
+ 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 hook.
+
+
+
+
+
+
+
+
+ The LXC name of the container. Useful for logging messages
+ in commmon log environments. []
+
+
+
+
+
+
+
+
+
+
+
+ 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. []
+
+
+
+
+
+
+
+
+
+
+
+ The path to the console output of the container if not NULL.
+ [] []
+
+
+
+
+
+
+
+
+
+
+
+ The path to the console log output of the container if not NULL.
+ []
+
+
+
+
+
+
+
+
+
+
+
+ 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.
+ []
+
+
+
+
+
+
+
+
+
+
+
+ The host relative path to the container root which has been
+ mounted to the rootfs.mount location.
+ []
+
+
+
+
+
+
+
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index ea0fcf6fc..d448d59f5 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -172,7 +172,7 @@ return -1;
#endif
char *lxchook_names[NUM_LXC_HOOKS] = {
- "pre-start", "pre-mount", "mount", "start", "post-stop" };
+ "pre-start", "pre-mount", "mount", "autodev", "start", "post-stop" };
typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
@@ -971,33 +971,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;
@@ -1029,8 +1002,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);
@@ -2612,6 +2584,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;
@@ -2687,6 +2663,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 83de84aab..e22685966 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -214,8 +214,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 {
@@ -256,6 +256,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 7372a347b..034136ef5 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -107,6 +107,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 },
@@ -833,6 +834,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)
@@ -1262,6 +1265,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 184fb04c6..a97dccaa8 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 a539703d5..e78f685df 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -401,6 +401,27 @@ 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");
+ }
+ /* 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;
@@ -587,6 +608,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