conf: introduce lxc.rootfs.managed

This introduces a new config key lxc.rootfs.managed which can be used to indicate whether this LXC instance is managing the container storage. If LXC is not managing the storage then LXC will not modify the container storage. For example, an API call to c->destroy(c) will then run any destroy hooks but will not destroy the actual rootfs (Unless, of course, the hook does so behind LXC's back.). Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com> CC: Wolfgang Bumiller <w.bumiller@proxmox.com> CC: Stéphane Graber <stgraber@ubuntu.com> CC: Serge Hallyn <serge@hallyn.com> CC: 2xsec <dh48.jeong@samsung.com>
parent a3cf04da
...@@ -2760,6 +2760,7 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2760,6 +2760,7 @@ struct lxc_conf *lxc_conf_init(void)
free(new); free(new);
return NULL; return NULL;
} }
new->rootfs.managed = true;
new->logfd = -1; new->logfd = -1;
lxc_list_init(&new->cgroup); lxc_list_init(&new->cgroup);
lxc_list_init(&new->cgroup2); lxc_list_init(&new->cgroup2);
......
...@@ -154,6 +154,7 @@ struct lxc_tty_info { ...@@ -154,6 +154,7 @@ struct lxc_tty_info {
* @options : mount options * @options : mount options
* @mountflags : the portion of @options that are flags * @mountflags : the portion of @options that are flags
* @data : the porition of @options that are not flags * @data : the porition of @options that are not flags
* @managed : whether it is managed by LXC
*/ */
struct lxc_rootfs { struct lxc_rootfs {
char *path; char *path;
...@@ -162,6 +163,7 @@ struct lxc_rootfs { ...@@ -162,6 +163,7 @@ struct lxc_rootfs {
char *options; char *options;
unsigned long mountflags; unsigned long mountflags;
char *data; char *data;
bool managed;
}; };
/* /*
......
...@@ -141,6 +141,7 @@ lxc_config_define(no_new_privs); ...@@ -141,6 +141,7 @@ lxc_config_define(no_new_privs);
lxc_config_define(personality); lxc_config_define(personality);
lxc_config_define(prlimit); lxc_config_define(prlimit);
lxc_config_define(pty_max); lxc_config_define(pty_max);
lxc_config_define(rootfs_managed);
lxc_config_define(rootfs_mount); lxc_config_define(rootfs_mount);
lxc_config_define(rootfs_options); lxc_config_define(rootfs_options);
lxc_config_define(rootfs_path); lxc_config_define(rootfs_path);
...@@ -226,6 +227,7 @@ static struct lxc_config_t config[] = { ...@@ -226,6 +227,7 @@ static struct lxc_config_t config[] = {
{ "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, }, { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
{ "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, }, { "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, },
{ "lxc.pty.max", set_config_pty_max, get_config_pty_max, clr_config_pty_max, }, { "lxc.pty.max", set_config_pty_max, get_config_pty_max, clr_config_pty_max, },
{ "lxc.rootfs.managed", set_config_rootfs_managed, get_config_rootfs_managed, clr_config_rootfs_managed, },
{ "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, }, { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, },
{ "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, }, { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, },
{ "lxc.rootfs.path", set_config_rootfs_path, get_config_rootfs_path, clr_config_rootfs_path, }, { "lxc.rootfs.path", set_config_rootfs_path, get_config_rootfs_path, clr_config_rootfs_path, },
...@@ -2134,6 +2136,31 @@ static int set_config_rootfs_path(const char *key, const char *value, ...@@ -2134,6 +2136,31 @@ static int set_config_rootfs_path(const char *key, const char *value,
return ret; return ret;
} }
static int set_config_rootfs_managed(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
unsigned int val = 0;
if (lxc_config_value_empty(value)) {
lxc_conf->rootfs.managed = true;
return 0;
}
if (lxc_safe_uint(value, &val) < 0)
return -EINVAL;
switch (val) {
case 0:
lxc_conf->rootfs.managed = false;
return 0;
case 1:
lxc_conf->rootfs.managed = true;
return 0;
}
return -EINVAL;
}
static int set_config_rootfs_mount(const char *key, const char *value, static int set_config_rootfs_mount(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
...@@ -3356,6 +3383,12 @@ static int get_config_rootfs_path(const char *key, char *retv, int inlen, ...@@ -3356,6 +3383,12 @@ static int get_config_rootfs_path(const char *key, char *retv, int inlen,
return lxc_get_conf_str(retv, inlen, c->rootfs.path); return lxc_get_conf_str(retv, inlen, c->rootfs.path);
} }
static int get_config_rootfs_managed(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
return lxc_get_conf_bool(c, retv, inlen, c->rootfs.managed);
}
static int get_config_rootfs_mount(const char *key, char *retv, int inlen, static int get_config_rootfs_mount(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
...@@ -3976,6 +4009,13 @@ static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c, ...@@ -3976,6 +4009,13 @@ static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c,
return 0; return 0;
} }
static inline int clr_config_rootfs_managed(const char *key, struct lxc_conf *c,
void *data)
{
c->rootfs.managed = true;
return 0;
}
static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c, static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c,
void *data) void *data)
{ {
......
...@@ -672,6 +672,21 @@ int lxc_get_conf_str(char *retv, int inlen, const char *value) ...@@ -672,6 +672,21 @@ int lxc_get_conf_str(char *retv, int inlen, const char *value)
return value_len; return value_len;
} }
int lxc_get_conf_bool(struct lxc_conf *c, char *retv, int inlen, bool v)
{
int len;
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
strprint(retv, inlen, "%d", v);
return fulllen;
}
int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v) int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
{ {
int len; int len;
......
...@@ -86,6 +86,7 @@ extern bool lxc_config_net_hwaddr(const char *line); ...@@ -86,6 +86,7 @@ extern bool lxc_config_net_hwaddr(const char *line);
extern void update_hwaddr(const char *line); extern void update_hwaddr(const char *line);
extern bool new_hwaddr(char *hwaddr); extern bool new_hwaddr(char *hwaddr);
extern int lxc_get_conf_str(char *retv, int inlen, const char *value); extern int lxc_get_conf_str(char *retv, int inlen, const char *value);
extern int lxc_get_conf_bool(struct lxc_conf *c, char *retv, int inlen, bool v);
extern int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v); extern int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v);
extern int lxc_get_conf_size_t(struct lxc_conf *c, char *retv, int inlen, size_t v); extern int lxc_get_conf_size_t(struct lxc_conf *c, char *retv, int inlen, size_t v);
extern int lxc_get_conf_uint64(struct lxc_conf *c, char *retv, int inlen, uint64_t v); extern int lxc_get_conf_uint64(struct lxc_conf *c, char *retv, int inlen, uint64_t v);
......
...@@ -2973,6 +2973,10 @@ static bool container_destroy(struct lxc_container *c, ...@@ -2973,6 +2973,10 @@ static bool container_destroy(struct lxc_container *c,
} }
} }
/* LXC is not managing the storage of the container. */
if (conf && !conf->rootfs.managed)
goto on_success;
if (conf && conf->rootfs.path && conf->rootfs.mount) { if (conf && conf->rootfs.path && conf->rootfs.mount) {
if (!do_destroy_container(conf)) { if (!do_destroy_container(conf)) {
ERROR("Error destroying rootfs for %s", c->name); ERROR("Error destroying rootfs for %s", c->name);
...@@ -3045,6 +3049,7 @@ static bool container_destroy(struct lxc_container *c, ...@@ -3045,6 +3049,7 @@ static bool container_destroy(struct lxc_container *c,
} }
INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name); INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name);
on_success:
bret = true; bret = true;
out: out:
...@@ -3060,14 +3065,16 @@ static bool do_lxcapi_destroy(struct lxc_container *c) ...@@ -3060,14 +3065,16 @@ static bool do_lxcapi_destroy(struct lxc_container *c)
if (!c || !lxcapi_is_defined(c)) if (!c || !lxcapi_is_defined(c))
return false; return false;
if (has_snapshots(c)) { if (c->lxc_conf && c->lxc_conf->rootfs.managed) {
ERROR("Container %s has snapshots; not removing", c->name); if (has_snapshots(c)) {
return false; ERROR("Container %s has snapshots; not removing", c->name);
} return false;
}
if (has_fs_snapshots(c)) { if (has_fs_snapshots(c)) {
ERROR("container %s has snapshots on its rootfs", c->name); ERROR("container %s has snapshots on its rootfs", c->name);
return false; return false;
}
} }
return container_destroy(c, NULL); return container_destroy(c, NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment