[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