[lxc-devel] [PATCH] [resend?] Add a unexpanded lxc_conf
Stéphane Graber
stgraber at ubuntu.com
Wed Jun 18 20:52:07 UTC 2014
On Thu, Jun 12, 2014 at 02:24:38PM +0000, Serge Hallyn wrote:
> Currently when a container's configuration file has lxc.includes,
> any future write_config() will expand the lxc.includes. This
> affects container clones (and snapshots) as well as users of the
> API who make an update and then c.save_config().
>
> To fix this, separately track the expanded and unexpanded lxc_conf. The
> unexpanded conf does not contain values read from lxc.includes. The
> expanded conf does. Lxc functions mainly need the expanded conf to
> figure out how to configure the container. The unexpanded conf is used
> at write_config().
>
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
Acked-by: Stéphane Graber <stgraber at ubuntu.com>
> ---
> src/lxc/conf.c | 13 +++++++++++++
> src/lxc/conf.h | 4 ++++
> src/lxc/confile.c | 45 ++++++++++++++++++++++++++++++++++++++++++---
> src/lxc/confile.h | 2 +-
> src/lxc/lxc_execute.c | 2 +-
> src/lxc/lxccontainer.c | 38 +++++++++++++++++++++++++++++++-------
> src/lxc/lxccontainer.h | 10 ++++++++++
> 7 files changed, 102 insertions(+), 12 deletions(-)
>
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index 4b52550..521a48d 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -2689,6 +2689,7 @@ struct lxc_conf *lxc_conf_init(void)
> lxc_list_init(&new->caps);
> lxc_list_init(&new->keepcaps);
> lxc_list_init(&new->id_map);
> + lxc_list_init(&new->includes);
> for (i=0; i<NUM_LXC_HOOKS; i++)
> lxc_list_init(&new->hooks[i]);
> lxc_list_init(&new->groups);
> @@ -4364,6 +4365,17 @@ static void lxc_clear_saved_nics(struct lxc_conf *conf)
> free(conf->saved_nics);
> }
>
> +static inline void lxc_clear_includes(struct lxc_conf *conf)
> +{
> + struct lxc_list *it,*next;
> +
> + lxc_list_for_each_safe(it, &conf->includes, next) {
> + lxc_list_del(it);
> + free(it->elem);
> + free(it);
> + }
> +}
> +
> void lxc_conf_free(struct lxc_conf *conf)
> {
> if (!conf)
> @@ -4402,6 +4414,7 @@ void lxc_conf_free(struct lxc_conf *conf)
> lxc_clear_saved_nics(conf);
> lxc_clear_idmaps(conf);
> lxc_clear_groups(conf);
> + lxc_clear_includes(conf);
> free(conf);
> }
>
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> index f5fab3d..53590bc 100644
> --- a/src/lxc/conf.h
> +++ b/src/lxc/conf.h
> @@ -283,6 +283,7 @@ struct saved_nic {
>
> struct lxc_conf {
> int is_execute;
> + bool unexpanded;
> char *fstab;
> int tty;
> int pts;
> @@ -338,6 +339,9 @@ struct lxc_conf {
>
> /* set to true when rootfs has been setup */
> bool rootfs_setup;
> +
> + /* list of included files */
> + struct lxc_list includes;
> };
>
> 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 70097f8..2ab3fcb 100644
> --- a/src/lxc/confile.c
> +++ b/src/lxc/confile.c
> @@ -1552,10 +1552,34 @@ static int config_console(const char *key, const char *value,
> return config_path_item(&lxc_conf->console.path, value);
> }
>
> +static int add_include_file(const char *fname, struct lxc_conf *lxc_conf)
> +{
> + struct lxc_list *list;
> + char *v;
> + int len = strlen(fname);
> +
> + list = malloc(sizeof(*list));
> + if (!list)
> + return -1;
> + lxc_list_init(list);
> + v = malloc(len+1);
> + if (!v) {
> + free(list);
> + return -1;
> + }
> + strncpy(v, fname, len);
> + v[len] = '\0';
> + list->elem = v;
> + lxc_list_add_tail(&lxc_conf->includes, list);
> + return 0;
> +}
> +
> static int config_includefile(const char *key, const char *value,
> struct lxc_conf *lxc_conf)
> {
> - return lxc_config_read(value, lxc_conf);
> + if (lxc_conf->unexpanded)
> + return add_include_file(value, lxc_conf);
> + return lxc_config_read(value, lxc_conf, NULL);
> }
>
> static int config_rootfs(const char *key, const char *value,
> @@ -1673,8 +1697,10 @@ static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
> return parse_line(buffer, conf);
> }
>
> -int lxc_config_read(const char *file, struct lxc_conf *conf)
> +int lxc_config_read(const char *file, struct lxc_conf *conf, struct lxc_conf *unexp_conf)
> {
> + int ret;
> +
> if( access(file, R_OK) == -1 ) {
> return -1;
> }
> @@ -1682,7 +1708,16 @@ int lxc_config_read(const char *file, struct lxc_conf *conf)
> if( ! conf->rcfile ) {
> conf->rcfile = strdup( file );
> }
> - return lxc_file_for_each_line(file, parse_line, conf);
> + ret = lxc_file_for_each_line(file, parse_line, conf);
> + if (ret)
> + return ret;
> + if (!unexp_conf)
> + return 0;
> + if (!unexp_conf->rcfile) {
> + unexp_conf->rcfile = strdup( file );
> + }
> +
> + return lxc_file_for_each_line(file, parse_line, unexp_conf);
> }
>
> int lxc_config_define_add(struct lxc_list *defines, char* arg)
> @@ -2223,6 +2258,10 @@ void write_config(FILE *fout, struct lxc_conf *c)
> struct lxc_list *it;
> int i;
>
> + lxc_list_for_each(it, &c->includes) {
> + fprintf(fout, "lxc.include = %s\n", (char *)it->elem);
> + }
> +
> if (c->fstab)
> fprintf(fout, "lxc.mount = %s\n", c->fstab);
> lxc_list_for_each(it, &c->mount_list) {
> diff --git a/src/lxc/confile.h b/src/lxc/confile.h
> index 171614a..7e34089 100644
> --- a/src/lxc/confile.h
> +++ b/src/lxc/confile.h
> @@ -39,7 +39,7 @@ struct lxc_config_t {
> extern struct lxc_config_t *lxc_getconfig(const char *key);
> extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv, int inlen);
> extern int lxc_listconfigs(char *retv, int inlen);
> -extern int lxc_config_read(const char *file, struct lxc_conf *conf);
> +extern int lxc_config_read(const char *file, struct lxc_conf *conf, struct lxc_conf *unexp_conf);
>
> extern int lxc_config_define_add(struct lxc_list *defines, char* arg);
> extern int lxc_config_define_load(struct lxc_list *defines,
> diff --git a/src/lxc/lxc_execute.c b/src/lxc/lxc_execute.c
> index 6949e2b..b602793 100644
> --- a/src/lxc/lxc_execute.c
> +++ b/src/lxc/lxc_execute.c
> @@ -131,7 +131,7 @@ int main(int argc, char *argv[])
> return 1;
> }
>
> - if (rcfile && lxc_config_read(rcfile, conf)) {
> + if (rcfile && lxc_config_read(rcfile, conf, NULL)) {
> ERROR("failed to read configuration file");
> return 1;
> }
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 5cedb27..bb7b4bb 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -238,6 +238,10 @@ static void lxc_container_free(struct lxc_container *c)
> lxc_conf_free(c->lxc_conf);
> c->lxc_conf = NULL;
> }
> + if (c->lxc_unexp_conf) {
> + lxc_conf_free(c->lxc_unexp_conf);
> + c->lxc_unexp_conf = NULL;
> + }
> if (c->config_path) {
> free(c->config_path);
> c->config_path = NULL;
> @@ -410,7 +414,14 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
> {
> if (!c->lxc_conf)
> c->lxc_conf = lxc_conf_init();
> - if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf))
> + if (!c->lxc_unexp_conf) {
> + c->lxc_unexp_conf = lxc_conf_init();
> + if (c->lxc_unexp_conf)
> + c->lxc_unexp_conf->unexpanded = true;
> + }
> + if (c->lxc_conf && c->lxc_unexp_conf &&
> + !lxc_config_read(fname, c->lxc_conf,
> + c->lxc_unexp_conf))
> return true;
> return false;
> }
> @@ -1196,9 +1207,15 @@ out_error:
>
> static void lxcapi_clear_config(struct lxc_container *c)
> {
> - if (c && c->lxc_conf) {
> - lxc_conf_free(c->lxc_conf);
> - c->lxc_conf = NULL;
> + if (c) {
> + if (c->lxc_conf) {
> + lxc_conf_free(c->lxc_conf);
> + c->lxc_conf = NULL;
> + }
> + if (c->lxc_unexp_conf) {
> + lxc_conf_free(c->lxc_unexp_conf);
> + c->lxc_unexp_conf = NULL;
> + }
> }
> }
>
> @@ -1321,6 +1338,7 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
> /* reload config to get the rootfs */
> lxc_conf_free(c->lxc_conf);
> c->lxc_conf = NULL;
> + c->lxc_unexp_conf = NULL;
> if (!load_config_locked(c, c->configfile))
> goto out_unlock;
>
> @@ -1845,7 +1863,7 @@ static bool lxcapi_save_config(struct lxc_container *c, const char *alt_file)
> fout = fopen(alt_file, "w");
> if (!fout)
> goto out;
> - write_config(fout, c->lxc_conf);
> + write_config(fout, c->lxc_unexp_conf);
> fclose(fout);
> ret = true;
>
> @@ -2072,11 +2090,17 @@ static bool set_config_item_locked(struct lxc_container *c, const char *key, con
>
> if (!c->lxc_conf)
> c->lxc_conf = lxc_conf_init();
> - if (!c->lxc_conf)
> + if (!c->lxc_unexp_conf) {
> + c->lxc_unexp_conf = lxc_conf_init();
> + c->lxc_unexp_conf->unexpanded = true;
> + }
> + if (!c->lxc_conf || !c->lxc_unexp_conf)
> return false;
> config = lxc_getconfig(key);
> if (!config)
> return false;
> + if (config->cb(key, v, c->lxc_unexp_conf) != 0)
> + return false;
> return (0 == config->cb(key, v, c->lxc_conf));
> }
>
> @@ -2677,7 +2701,7 @@ static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *n
> SYSERROR("open %s", newpath);
> goto out;
> }
> - write_config(fout, c->lxc_conf);
> + write_config(fout, c->lxc_unexp_conf);
> fclose(fout);
> c->lxc_conf->rootfs.path = origroot;
>
> diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
> index 1d0628a..d1de399 100644
> --- a/src/lxc/lxccontainer.h
> +++ b/src/lxc/lxccontainer.h
> @@ -99,6 +99,16 @@ struct lxc_container {
> */
> struct lxc_conf *lxc_conf;
>
> + /*!
> + * \private
> + * The non-common, unexpanded configuration. This includes the
> + * list of lxc.include files, and does not contain any
> + * individual configuration items from the include files.
> + * Anything coming from the container's own configuration file
> + * or from lxcapi_set_config_item() does get added here.
> + */
> + struct lxc_conf *lxc_unexp_conf;
> +
> // public fields
> /*! Human-readable string representing last error */
> char *error_string;
> --
> 1.9.1
>
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
--
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20140618/48da03c0/attachment.sig>
More information about the lxc-devel
mailing list