<p dir="ltr">Consider it done. :)</p>
<div class="gmail_quote">On Sep 4, 2015 7:47 PM, "Stéphane Graber" <<a href="mailto:stgraber@ubuntu.com">stgraber@ubuntu.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Fri, Sep 04, 2015 at 07:42:50PM +0200, Christian Brauner wrote:<br>
> On Fri, Sep 04, 2015 at 01:11:14PM -0400, Stéphane Graber wrote:<br>
> > On Fri, Sep 04, 2015 at 04:21:42PM +0200, Christian Brauner wrote:<br>
> > > On Fri, Sep 04, 2015 at 02:04:29PM +0000, Serge Hallyn wrote:<br>
> > > > Quoting Christian Brauner (<a href="mailto:christianvanbrauner@gmail.com">christianvanbrauner@gmail.com</a>):<br>
> > > > > On Mon, Aug 31, 2015 at 09:53:03PM +0200, Christian Brauner wrote:<br>
> > > > > > On Mon Aug 31, 2015 at 04:08:33PM +0000, Serge Hallyn wrote:<br>
> > > > > > > Quoting Stéphane Graber (stgraber at <a href="http://ubuntu.com" rel="noreferrer" target="_blank">ubuntu.com</a>):<br>
> > > > > > > > On Mon, Aug 31, 2015 at 01:43:07PM +0000, Serge Hallyn wrote:<br>
> > > > > > > > > Quoting Christian Brauner (christianvanbrauner at <a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a>):<br>
> > > > > > > > > > On Fri, Aug 28, 2015 at 12:46:17AM +0200, Christian Brauner wrote:<br>
> > > > > > > > > > > On Thu, Aug 27, 2015 at 03:41:03PM -0400, Stéphane Graber wrote:<br>
> > > > > > > > > > > > On Sun, Aug 16, 2015 at 04:46:31PM +0000, Serge Hallyn wrote:<br>
> > > > > > > > > > > > > Quoting Christian Brauner (christianvanbrauner at <a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a>):<br>
> > > > > > > > > > > > > Hey,<br>
> > > > > > > > > > > > ><br>
> > > > > > > > > > > > > I'll leave this to Stéphane, as he's pretty keen on leaving the #<br>
> > > > > > > > > > > > > commands<br>
> > > > > > > > > > > > > low. As you say we might eventually be able to deprecate<br>
> > > > > > > > > > > > > lxc-clone,<br>
> > > > > > > > > > > > > and<br>
> > > > > > > > > > > > > lxc-copy might eventually be a nice hook for migration.<br>
> > > > > > > > > > > ><br>
> > > > > > > > > > > > That'd be fine with me I think, bonus point if we can somehow merge<br>
> > > > > > > > > > > > lxc-start-ephemeral in there and kill two birds with one stone<br>
> > > > > > > > > > > > (lxc-clone & lxc-start-ephemeral).<br>
> > > > > > > > > > > ><br>
> > > > > > > > > > > > The timeline for this would be having lxc-copy in 1.2 with both<br>
> > > > > > > > > > > > lxc-clone and lxc-start-ephemeral doing arg swapping + re-exec<br>
> > > > > > > > > > > > tricks<br>
> > > > > > > > > > > > with a warning that they'll go away for good in 2.0.<br>
> > > > > > > > > > > ><br>
> > > > > > > > > > > > How does that sound?<br>
> > > > > > > > > > ><br>
> > > > > > > > > > > Sounds good! I'm on it!<br>
> > > > > > > > > > ><br>
> > > > > > > > > > > Christian<br>
> > > > > > > > > ><br>
> > > > > > > > > > In the current python implementation of lxc-start-ephemeral we generate<br>
> > > > > > > > > > a<br>
> > > > > > > > > > pre-mount and post-stop script. The post-stop script seems to be used to<br>
> > > > > > > > > > destroy<br>
> > > > > > > > > > the container. For the rewrite in C and the merge with lxc-clone I<br>
> > > > > > > > > > thought<br>
> > > > > > > > > > about<br>
> > > > > > > > > > using a simple snapshot-clone with c->clone() with a random name, start<br>
> > > > > > > > > > it<br>
> > > > > > > > > > c->start() and when the container is shutdown destroy it with<br>
> > > > > > > > > > c->destroy().<br>
> > > > > > > > > > This seems cleaner to me then generating scripts. Are there any reasons<br>
> > > > > > > > > > to<br>
> > > > > > > > > > not<br>
> > > > > > > > > > do it this way? And if so what would you prefer?<br>
> > > > > > > > ><br>
> > > > > > > > > If you can do this robustly and cleanly then I prefer this.<br>
> > > > > > > ><br>
> > > > > > > > The reason was that the container could be started backgrounded (-d) in<br>
> > > > > > > > which case lxc-start-ephemeral wasn't around anymore to clean things up<br>
> > > > > > > > when the container exits.<br>
> > > > > > > ><br>
> > > > > > > > The post-stop method ensured that the container would be destroyed<br>
> > > > > > > > whenever it finally dies and regardless of how it was killed (either<br>
> > > > > > > > shutdown from inside the container or lxc-stop/lxc-destroy).<br>
> > > > > > ><br>
> > > > > > > Right, so to do this without post-stop we'd probably have to hack a special<br>
> > > > > > > case into the reboot: loop around container-start. Maybe even hardcode the<br>
> > > > > > > 'transient' case into the lxc_handler struct. Or just have a 'special'<br>
> > > > > > > post-stop hook (doesn't even have to be a script, just a hard-code value<br>
> > > > > > > checked for before we run the script) telling us 'delete this thing'.<br>
> > > > > > ><br>
> > > > > > > It could end up looking nice, or could end up a mess. I reserve final<br>
> > > > > > > judgement until there's code :)<br>
> > > > > > Agreed. Let's see how mess-less I can code this.<br>
> > > > > ><br>
> > > > > > As long as the container is started in foreground mode the container will be<br>
> > > > > > destroyed regardless of whether it was killed by lxc-stop or shutdown from<br>
> > > > > > inside. The only problematic case is when the container is started daemonized.<br>
> > > > > ><br>
> > > > > > I need to think about how to handle that case for a bit. I'd like to code more<br>
> > > > > > than one option I think. Unless there's need for rush. :) Suggestions of course<br>
> > > > > > welcome.<br>
> > > > > I'm currently in favour of the lxc.hook.post-stop version for daemonized<br>
> > > > > containers. The rest means fiddling with a lot of the api-functions for the<br>
> > > > > a rather special case. But there are two things I would like to have input<br>
> > > > > about:<br>
> > > > ><br>
> > > > > 1) Should we register ephemeral clone-snapshots in the lxc_snapshots file of the<br>
> > > > > original container? (I would think not.)<br>
> > > ><br>
> > > > If for instance it is a overlayfs based snapshot, and you allow the parent<br>
> > > > to be deleted, then the ephemeral container will misbehave. I'm pretty<br>
> > > > sure that's the case now and I haven't heard any complaints, but it is<br>
> > > > non-ideal.<br>
> > > ><br>
> > > > > 2) Should we have an additional state TRANSIENT in addition to RUNNING,<br>
> > > > > STARTING, etc.?<br>
> > > ><br>
> > > > What exactly would it mean? STARTING is already inherently TRANSIENT. Would<br>
> > > > TRANSIENT mean 'building but not yet starting'?<br>
> > > I was unclear. TRANSIENT or EPHEMERAL in the sense of "this is a running<br>
> > > container but it will be deleted once it is shutdown". So when you do work on a<br>
> > > container and you're unsure whether it is an ephemeral container you could check<br>
> > > with lxc-info -n NAME and see TRANSIENT or EPHEMERAL and know "this thing is<br>
> > > going to be deleted when I shut it down."<br>
> ><br>
> > It seems to me like this has the potential to break a fair amount of<br>
> > existing tools which wait for "RUNNING" before interacting with a<br>
> > container. If we were to have multiple "RUNNING" equivalent state, we<br>
> > ought to add a new exported function that'd check whether the container<br>
> > is running regardless of the state's name but requiring the use of this<br>
> > would only be possible when we break backward compatibility (so LXC<br>
> > 2.0).<br>
><br>
> Agreed!.<br>
><br>
> ><br>
> > I suspect a cleaner way would be to have a config option for ephemeral<br>
> > containers, something like lxc.ephemeral=1 that will cause LXC to<br>
> > destroy the container when it dies and can be used by API clients to<br>
> > query whether a container is ephemeral.<br>
><br>
> I actually already done that. I just need to bring it in final shape. But here<br>
> is a sneak-preview so you can stop me if you'd rather have it a different way.<br>
> And thanks for all the feedback and quick answers!<br>
><br>
> PRELIMINARY: Destroy ephemeral overlayfs container<br>
<br>
I personally prefer ephemeral as a name, if only because that's what<br>
we've been using for years in both LXC and LXD, so one less thing to<br>
confuse people with :)<br>
<br>
><br>
> ---<br>
> src/lxc/conf.h | 3 +++<br>
> src/lxc/confile.c | 16 ++++++++++++++++<br>
> src/lxc/start.c | 14 ++++++++++++++<br>
> 3 files changed, 33 insertions(+)<br>
><br>
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h<br>
> index dc5328a..6e75713 100644<br>
> --- a/src/lxc/conf.h<br>
> +++ b/src/lxc/conf.h<br>
> @@ -370,6 +370,9 @@ struct lxc_conf {<br>
> * should run under when using lxc-execute */<br>
> uid_t init_uid;<br>
> gid_t init_gid;<br>
> +<br>
> + /* transient */<br>
> + int transient;<br>
> };<br>
><br>
> #ifdef HAVE_TLS<br>
> diff --git a/src/lxc/confile.c b/src/lxc/confile.c<br>
> index ca3b8d8..356d85f 100644<br>
> --- a/src/lxc/confile.c<br>
> +++ b/src/lxc/confile.c<br>
> @@ -108,6 +108,8 @@ static int config_environment(const char *, const char *, struct lxc_conf *);<br>
> static int config_init_cmd(const char *, const char *, struct lxc_conf *);<br>
> static int config_init_uid(const char *, const char *, struct lxc_conf *);<br>
> static int config_init_gid(const char *, const char *, struct lxc_conf *);<br>
> +static int config_transient(const char *key, const char *value,<br>
> + struct lxc_conf *lxc_conf);<br>
><br>
> static struct lxc_config_t config[] = {<br>
><br>
> @@ -176,6 +178,7 @@ static struct lxc_config_t config[] = {<br>
> { "lxc.init_cmd", config_init_cmd },<br>
> { "lxc.init_uid", config_init_uid },<br>
> { "lxc.init_gid", config_init_gid },<br>
> + { "lxc.transient", config_transient },<br>
> };<br>
><br>
> struct signame {<br>
> @@ -2490,6 +2493,8 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,<br>
> return lxc_get_conf_int(c, retv, inlen, c->init_uid);<br>
> else if (strcmp(key, "lxc.init_gid") == 0)<br>
> return lxc_get_conf_int(c, retv, inlen, c->init_gid);<br>
> + else if (strcmp(key, "lxc.transient") == 0)<br>
> + return lxc_get_conf_int(c, retv, inlen, c->transient);<br>
> else return -1;<br>
><br>
> if (!v)<br>
> @@ -2759,3 +2764,14 @@ bool network_new_hwaddrs(struct lxc_conf *conf)<br>
> }<br>
> return true;<br>
> }<br>
> +<br>
> +static int config_transient(const char *key, const char *value,<br>
> + struct lxc_conf *lxc_conf)<br>
> +{<br>
> + int v = atoi(value);<br>
> +<br>
> + lxc_conf->transient = v;<br>
> +<br>
> + return 0;<br>
> +}<br>
> +<br>
> diff --git a/src/lxc/start.c b/src/lxc/start.c<br>
> index ffb8d12..e551ca4 100644<br>
> --- a/src/lxc/start.c<br>
> +++ b/src/lxc/start.c<br>
> @@ -495,6 +495,20 @@ void lxc_fini(const char *name, struct lxc_handler *handler)<br>
> close(handler->ttysock[0]);<br>
> close(handler->ttysock[1]);<br>
> }<br>
> + if (handler->conf->transient > 0) {<br>
> + char *check_rootfs = handler->conf->rootfs.path;<br>
> + if (strncmp(check_rootfs, "overlayfs:", 10) == 0) {<br>
> + int ret;<br>
> + char destroy[MAXPATHLEN];<br>
> + ret = snprintf(destroy, MAXPATHLEN, "%s/%s", handler->lxcpath, name);<br>
> + if (ret < 0)<br>
> + ERROR("Error creating string");<br>
> + INFO(destroy);<br>
> + ret = lxc_rmdir_onedev(destroy, NULL);<br>
> + if (ret < 0)<br>
> + ERROR("Destroying container failed");<br>
> + }<br>
> + }<br>
> cgroup_destroy(handler);<br>
> free(handler);<br>
> }<br>
> --<br>
> 2.5.1<br>
><br>
<br>
<br>
<br>
--<br>
Stéphane Graber<br>
Ubuntu developer<br>
<a href="http://www.ubuntu.com" rel="noreferrer" target="_blank">http://www.ubuntu.com</a><br>
</blockquote></div>