mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-15 13:47:41 +00:00
api: add set_cgroup_item and get_cgroup_item (to c api)
set_cgroup_item takes a pointer to a running container, a cgroup subsystem name, and a char *value and it mimicks 'lxc-cgroup -n containername subsys value' get_cgroup_item takes a pointer to a running container, a a cgroup subsystem name, a destination value * and the length of the value being sent in, and returns the length of what was read from the cgroup file. If a 0 len is passed in, then the length of the file is returned. So you can do len = c->get_cgroup_item(c, "devices.list", NULL, 0); v = malloc(len+1); ret = c->get_cgroup_item(c, "devices.list", v, len); to read the whole file. This patch also disables the lxc-init part of the startone test, which was failing because lxc-init has been moved due to multiarch issues. The test is salvagable, but saving it was beyond this effort. Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com> Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
parent
ab4a150176
commit
794dd12099
@ -789,6 +789,13 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you pass in NULL value or 0 len, then you are asking for the size
|
||||||
|
* of the file. Note that we can't get the file size quickly through stat
|
||||||
|
* or lseek. Therefore if you pass in len > 0 but less than the file size,
|
||||||
|
* your only indication will be that the return value will be equal to the
|
||||||
|
* passed-in ret. We will not return the actual full file size.
|
||||||
|
*/
|
||||||
int lxc_cgroup_get(const char *name, const char *filename,
|
int lxc_cgroup_get(const char *name, const char *filename,
|
||||||
char *value, size_t len)
|
char *value, size_t len)
|
||||||
{
|
{
|
||||||
@ -813,7 +820,18 @@ int lxc_cgroup_get(const char *name, const char *filename,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!len || !value) {
|
||||||
|
char buf[100];
|
||||||
|
int count = 0;
|
||||||
|
while ((ret = read(fd, buf, 100)) > 0)
|
||||||
|
count += ret;
|
||||||
|
if (ret >= 0)
|
||||||
|
ret = count;
|
||||||
|
} else {
|
||||||
|
memset(value, 0, len);
|
||||||
ret = read(fd, value, len);
|
ret = read(fd, value, len);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
ERROR("read %s : %s", path, strerror(errno));
|
ERROR("read %s : %s", path, strerror(errno));
|
||||||
|
|
||||||
|
@ -163,6 +163,13 @@ static const char *lxcapi_state(struct lxc_container *c)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_stopped_nolock(struct lxc_container *c)
|
||||||
|
{
|
||||||
|
lxc_state_t s;
|
||||||
|
s = lxc_getstate(c->name);
|
||||||
|
return (s == STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
static bool lxcapi_is_running(struct lxc_container *c)
|
static bool lxcapi_is_running(struct lxc_container *c)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
@ -850,6 +857,49 @@ static char *lxcapi_config_file_name(struct lxc_container *c)
|
|||||||
return strdup(c->configfile);
|
return strdup(c->configfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
bool b = false;
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lxclock(c->privlock, 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (is_stopped_nolock(c))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = lxc_cgroup_set(c->name, subsys, value);
|
||||||
|
if (!ret)
|
||||||
|
b = true;
|
||||||
|
err:
|
||||||
|
lxcunlock(c->privlock);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!c || !c->lxc_conf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (lxclock(c->privlock, 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (is_stopped_nolock(c))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = lxc_cgroup_get(c->name, subsys, retv, inlen);
|
||||||
|
|
||||||
|
out:
|
||||||
|
lxcunlock(c->privlock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct lxc_container *lxc_container_new(const char *name)
|
struct lxc_container *lxc_container_new(const char *name)
|
||||||
{
|
{
|
||||||
struct lxc_container *c;
|
struct lxc_container *c;
|
||||||
@ -920,6 +970,8 @@ struct lxc_container *lxc_container_new(const char *name)
|
|||||||
c->shutdown = lxcapi_shutdown;
|
c->shutdown = lxcapi_shutdown;
|
||||||
c->clear_config_item = lxcapi_clear_config_item;
|
c->clear_config_item = lxcapi_clear_config_item;
|
||||||
c->get_config_item = lxcapi_get_config_item;
|
c->get_config_item = lxcapi_get_config_item;
|
||||||
|
c->get_cgroup_item = lxcapi_get_cgroup_item;
|
||||||
|
c->set_cgroup_item = lxcapi_set_cgroup_item;
|
||||||
|
|
||||||
/* we'll allow the caller to update these later */
|
/* we'll allow the caller to update these later */
|
||||||
if (lxc_log_init(NULL, NULL, "lxc_container", 0)) {
|
if (lxc_log_init(NULL, NULL, "lxc_container", 0)) {
|
||||||
|
@ -48,6 +48,15 @@ struct lxc_container {
|
|||||||
* the length which was our would be printed. */
|
* the length which was our would be printed. */
|
||||||
int (*get_config_item)(struct lxc_container *c, const char *key, char *retv, int inlen);
|
int (*get_config_item)(struct lxc_container *c, const char *key, char *retv, int inlen);
|
||||||
int (*get_keys)(struct lxc_container *c, const char *key, char *retv, int inlen);
|
int (*get_keys)(struct lxc_container *c, const char *key, char *retv, int inlen);
|
||||||
|
/*
|
||||||
|
* get_cgroup_item returns the number of bytes read, or an error (<0).
|
||||||
|
* If retv NULL or inlen 0 is passed in, then the length of the cgroup
|
||||||
|
* file will be returned. * Otherwise it will return the # of bytes read.
|
||||||
|
* If inlen is less than the number of bytes available, then the returned
|
||||||
|
* value will be inlen, not the full available size of the file.
|
||||||
|
*/
|
||||||
|
int (*get_cgroup_item)(struct lxc_container *c, const char *subsys, char *retv, int inlen);
|
||||||
|
bool (*set_cgroup_item)(struct lxc_container *c, const char *subsys, const char *value);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
bool (*commit_cgroups)(struct lxc_container *c);
|
bool (*commit_cgroups)(struct lxc_container *c);
|
||||||
|
@ -98,6 +98,8 @@ int main(int argc, char *argv[])
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
const char *s;
|
const char *s;
|
||||||
bool b;
|
bool b;
|
||||||
|
char buf[201];
|
||||||
|
int len;
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
/* test a real container */
|
/* test a real container */
|
||||||
@ -125,6 +127,19 @@ int main(int argc, char *argv[])
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200);
|
||||||
|
if (len >= 0) {
|
||||||
|
fprintf(stderr, "%d: %s not running but had cgroup settings\n", __LINE__, MYNAME);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buf, "0");
|
||||||
|
b = c->set_cgroup_item(c, "cpuset.cpus", buf);
|
||||||
|
if (b) {
|
||||||
|
fprintf(stderr, "%d: %s not running but coudl set cgroup settings\n", __LINE__, MYNAME);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
s = c->state(c);
|
s = c->state(c);
|
||||||
if (!s || strcmp(s, "STOPPED")) {
|
if (!s || strcmp(s, "STOPPED")) {
|
||||||
fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined");
|
fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined");
|
||||||
@ -172,12 +187,43 @@ int main(int argc, char *argv[])
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len = c->get_cgroup_item(c, "cpuset.cpus", buf, 0);
|
||||||
|
if (len <= 0) {
|
||||||
|
fprintf(stderr, "%d: not able to get length of cpuset.cpus (ret %d)\n", __LINE__, len);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200);
|
||||||
|
if (len <= 0 || strcmp(buf, "0\n")) {
|
||||||
|
fprintf(stderr, "%d: not able to get cpuset.cpus (len %d buf %s)\n", __LINE__, len, buf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buf, "FROZEN");
|
||||||
|
b = c->set_cgroup_item(c, "freezer.state", buf);
|
||||||
|
if (!b) {
|
||||||
|
fprintf(stderr, "%d: not able to set freezer.state.\n", __LINE__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buf, "XXX");
|
||||||
|
len = c->get_cgroup_item(c, "freezer.state", buf, 200);
|
||||||
|
if (len <= 0 || (strcmp(buf, "FREEZING\n") && strcmp(buf, "FROZEN\n"))) {
|
||||||
|
fprintf(stderr, "%d: not able to get freezer.state (len %d buf %s)\n", __LINE__, len, buf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->set_cgroup_item(c, "freezer.state", "THAWED");
|
||||||
|
|
||||||
printf("hit return to finish");
|
printf("hit return to finish");
|
||||||
ret = scanf("%c", &mychar);
|
ret = scanf("%c", &mychar);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
c->stop(c);
|
c->stop(c);
|
||||||
|
|
||||||
|
/* feh - multilib has moved the lxc-init crap */
|
||||||
|
goto ok;
|
||||||
|
|
||||||
ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc");
|
ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc");
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/");
|
ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/");
|
||||||
@ -204,6 +250,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
// auto-check result? ('bobo' is printed on stdout)
|
// auto-check result? ('bobo' is printed on stdout)
|
||||||
|
|
||||||
|
ok:
|
||||||
fprintf(stderr, "all lxc_container tests passed for %s\n", c->name);
|
fprintf(stderr, "all lxc_container tests passed for %s\n", c->name);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user