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)
free(new);
return NULL;
}
new->rootfs.managed = true;
new->logfd = -1;
lxc_list_init(&new->cgroup);
lxc_list_init(&new->cgroup2);
......
......@@ -154,6 +154,7 @@ struct lxc_tty_info {
* @options : mount options
* @mountflags : the portion of @options that are flags
* @data : the porition of @options that are not flags
* @managed : whether it is managed by LXC
*/
struct lxc_rootfs {
char *path;
......@@ -162,6 +163,7 @@ struct lxc_rootfs {
char *options;
unsigned long mountflags;
char *data;
bool managed;
};
/*
......
......@@ -141,6 +141,7 @@ lxc_config_define(no_new_privs);
lxc_config_define(personality);
lxc_config_define(prlimit);
lxc_config_define(pty_max);
lxc_config_define(rootfs_managed);
lxc_config_define(rootfs_mount);
lxc_config_define(rootfs_options);
lxc_config_define(rootfs_path);
......@@ -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.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.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.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, },
......@@ -2134,6 +2136,31 @@ static int set_config_rootfs_path(const char *key, const char *value,
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,
struct lxc_conf *lxc_conf, void *data)
{
......@@ -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);
}
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,
struct lxc_conf *c, void *data)
{
......@@ -3976,6 +4009,13 @@ static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c,
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,
void *data)
{
......
......@@ -672,6 +672,21 @@ int lxc_get_conf_str(char *retv, int inlen, const char *value)
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 len;
......
......@@ -86,6 +86,7 @@ extern bool lxc_config_net_hwaddr(const char *line);
extern void update_hwaddr(const char *line);
extern bool new_hwaddr(char *hwaddr);
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_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);
......
......@@ -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 (!do_destroy_container(conf)) {
ERROR("Error destroying rootfs for %s", c->name);
......@@ -3045,6 +3049,7 @@ static bool container_destroy(struct lxc_container *c,
}
INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name);
on_success:
bret = true;
out:
......@@ -3060,14 +3065,16 @@ static bool do_lxcapi_destroy(struct lxc_container *c)
if (!c || !lxcapi_is_defined(c))
return false;
if (has_snapshots(c)) {
ERROR("Container %s has snapshots; not removing", c->name);
return false;
}
if (c->lxc_conf && c->lxc_conf->rootfs.managed) {
if (has_snapshots(c)) {
ERROR("Container %s has snapshots; not removing", c->name);
return false;
}
if (has_fs_snapshots(c)) {
ERROR("container %s has snapshots on its rootfs", c->name);
return false;
if (has_fs_snapshots(c)) {
ERROR("container %s has snapshots on its rootfs", c->name);
return false;
}
}
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