From ee1e7aa0eb82fe35a871166a8fa1834c01293ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Sat, 21 Sep 2013 21:30:06 -0400 Subject: [PATCH] autostart: Define lxc.start.* and lxc.group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First patch in the set of changes required for container autostart. This commit adds the new configuration keys and parsers that will then be used by lxc-start and lxc-stop. Signed-off-by: Stéphane Graber Acked-by: Serge E. Hallyn Acked-by: Dwight Engen --- doc/lxc.conf.sgml.in | 59 ++++++++++++++++++++++++++- src/lxc/conf.c | 14 +++++++ src/lxc/conf.h | 6 +++ src/lxc/confile.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in index ba85a9778..e6d96891f 100644 --- a/doc/lxc.conf.sgml.in +++ b/doc/lxc.conf.sgml.in @@ -1246,7 +1246,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Logging + Logging Logging can be configured on a per-container basis. By default, depending upon how the lxc package was compiled, container startup @@ -1294,6 +1294,63 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Autostart + + The autostart options support marking which containers should be + auto-started and in what order. These options may be used by LXC tools + directly or by external tooling provided by the distributions. + + + + + + + + + + Whether the container should be auto-started. + Valid values are 0 (off) and 1 (on). + + + + + + + + + + How long to wait (in seconds) after the container is + started before starting the next one. + + + + + + + + + + An integer used to sort the containers when auto-starting + a series of containers at once. + + + + + + + + + + A multi-value key (can be used multiple times) to put the + container in a container group. Those groups can then be + used (amongst other things) to start a series of related + containers. + + + + + diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 69f90d002..fb0c593f5 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2642,6 +2642,7 @@ struct lxc_conf *lxc_conf_init(void) lxc_list_init(&new->id_map); for (i=0; ihooks[i]); + lxc_list_init(&new->groups); new->lsm_aa_profile = NULL; new->lsm_se_context = NULL; new->lsm_umount_proc = 0; @@ -3883,6 +3884,18 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key) return 0; } +int lxc_clear_groups(struct lxc_conf *c) +{ + struct lxc_list *it,*next; + + lxc_list_for_each_safe(it, &c->groups, next) { + lxc_list_del(it); + free(it->elem); + free(it); + } + return 0; +} + int lxc_clear_mount_entries(struct lxc_conf *c) { struct lxc_list *it,*next; @@ -3970,6 +3983,7 @@ void lxc_conf_free(struct lxc_conf *conf) lxc_clear_mount_entries(conf); lxc_clear_saved_nics(conf); lxc_clear_idmaps(conf); + lxc_clear_groups(conf); free(conf); } diff --git a/src/lxc/conf.h b/src/lxc/conf.h index f1e09035e..ec7629585 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -323,6 +323,11 @@ struct lxc_conf { int loglevel; // loglevel as specifed in config (if any) int inherit_ns_fd[LXC_NS_MAX]; + + int start_auto; + int start_delay; + int start_order; + struct lxc_list groups; }; int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, @@ -356,6 +361,7 @@ extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key); extern int lxc_clear_mount_entries(struct lxc_conf *c); extern int lxc_clear_hooks(struct lxc_conf *c, const char *key); extern int lxc_clear_idmaps(struct lxc_conf *c); +extern int lxc_clear_groups(struct lxc_conf *c); /* * Configure the container from inside diff --git a/src/lxc/confile.c b/src/lxc/confile.c index dbd140f20..c5ec4f3af 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -92,6 +92,8 @@ static int config_includefile(const char *, const char *, struct lxc_conf *); static int config_network_nic(const char *, const char *, struct lxc_conf *); static int config_autodev(const char *, const char *, struct lxc_conf *); static int config_stopsignal(const char *, const char *, struct lxc_conf *); +static int config_start(const char *, const char *, struct lxc_conf *); +static int config_group(const char *, const char *, struct lxc_conf *); static struct lxc_config_t config[] = { @@ -142,6 +144,10 @@ static struct lxc_config_t config[] = { { "lxc.include", config_includefile }, { "lxc.autodev", config_autodev }, { "lxc.stopsignal", config_stopsignal }, + { "lxc.start.auto", config_start }, + { "lxc.start.delay", config_start }, + { "lxc.start.order", config_start }, + { "lxc.group", config_group }, }; struct signame { @@ -925,6 +931,71 @@ static int config_pts(const char *key, const char *value, return 0; } +static int config_start(const char *key, const char *value, + struct lxc_conf *lxc_conf) +{ + if(strcmp(key, "lxc.start.auto") == 0) { + lxc_conf->start_auto = atoi(value); + return 0; + } + else if (strcmp(key, "lxc.start.delay") == 0) { + lxc_conf->start_delay = atoi(value); + return 0; + } + else if (strcmp(key, "lxc.start.order") == 0) { + lxc_conf->start_order = atoi(value); + return 0; + } + SYSERROR("Unknown key: %s", key); + return -1; +} + +static int config_group(const char *key, const char *value, + struct lxc_conf *lxc_conf) +{ + char *groups, *groupptr, *sptr, *token; + struct lxc_list *grouplist; + int ret = -1; + + if (!strlen(value)) + return lxc_clear_groups(lxc_conf); + + groups = strdup(value); + if (!groups) { + SYSERROR("failed to dup '%s'", value); + return -1; + } + + /* in case several groups are specified in a single line + * split these groups in a single element for the list */ + for (groupptr = groups;;groupptr = NULL) { + token = strtok_r(groupptr, " \t", &sptr); + if (!token) { + ret = 0; + break; + } + + grouplist = malloc(sizeof(*grouplist)); + if (!grouplist) { + SYSERROR("failed to allocate groups list"); + break; + } + + grouplist->elem = strdup(token); + if (!grouplist->elem) { + SYSERROR("failed to dup '%s'", token); + free(grouplist); + break; + } + + lxc_list_add_tail(&lxc_conf->groups, grouplist); + } + + free(groups); + + return ret; +} + static int config_tty(const char *key, const char *value, struct lxc_conf *lxc_conf) { @@ -1729,6 +1800,22 @@ static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen, return fulllen; } +static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen) +{ + int len, fulllen = 0; + struct lxc_list *it; + + if (!retv) + inlen = 0; + else + memset(retv, 0, inlen); + + lxc_list_for_each(it, &c->groups) { + strprint(retv, inlen, "%s\n", (char *)it->elem); + } + return fulllen; +} + static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; @@ -1952,6 +2039,14 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv, return lxc_get_item_network(c, retv, inlen); else if (strncmp(key, "lxc.network.", 12) == 0) return lxc_get_item_nic(c, retv, inlen, key + 12); + else if (strcmp(key, "lxc.start.auto") == 0) + return lxc_get_conf_int(c, retv, inlen, c->start_auto); + else if (strcmp(key, "lxc.start.delay") == 0) + return lxc_get_conf_int(c, retv, inlen, c->start_delay); + else if (strcmp(key, "lxc.start.order") == 0) + return lxc_get_conf_int(c, retv, inlen, c->start_order); + else if (strcmp(key, "lxc.group") == 0) + return lxc_get_item_groups(c, retv, inlen); else return -1; if (!v) @@ -1977,6 +2072,8 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key) return lxc_clear_mount_entries(c); else if (strncmp(key, "lxc.hook", 8) == 0) return lxc_clear_hooks(c, key); + else if (strncmp(key, "lxc.group", 9) == 0) + return lxc_clear_groups(c); return -1; }