diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_api.go | 5 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 19 | ||||
-rw-r--r-- | libpod/oci.go | 29 |
3 files changed, 41 insertions, 12 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go index 09d7f220d..6bef3c47d 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -203,9 +203,8 @@ func (c *Container) Kill(signal uint) error { } // Exec starts a new process inside the container -// TODO allow specifying streams to attach to // TODO investigate allowing exec without attaching -func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string) error { +func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams) error { var capList []string locked := false @@ -267,7 +266,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID) - execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID) + execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams) if err != nil { return errors.Wrapf(err, "error exec %s", c.ID()) } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index b074efa3a..0e9a5124e 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -472,10 +472,19 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr return nil } -func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) (err error) { - +func (c *Container) checkpointRestoreSupported() (err error) { if !criu.CheckForCriu() { - return errors.Errorf("checkpointing a container requires at least CRIU %d", criu.MinCriuVersion) + return errors.Errorf("Checkpoint/Restore requires at least CRIU %d", criu.MinCriuVersion) + } + if !c.runtime.ociRuntime.featureCheckCheckpointing() { + return errors.Errorf("Configured runtime does not support checkpoint/restore") + } + return nil +} + +func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) (err error) { + if err := c.checkpointRestoreSupported(); err != nil { + return err } if c.state.State != ContainerStateRunning { @@ -532,8 +541,8 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (err error) { - if !criu.CheckForCriu() { - return errors.Errorf("restoring a container requires at least CRIU %d", criu.MinCriuVersion) + if err := c.checkpointRestoreSupported(); err != nil { + return err } if (c.state.State != ContainerStateConfigured) && (c.state.State != ContainerStateExited) { diff --git a/libpod/oci.go b/libpod/oci.go index 26d2c6ef1..2b3cc5db5 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -733,7 +733,7 @@ func (r *OCIRuntime) unpauseContainer(ctr *Container) error { // TODO: Add --detach support // TODO: Convert to use conmon // TODO: add --pid-file and use that to generate exec session tracking -func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string) (*exec.Cmd, error) { +func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams) (*exec.Cmd, error) { if len(cmd) == 0 { return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute") } @@ -789,9 +789,17 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty logrus.Debugf("Starting runtime %s with following arguments: %v", r.path, args) execCmd := exec.Command(r.path, args...) - execCmd.Stdout = os.Stdout - execCmd.Stderr = os.Stderr - execCmd.Stdin = os.Stdin + + if streams.AttachOutput { + execCmd.Stdout = streams.OutputStream + } + if streams.AttachInput { + execCmd.Stdin = streams.InputStream + } + if streams.AttachError { + execCmd.Stderr = streams.ErrorStream + } + execCmd.Env = append(execCmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)) if err := execCmd.Start(); err != nil { @@ -890,3 +898,16 @@ func (r *OCIRuntime) checkpointContainer(ctr *Container, options ContainerCheckp args = append(args, ctr.ID()) return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...) } + +func (r *OCIRuntime) featureCheckCheckpointing() bool { + // Check if the runtime implements checkpointing. Currently only + // runc's checkpoint/restore implementation is supported. + cmd := exec.Command(r.path, "checkpoint", "-h") + if err := cmd.Start(); err != nil { + return false + } + if err := cmd.Wait(); err == nil { + return true + } + return false +} |