[lxc-devel] [PATCH RFC] Allow a few basic limits to be set at creation / runtime

Dwight Engen dwight.engen at oracle.com
Thu May 29 14:57:55 UTC 2014


On Thu, 29 May 2014 08:40:01 +0200
Stéphane Graber <stgraber at ubuntu.com> wrote:

> On Wed, May 28, 2014 at 03:58:07PM +0000, Serge Hallyn wrote:
> > Quoting Dwight Engen (dwight.engen at oracle.com):
> > > On Wed, 28 May 2014 14:51:55 +0000
> > > Serge Hallyn <serge.hallyn at ubuntu.com> wrote:
> > > 
> > > > Quoting Dwight Engen (dwight.engen at oracle.com):
> > > > > Currently, a user has to read kernel/Documentation/cgroups/*
> > > > > to know what is available and then apply these using
> > > > > lxc-cgroups to set runtime limits, or hand edit the
> > > > > configuration file after creating a container to set them
> > > > > permanently.
> > > > > 
> > > > > This change covers the most common use cases (cpu, memory) by
> > > > > allowing the user to specify them to lxc-create, and
> > > > > introduces a new command lxc-ctl which allows setting the
> > > > > limits at run-time and/or saving them to the containers'
> > > > > config file with the --save option. This functionality is
> > > > > analogous to that found in vzctl, or Solaris zonecfg.
> > > > > 
> > > > > Introduce config_cgroup_find to find an already set cgroup
> > > > > item, and use it in config_cgroup() to replace a value
> > > > > instead of appending another entry. This means that (in for
> > > > > example lxc-clone) only the last duplicate entry will now be
> > > > > written out.
> > > > > 
> > > > > Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
> > > > 
> > > > would lxc-cgctl or lxc-limit be a better name, or do you intend
> > > > to generalize it to other container controls later?
> > > 
> > > I'm open to whatever name we feel is appropriate. I called it
> > > lxc-ctl to leave it open in case we wanted to extend it in the
> > > future and also since it might be more discoverable to users of
> > > vzctl.
> > > 
> > > Since you acked it below, I'll take it that we're okay with the
> > > idea in
> > 
> > Yup, and I'm also ok with the name.  Not sure whether Stéphane will
> > have objections, but I think it's true that most people are
> > currently not using cgroups with containers much for lack of
> > something like this.
> 
> First of all, you're missing a manpage :)
> 
> 
> I've been talking about a tool like that a bit with Serge a few weeks
> back and still think it'd be good to have for 1.1, however I think we
> should expand the scope of it a bit to cover most container
> configuration use cases.

We could make it so that the tool could basically call
lxc_config_readline() on --config=<arg> Any that it determines could be
applied at runtime it could go ahead and apply, otherwise they are set
into the config for the --save case.

> It sounds like one such tool could basically replace lxc-cgroup
> entirely, some of what lxc-info does, lxc-device could probably be
> merged into it too.
> 
> 
> So I definitely agree with the idea, and I think while LXC 1.0's
> commands were a big improvement over 0.9 in consistency and ease of
> use, we can do much better with 1.1.
> As for the exact implementation, I think we need to talk some more
> about what features we want in there, make sure we have something
> that covers our current needs and that's flexible enough to add extra
> class of options in the future, deal with things we can change on the
> fly, things we can only change in the config, ...

That sounds good to me. I was just initially going for a few simple
cases that I thought would be the most useful, but I agree with
designing it to handle what we need in the future. The trick is in
deciding what the tool should handle vs just saying edit the config
file.

> Adding binaries all the time isn't very scalable when we have an ever
> expanding set of features, I'd rather not have lxc turn into git in
> that regard where my system nowadays list 155 git- commands
> available :)

Yeah, and there is certainly overlap with this and lxc-cgroup at a
minimum right now. I'd be okay with a single lxc binary with
subcommands, but we'd discussed that before and I think Serge prefers
separate binaries. If you think lxc-cgroup and lxc-info should be
combined into this, I can take a look at that.
 
> > 
> > > general, and I'll write up a man page for the new command once we
> > > settle on a name.
> > > 
> > > > Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
> > > > 
> > > > > ---
> > > > >  .gitignore           |   1 +
> > > > >  src/lxc/Makefile.am  |   2 +
> > > > >  src/lxc/arguments.h  |  10 ++-
> > > > >  src/lxc/confile.c    | 175
> > > > > ++++++++++++++++++++++++++++++++++++++++++---------
> > > > > src/lxc/confile.h    |  18 ++++++ src/lxc/lxc_create.c |  19
> > > > > +++++- src/lxc/lxc_ctl.c    | 133
> > > > > +++++++++++++++++++++++++++++++++++++++ 7 files changed, 326
> > > > > insertions(+), 32 deletions(-) create mode 100644
> > > > > src/lxc/lxc_ctl.c
> > > > > 
> > > > > diff --git a/.gitignore b/.gitignore
> > > > > index 8145f81..b90a0e2 100644
> > > > > --- a/.gitignore
> > > > > +++ b/.gitignore
> > > > > @@ -52,6 +52,7 @@ src/lxc/lxc-clone
> > > > >  src/lxc/lxc-console
> > > > >  src/lxc/lxc-config
> > > > >  src/lxc/lxc-create
> > > > > +src/lxc/lxc-ctl
> > > > >  src/lxc/lxc-destroy
> > > > >  src/lxc/lxc-execute
> > > > >  src/lxc/lxc-freeze
> > > > > diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> > > > > index ab8a46e..d48ebf6 100644
> > > > > --- a/src/lxc/Makefile.am
> > > > > +++ b/src/lxc/Makefile.am
> > > > > @@ -186,6 +186,7 @@ bin_PROGRAMS = \
> > > > >  	lxc-config \
> > > > >  	lxc-console \
> > > > >  	lxc-create \
> > > > > +	lxc-ctl \
> > > > >  	lxc-destroy \
> > > > >  	lxc-execute \
> > > > >  	lxc-freeze \
> > > > > @@ -229,6 +230,7 @@ lxc_unfreeze_SOURCES = lxc_unfreeze.c
> > > > >  lxc_unshare_SOURCES = lxc_unshare.c
> > > > >  lxc_wait_SOURCES = lxc_wait.c
> > > > >  lxc_create_SOURCES = lxc_create.c
> > > > > +lxc_ctl_SOURCES = lxc_ctl.c
> > > > >  lxc_snapshot_SOURCES = lxc_snapshot.c
> > > > >  lxc_usernsexec_SOURCES = lxc_usernsexec.c
> > > > >  lxc_user_nic_SOURCES = lxc_user_nic.c network.c network.h
> > > > > diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
> > > > > index cc85f86..0e963dd 100644
> > > > > --- a/src/lxc/arguments.h
> > > > > +++ b/src/lxc/arguments.h
> > > > > @@ -88,6 +88,9 @@ struct lxc_arguments {
> > > > >  	char *lvname, *vgname, *thinpool;
> > > > >  	char *zfsroot, *lowerdir, *dir;
> > > > >  
> > > > > +	/* lxc-create/lxc-ctl */
> > > > > +	char *mem, *cpulimit, *cpuset;
> > > > > +
> > > > >  	/* auto-start */
> > > > >  	int all;
> > > > >  	int ignore_auto;
> > > > > @@ -114,8 +117,11 @@ struct lxc_arguments {
> > > > >  	{0, 0, 0, 0}
> > > > >  
> > > > >  /* option keys for long only options */
> > > > > -#define	OPT_USAGE 0x1000
> > > > > -#define	OPT_VERSION OPT_USAGE-1
> > > > > +#define	OPT_USAGE	0x1000
> > > > > +#define	OPT_VERSION	OPT_USAGE-1
> > > > > +#define OPT_MEM		OPT_USAGE-2
> > > > > +#define OPT_CPULIMIT	OPT_USAGE-3
> > > > > +#define OPT_CPUSET	OPT_USAGE-4
> > > > >  
> > > > >  extern int lxc_arguments_parse(struct lxc_arguments *args,
> > > > >  			       int argc, char *const argv[]);
> > > > > diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> > > > > index ac05b75..d65789e 100644
> > > > > --- a/src/lxc/confile.c
> > > > > +++ b/src/lxc/confile.c
> > > > > @@ -37,6 +37,7 @@
> > > > >  #include <netinet/in.h>
> > > > >  #include <net/if.h>
> > > > >  
> > > > > +#include "arguments.h"
> > > > >  #include "parse.h"
> > > > >  #include "config.h"
> > > > >  #include "confile.h"
> > > > > @@ -45,6 +46,7 @@
> > > > >  #include "conf.h"
> > > > >  #include "network.h"
> > > > >  #include "lxcseccomp.h"
> > > > > +#include "lxccontainer.h"
> > > > >  
> > > > >  #if HAVE_SYS_PERSONALITY_H
> > > > >  #include <sys/personality.h>
> > > > > @@ -1212,13 +1214,27 @@ static int config_stopsignal(const
> > > > > char *key, const char *value, return 0;
> > > > >  }
> > > > >  
> > > > > +static struct lxc_list *config_cgroup_find(struct lxc_conf
> > > > > *lxc_conf,
> > > > > +					   const char
> > > > > *subkey) +{
> > > > > +	struct lxc_list *it;
> > > > > +
> > > > > +	lxc_list_for_each(it, &lxc_conf->cgroup) {
> > > > > +		struct lxc_cgroup *cg = it->elem;
> > > > > +		if (strcmp(cg->subsystem, subkey) == 0)
> > > > > +			return it;
> > > > > +	}
> > > > > +	return NULL;
> > > > > +}
> > > > > +
> > > > >  static int config_cgroup(const char *key, const char *value,
> > > > >  			 struct lxc_conf *lxc_conf)
> > > > >  {
> > > > >  	char *token = "lxc.cgroup.";
> > > > > -	char *subkey;
> > > > > +	char *subkey, *subsystem, *val;
> > > > >  	struct lxc_list *cglist = NULL;
> > > > >  	struct lxc_cgroup *cgelem = NULL;
> > > > > +	bool add = false;
> > > > >  
> > > > >  	if (!value || strlen(value) == 0)
> > > > >  		return lxc_clear_cgroups(lxc_conf, key);
> > > > > @@ -1236,41 +1252,44 @@ static int config_cgroup(const char
> > > > > *key, const char *value, 
> > > > >  	subkey += strlen(token);
> > > > >  
> > > > > -	cglist = malloc(sizeof(*cglist));
> > > > > -	if (!cglist)
> > > > > -		goto out;
> > > > > -
> > > > > -	cgelem = malloc(sizeof(*cgelem));
> > > > > -	if (!cgelem)
> > > > > -		goto out;
> > > > > -	memset(cgelem, 0, sizeof(*cgelem));
> > > > > +	subsystem = strdup(subkey);
> > > > > +	if (!subsystem)
> > > > > +		return -1;
> > > > > +	val = strdup(value);
> > > > > +	if (!val)
> > > > > +		goto err1;
> > > > >  
> > > > > -	cgelem->subsystem = strdup(subkey);
> > > > > -	cgelem->value = strdup(value);
> > > > > +	cglist = config_cgroup_find(lxc_conf, subkey);
> > > > > +	if (cglist) {
> > > > > +		cgelem = cglist->elem;
> > > > > +		free(cgelem->subsystem);
> > > > > +		free(cgelem->value);
> > > > > +	} else {
> > > > > +		cglist = malloc(sizeof(*cglist));
> > > > > +		if (!cglist)
> > > > > +			goto err2;
> > > > >  
> > > > > -	if (!cgelem->subsystem || !cgelem->value)
> > > > > -		goto out;
> > > > > +		cgelem = malloc(sizeof(*cgelem));
> > > > > +		if (!cgelem)
> > > > > +			goto err3;
> > > > > +		memset(cgelem, 0, sizeof(*cgelem));
> > > > > +		add = true;
> > > > > +	}
> > > > >  
> > > > > +	cgelem->subsystem = subsystem;
> > > > > +	cgelem->value = val;
> > > > >  	cglist->elem = cgelem;
> > > > >  
> > > > > -	lxc_list_add_tail(&lxc_conf->cgroup, cglist);
> > > > > -
> > > > > +	if (add)
> > > > > +		lxc_list_add_tail(&lxc_conf->cgroup, cglist);
> > > > >  	return 0;
> > > > >  
> > > > > -out:
> > > > > -	if (cglist)
> > > > > -		free(cglist);
> > > > > -
> > > > > -	if (cgelem) {
> > > > > -		if (cgelem->subsystem)
> > > > > -			free(cgelem->subsystem);
> > > > > -
> > > > > -		if (cgelem->value)
> > > > > -			free(cgelem->value);
> > > > > -
> > > > > -		free(cgelem);
> > > > > -	}
> > > > > -
> > > > > +err3:
> > > > > +	free(cglist);
> > > > > +err2:
> > > > > +	free(val);
> > > > > +err1:
> > > > > +	free(subsystem);
> > > > >  	return -1;
> > > > >  }
> > > > >  
> > > > > @@ -2402,3 +2421,101 @@ void write_config(FILE *fout, struct
> > > > > lxc_conf *c) lxc_list_for_each(it, &c->groups)
> > > > >  		fprintf(fout, "lxc.group = %s\n", (char
> > > > > *)it->elem); }
> > > > > +
> > > > > +static const struct lxc_ctl lxc_ctl_init[] = {
> > > > > +	{false, "mem",       "memory.limit_in_bytes", NULL},
> > > > > +	{false, "cpulimit",  "cpu.shares", NULL},
> > > > > +	{false, "cpuset",    "cpuset.cpus", NULL}
> > > > > +};
> > > > > +
> > > > > +#define LXC_CTL_CNT
> > > > > (sizeof(lxc_ctl_init)/sizeof(lxc_ctl_init[0])) +
> > > > > +struct lxc_ctl *lxc_ctl_new(struct lxc_arguments *args)
> > > > > +{
> > > > > +	struct lxc_ctl *ctl;
> > > > > +	ctl = malloc(sizeof(lxc_ctl_init));
> > > > > +	if (ctl)
> > > > > +		memcpy(ctl, lxc_ctl_init,
> > > > > sizeof(lxc_ctl_init));
> > > > > +	if (args->mem)
> > > > > +		lxc_ctl_set_value(ctl, "mem", args->mem);
> > > > > +	if (args->cpuset)
> > > > > +		lxc_ctl_set_value(ctl, "cpuset",
> > > > > args->cpuset);
> > > > > +	if (args->cpulimit) {
> > > > > +		char buf[11];
> > > > > +		sprintf(buf, "%d", atoi(args->cpulimit) *
> > > > > 1024 / 100);
> > > > > +		lxc_ctl_set_value(ctl, "cpulimit", buf);
> > > > > +	}
> > > > > +
> > > > > +	return ctl;
> > > > > +};
> > > > > +
> > > > > +void lxc_ctl_free(struct lxc_ctl *lxc_ctl)
> > > > > +{
> > > > > +	int i;
> > > > > +
> > > > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > > > +		if (lxc_ctl[i].value)
> > > > > +			free(lxc_ctl[i].value);
> > > > > +	}
> > > > > +	free(lxc_ctl);
> > > > > +}
> > > > > +
> > > > > +void lxc_ctl_set_value(struct lxc_ctl *lxc_ctl, const char
> > > > > *ctl,
> > > > > +		       const char *value)
> > > > > +{
> > > > > +	int i;
> > > > > +
> > > > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > > > +		if (strcmp(lxc_ctl[i].ctl, ctl))
> > > > > +			continue;
> > > > > +		lxc_ctl[i].set = 1;
> > > > > +		if (lxc_ctl[i].value)
> > > > > +			free(lxc_ctl[i].value);
> > > > > +		lxc_ctl[i].value = strdup(value);
> > > > > +		break;
> > > > > +	}
> > > > > +}
> > > > > +
> > > > > +bool lxc_ctl_set_running(struct lxc_ctl *lxc_ctl, struct
> > > > > lxc_container *c) +{
> > > > > +	int i;
> > > > > +
> > > > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > > > +		if (!lxc_ctl[i].set)
> > > > > +			continue;
> > > > > +
> > > > > +		if (!c->set_cgroup_item(c, lxc_ctl[i].cgitem,
> > > > > lxc_ctl[i].value)) {
> > > > > +			ERROR("failed setting %s to %s",
> > > > > +			      lxc_ctl[i].cgitem,
> > > > > lxc_ctl[i].value);
> > > > > +			return false;
> > > > > +		}
> > > > > +	}
> > > > > +	return true;
> > > > > +}
> > > > > +
> > > > > +bool lxc_ctl_set_config(struct lxc_ctl *lxc_ctl, struct
> > > > > lxc_container *c) +{
> > > > > +	char *key;
> > > > > +	int i, rc;
> > > > > +	bool did_set = false;
> > > > > +
> > > > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > > > +		if (!lxc_ctl[i].set)
> > > > > +			continue;
> > > > > +
> > > > > +		rc = asprintf(&key, "lxc.cgroup.%s",
> > > > > lxc_ctl[i].cgitem);
> > > > > +		if (rc < 0)
> > > > > +			return false;
> > > > > +		if (config_cgroup(key, lxc_ctl[i].value,
> > > > > c->lxc_conf) != 0) {
> > > > > +			ERROR("failed setting cfg %s to %s",
> > > > > +			      lxc_ctl[i].cgitem,
> > > > > lxc_ctl[i].value);
> > > > > +			return false;
> > > > > +		}
> > > > > +		free(key);
> > > > > +		did_set = true;
> > > > > +	}
> > > > > +
> > > > > +	if (did_set && !c->save_config(c, NULL))
> > > > > +		return false;
> > > > > +	return true;
> > > > > +}
> > > > > diff --git a/src/lxc/confile.h b/src/lxc/confile.h
> > > > > index 171614a..4e32ede 100644
> > > > > --- a/src/lxc/confile.h
> > > > > +++ b/src/lxc/confile.h
> > > > > @@ -25,10 +25,13 @@
> > > > >  #define __LXC_CONFILE_H
> > > > >  
> > > > >  #include <stdio.h>
> > > > > +#include <stdbool.h>
> > > > >  #include <lxc/attach_options.h>
> > > > >  
> > > > >  struct lxc_conf;
> > > > >  struct lxc_list;
> > > > > +struct lxc_container;
> > > > > +struct lxc_arguments;
> > > > >  
> > > > >  typedef int (*config_cb)(const char *, const char *, struct
> > > > > lxc_conf *); struct lxc_config_t {
> > > > > @@ -52,4 +55,19 @@ extern int
> > > > > lxc_fill_elevated_privileges(char *flaglist, int *flags);
> > > > > extern int lxc_get_config_item(struct lxc_conf *c, const char
> > > > > *key, char *retv, int inlen); extern int
> > > > > lxc_clear_config_item(struct lxc_conf *c, const char *key);
> > > > > extern void write_config(FILE *fout, struct lxc_conf *c); +
> > > > > +struct lxc_ctl +{
> > > > > +	bool set;
> > > > > +	const char *ctl;
> > > > > +	const char *cgitem;
> > > > > +	char *value;
> > > > > +};
> > > > > +
> > > > > +extern struct lxc_ctl *lxc_ctl_new(struct lxc_arguments
> > > > > *args); +extern void lxc_ctl_free(struct lxc_ctl *lxc_ctl);
> > > > > +extern void lxc_ctl_set_value(struct lxc_ctl *lxc_ctl, const
> > > > > char *ctl, const char *value); +extern bool
> > > > > lxc_ctl_set_running(struct lxc_ctl *lxc_ctl, struct
> > > > > lxc_container *c); +extern bool lxc_ctl_set_config(struct
> > > > > lxc_ctl *lxc_ctl, struct lxc_container *c); + #endif
> > > > > diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c
> > > > > index 2cc866a..b8bf312 100644
> > > > > --- a/src/lxc/lxc_create.c
> > > > > +++ b/src/lxc/lxc_create.c
> > > > > @@ -32,6 +32,7 @@
> > > > >  #include "bdev.h"
> > > > >  #include "arguments.h"
> > > > >  #include "utils.h"
> > > > > +#include "confile.h"
> > > > >  
> > > > >  lxc_log_define(lxc_create_ui, lxc);
> > > > >  
> > > > > @@ -81,6 +82,9 @@ static int my_parser(struct lxc_arguments*
> > > > > args, int c, char* arg) case '4': args->fssize =
> > > > > get_fssize(arg); break; case '5': args->zfsroot = arg; break;
> > > > >  	case '6': args->dir = arg; break;
> > > > > +	case OPT_CPULIMIT: args->cpulimit = arg; break;
> > > > > +	case OPT_CPUSET: args->cpuset = arg; break;
> > > > > +	case OPT_MEM: args->mem = arg; break;
> > > > >  	}
> > > > >  	return 0;
> > > > >  }
> > > > > @@ -96,6 +100,9 @@ static const struct option my_longopts[] =
> > > > > { {"fssize", required_argument, 0, '4'},
> > > > >  	{"zfsroot", required_argument, 0, '5'},
> > > > >  	{"dir", required_argument, 0, '6'},
> > > > > +	{"cpulimit", required_argument, 0, OPT_CPULIMIT},
> > > > > +	{"cpuset", required_argument, 0, OPT_CPUSET},
> > > > > +	{"mem", required_argument, 0, OPT_MEM},
> > > > >  	LXC_COMMON_OPTIONS
> > > > >  };
> > > > >  
> > > > > @@ -154,7 +161,10 @@ Options :\n\
> > > > >                       (Default: 1G, default unit: M)\n\
> > > > >    --dir=DIR          Place rootfs directory under DIR\n\
> > > > >    --zfsroot=PATH     Create zfs under given zfsroot\n\
> > > > > -                     (Default: tank/lxc)\n",
> > > > > +                     (Default: tank/lxc)\n\
> > > > > +  --cpulimit=NUM     Percentage of cpu allowed\n\
> > > > > +  --cpuset=NUM,NUM   Which cpus to run on\n\
> > > > > +  --mem=BYTES        Amount of memory (may be suffixed with
> > > > > K,M,G)\n", .options  = my_longopts,
> > > > >  	.parser   = my_parser,
> > > > >  	.checker  = NULL,
> > > > > @@ -190,6 +200,7 @@ int main(int argc, char *argv[])
> > > > >  {
> > > > >  	struct lxc_container *c;
> > > > >  	struct bdev_specs spec;
> > > > > +	struct lxc_ctl *ctl;
> > > > >  	int flags = 0;
> > > > >  
> > > > >  	if (lxc_arguments_parse(&my_args, argc, argv))
> > > > > @@ -221,6 +232,10 @@ int main(int argc, char *argv[])
> > > > >  	if (strcmp(my_args.bdevtype, "none") == 0)
> > > > >  		my_args.bdevtype = "dir";
> > > > >  
> > > > > +	ctl = lxc_ctl_new(&my_args);
> > > > > +	if (!ctl)
> > > > > +		exit(1);
> > > > > +
> > > > >  	if (geteuid()) {
> > > > >  		if (mkdir_p(my_args.lxcpath[0], 0755)) {
> > > > >  			exit(1);
> > > > > @@ -276,6 +291,8 @@ int main(int argc, char *argv[])
> > > > >  		my_args.bdevtype = NULL;
> > > > >  	if (my_args.quiet)
> > > > >  		flags = LXC_CREATE_QUIET;
> > > > > +
> > > > > +	lxc_ctl_set_config(ctl, c);
> > > > >  	if (!c->create(c, my_args.template, my_args.bdevtype,
> > > > > &spec, flags, &argv[optind])) { ERROR("Error creating
> > > > > container %s", c->name); lxc_container_put(c);
> > > > > diff --git a/src/lxc/lxc_ctl.c b/src/lxc/lxc_ctl.c
> > > > > new file mode 100644
> > > > > index 0000000..efe82f9
> > > > > --- /dev/null
> > > > > +++ b/src/lxc/lxc_ctl.c
> > > > > @@ -0,0 +1,133 @@
> > > > > +/*
> > > > > + * lxc: linux Container library
> > > > > + *
> > > > > + * Authors:
> > > > > + * Copyright © 2014 Oracle
> > > > > + * Dwight Engen <dwight.engen at oracle.com>
> > > > > + *
> > > > > + * This library is free software; you can redistribute it
> > > > > and/or
> > > > > + * modify it under the terms of the GNU Lesser General Public
> > > > > + * License as published by the Free Software Foundation;
> > > > > either
> > > > > + * version 2.1 of the License, or (at your option) any later
> > > > > version.
> > > > > + *
> > > > > + * This library is distributed in the hope that it will be
> > > > > useful,
> > > > > + * but WITHOUT ANY WARRANTY; without even the implied
> > > > > warranty of
> > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> > > > > the GNU
> > > > > + * Lesser General Public License for more details.
> > > > > + *
> > > > > + * You should have received a copy of the GNU Lesser General
> > > > > Public
> > > > > + * License along with this library; if not, write to the Free
> > > > > Software
> > > > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
> > > > > Boston, MA 02110-1301 USA
> > > > > + */
> > > > > +
> > > > > +#define _GNU_SOURCE
> > > > > +#include <stdio.h>
> > > > > +#include <stdbool.h>
> > > > > +#include <sys/types.h>
> > > > > +
> > > > > +#include <lxc/lxccontainer.h>
> > > > > +
> > > > > +#include "lxc.h"
> > > > > +#include "log.h"
> > > > > +#include "utils.h"
> > > > > +#include "arguments.h"
> > > > > +#include "confile.h"
> > > > > +
> > > > > +lxc_log_define(lxc_ctl_ui, lxc);
> > > > > +
> > > > > +static bool save = false;
> > > > > +
> > > > > +#define OPT_SAVE	OPT_USAGE+1
> > > > > +
> > > > > +static int my_parser(struct lxc_arguments *args, int c, char
> > > > > *arg) +{
> > > > > +	switch (c) {
> > > > > +	case OPT_SAVE: save = 1; break;
> > > > > +	case OPT_CPULIMIT: args->cpulimit = arg; break;
> > > > > +	case OPT_CPUSET: args->cpuset = arg; break;
> > > > > +	case OPT_MEM: args->mem = arg; break;
> > > > > +	}
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct option my_longopts[] = {
> > > > > +	{"save", no_argument, 0, OPT_SAVE},
> > > > > +	{"cpulimit", required_argument, 0, OPT_CPULIMIT},
> > > > > +	{"cpuset", required_argument, 0, OPT_CPUSET},
> > > > > +	{"mem", required_argument, 0, OPT_MEM},
> > > > > +	LXC_COMMON_OPTIONS,
> > > > > +};
> > > > > +
> > > > > +static struct lxc_arguments my_args = {
> > > > > +	.progname = "lxc-ctl",
> > > > > +	.help     = "\
> > > > > +--name=NAME\n\
> > > > > +\n\
> > > > > +lxc-ctl set basic container limits\n\
> > > > > +\n\
> > > > > +Options :\n\
> > > > > +  -n, --name=NAME       NAME for name of the container\n\
> > > > > +      --save            Save to config file\n\
> > > > > +      --cpulimit=NUM    Set percentage of cpu allowed\n\
> > > > > +      --cpuset=NUM,NUM  Set which cpus to run on\n\
> > > > > +      --mem=BYTES       Set amount of memory (may be
> > > > > suffixed with K,M,G)",
> > > > > +	.name     = NULL,
> > > > > +	.options  = my_longopts,
> > > > > +	.parser   = my_parser,
> > > > > +	.checker  = NULL,
> > > > > +};
> > > > > +
> > > > > +int main(int argc, char *argv[])
> > > > > +{
> > > > > +	struct lxc_container *c;
> > > > > +	struct lxc_ctl *ctl;
> > > > > +	int ret = EXIT_FAILURE;
> > > > > +
> > > > > +	if (lxc_arguments_parse(&my_args, argc, argv))
> > > > > +		goto err1;
> > > > > +
> > > > > +	if (!my_args.log_file)
> > > > > +		my_args.log_file = "none";
> > > > > +
> > > > > +	if (lxc_log_init(my_args.name, my_args.log_file,
> > > > > my_args.log_priority,
> > > > > +			 my_args.progname, my_args.quiet,
> > > > > my_args.lxcpath[0]))
> > > > > +		goto err1;
> > > > > +	lxc_log_options_no_override();
> > > > > +
> > > > > +	c = lxc_container_new(my_args.name,
> > > > > my_args.lxcpath[0]);
> > > > > +	if (!c)
> > > > > +		goto err1;
> > > > > +
> > > > > +	if (!c->may_control(c)) {
> > > > > +		ERROR("Insufficent privileges to control
> > > > > %s:%s", my_args.lxcpath[0], my_args.name);
> > > > > +		goto err2;
> > > > > +	}
> > > > > +
> > > > > +	ctl = lxc_ctl_new(&my_args);
> > > > > +	if (!ctl)
> > > > > +		goto err2;
> > > > > +
> > > > > +	if (save && !lxc_ctl_set_config(ctl, c)) {
> > > > > +		ERROR("failed to save config %s:%s",
> > > > > my_args.lxcpath[0], my_args.name);
> > > > > +		goto err3;
> > > > > +	}
> > > > > +
> > > > > +	if (c->is_running(c)) {
> > > > > +		if (!lxc_ctl_set_running(ctl, c))
> > > > > +			goto err3;
> > > > > +	} else {
> > > > > +		if (!save) {
> > > > > +			ERROR("%s:%s is not running",
> > > > > my_args.lxcpath[0], my_args.name);
> > > > > +			goto err3;
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	ret = EXIT_SUCCESS;
> > > > > +
> > > > > +err3:
> > > > > +	lxc_ctl_free(ctl);
> > > > > +err2:
> > > > > +	lxc_container_put(c);
> > > > > +err1:
> > > > > +	return ret;
> > > > > +}
> > > > > -- 
> > > > > 1.9.0
> > > > > 
> > > > > _______________________________________________
> > > > > lxc-devel mailing list
> > > > > lxc-devel at lists.linuxcontainers.org
> > > > > http://lists.linuxcontainers.org/listinfo/lxc-devel
> > > > _______________________________________________
> > > > lxc-devel mailing list
> > > > lxc-devel at lists.linuxcontainers.org
> > > > http://lists.linuxcontainers.org/listinfo/lxc-devel
> > > 
> > > _______________________________________________
> > > lxc-devel mailing list
> > > lxc-devel at lists.linuxcontainers.org
> > > http://lists.linuxcontainers.org/listinfo/lxc-devel
> > _______________________________________________
> > lxc-devel mailing list
> > lxc-devel at lists.linuxcontainers.org
> > http://lists.linuxcontainers.org/listinfo/lxc-devel
> 



More information about the lxc-devel mailing list