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;
}