From e0d940463475b907d56aa548401f8ba916cec21b Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 2 Jun 2020 14:02:54 -0400 Subject: Enable detached exec for remote The biggest obstacle here was cleanup - we needed a way to remove detached exec sessions after they exited, but there's no way to tell if an exec session will be attached or detached when it's created, and that's when we must add the exit command that would do the removal. The solution was adding a delay to the exit command (5 minutes), which gives sufficient time for attached exec sessions to retrieve the exit code of the session after it exits, but still guarantees that they will be removed, even for detached sessions. This requires Conmon 2.0.17, which has the new `--exit-delay` flag. As part of the exit command rework, we can drop the hack we were using to clean up exec sessions (remove them as part of inspect). This is a lot cleaner, and I'm a lot happier about it. Otherwise, this is just plumbing - we need a bindings call for detached exec, and that needed to be added to the tunnel mode backend for entities. Signed-off-by: Matthew Heon --- libpod/container_exec.go | 8 ++++++++ libpod/oci.go | 3 +++ libpod/oci_conmon_exec_linux.go | 4 +++- 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'libpod') diff --git a/libpod/container_exec.go b/libpod/container_exec.go index f2943b73c..a0e8904dc 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -69,6 +69,10 @@ type ExecConfig struct { // The ID of the exec session, and the ID of the container the exec // session is a part of (in that order). ExitCommand []string `json:"exitCommand,omitempty"` + // ExitCommandDelay is a delay (in seconds) between the container + // exiting, and the exit command being executed. If set to 0, there is + // no delay. If set, ExitCommand must also be set. + ExitCommandDelay uint `json:"exitCommandDelay,omitempty"` } // ExecSession contains information on a single exec session attached to a given @@ -165,6 +169,9 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) { if len(config.Command) == 0 { return "", errors.Wrapf(define.ErrInvalidArg, "must provide a non-empty command to start an exec session") } + if config.ExitCommandDelay > 0 && len(config.ExitCommand) == 0 { + return "", errors.Wrapf(define.ErrInvalidArg, "must provide a non-empty exit command if giving an exit command delay") + } // Verify that we are in a good state to continue if !c.ensureState(define.ContainerStateRunning) { @@ -984,6 +991,7 @@ func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) { opts.PreserveFDs = session.Config.PreserveFDs opts.DetachKeys = session.Config.DetachKeys opts.ExitCommand = session.Config.ExitCommand + opts.ExitCommandDelay = session.Config.ExitCommandDelay return opts, nil } diff --git a/libpod/oci.go b/libpod/oci.go index 7c5218319..684a7ba42 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -172,6 +172,9 @@ type ExecOptions struct { // ExitCommand is a command that will be run after the exec session // exits. ExitCommand []string + // ExitCommandDelay is a delay (in seconds) between the exec session + // exiting, and the exit command being invoked. + ExitCommandDelay uint } // HTTPAttachStreams informs the HTTPAttach endpoint which of the container's diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index 51819f90a..bc39100f8 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -421,12 +421,14 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex for _, arg := range options.ExitCommand[1:] { args = append(args, []string{"--exit-command-arg", arg}...) } + if options.ExitCommandDelay > 0 { + args = append(args, []string{"--exit-delay", fmt.Sprintf("%d", options.ExitCommandDelay)}...) + } } logrus.WithFields(logrus.Fields{ "args": args, }).Debugf("running conmon: %s", r.conmonPath) - // TODO: Need to pass this back so we can wait on it. execCmd := exec.Command(r.conmonPath, args...) // TODO: This is commented because it doesn't make much sense in HTTP -- cgit v1.2.3-54-g00ecf