diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_api.go | 13 | ||||
-rw-r--r-- | libpod/container_internal.go | 21 | ||||
-rw-r--r-- | libpod/define/exec_codes.go | 18 | ||||
-rw-r--r-- | libpod/networking_linux.go | 11 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 7 | ||||
-rw-r--r-- | libpod/pod_api.go | 12 |
6 files changed, 73 insertions, 9 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go index 9bf97c5d4..4f0d5301c 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -216,8 +216,8 @@ func (c *Container) Kill(signal uint) error { } // Exec starts a new process inside the container -// Returns an exit code and an error. If Exec was not able to exec in the container before a failure, an exit code of 126 is returned. -// If another generic error happens, an exit code of 125 is returned. +// Returns an exit code and an error. If Exec was not able to exec in the container before a failure, an exit code of define.ExecErrorCodeCannotInvoke is returned. +// If another generic error happens, an exit code of define.ExecErrorCodeGeneric is returned. // Sometimes, the $RUNTIME exec call errors, and if that is the case, the exit code is the exit code of the call. // Otherwise, the exit code will be the exit code of the executed call inside of the container. // TODO investigate allowing exec without attaching @@ -821,3 +821,12 @@ func (c *Container) Restore(ctx context.Context, options ContainerCheckpointOpti defer c.newContainerEvent(events.Restore) return c.restore(ctx, options) } + +// AutoRemove indicates whether the container will be removed after it is executed +func (c *Container) AutoRemove() bool { + spec := c.config.Spec + if spec.Annotations == nil { + return false + } + return c.Spec().Annotations[InspectAnnotationAutoremove] == InspectResponseTrue +} diff --git a/libpod/container_internal.go b/libpod/container_internal.go index ac565fdad..6bf8439da 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -14,6 +14,7 @@ import ( "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" + "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/ctime" "github.com/containers/libpod/pkg/hooks" "github.com/containers/libpod/pkg/hooks/exec" @@ -163,7 +164,15 @@ func (c *Container) createExecBundle(sessionID string) (err error) { // cleanup an exec session after its done func (c *Container) cleanupExecBundle(sessionID string) error { - return os.RemoveAll(c.execBundlePath(sessionID)) + if err := os.RemoveAll(c.execBundlePath(sessionID)); err != nil && !os.IsNotExist(err) { + return err + } + // Clean up the sockets dir. Issue #3962 + // Also ignore if it doesn't exist for some reason; hence the conditional return below + if err := os.RemoveAll(filepath.Join(c.ociRuntime.socketsDir, sessionID)); err != nil && !os.IsNotExist(err) { + return err + } + return nil } // the path to a containers exec session bundle @@ -1124,6 +1133,16 @@ func (c *Container) pause() error { return errors.Wrapf(define.ErrNoCgroups, "cannot pause without using CGroups") } + if rootless.IsRootless() { + cgroupv2, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return errors.Wrap(err, "failed to determine cgroupversion") + } + if !cgroupv2 { + return errors.Wrap(define.ErrNoCgroups, "can not pause containers on rootless containers with cgroup V1") + } + } + if err := c.ociRuntime.pauseContainer(c); err != nil { return err } diff --git a/libpod/define/exec_codes.go b/libpod/define/exec_codes.go index 7184f1e59..33d631326 100644 --- a/libpod/define/exec_codes.go +++ b/libpod/define/exec_codes.go @@ -1,6 +1,8 @@ package define import ( + "strings" + "github.com/pkg/errors" ) @@ -28,3 +30,19 @@ func TranslateExecErrorToExitCode(originalEC int, err error) int { } return originalEC } + +// ExitCode reads the error message when failing to executing container process +// and then returns 0 if no error, ExecErrorCodeNotFound if command does not exist, or ExecErrorCodeCannotInvoke for +// all other errors +func ExitCode(err error) int { + if err == nil { + return 0 + } + e := strings.ToLower(err.Error()) + if strings.Contains(e, "file not found") || + strings.Contains(e, "no such file or directory") { + return ExecErrorCodeNotFound + } + + return ExecErrorCodeCannotInvoke +} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index fd14b2f73..67dd0150b 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -127,13 +127,13 @@ type slirp4netnsCmd struct { Args slirp4netnsCmdArg `json:"arguments"` } -func checkSlirpFlags(path string) (bool, bool, error) { +func checkSlirpFlags(path string) (bool, bool, bool, error) { cmd := exec.Command(path, "--help") out, err := cmd.CombinedOutput() if err != nil { - return false, false, err + return false, false, false, err } - return strings.Contains(string(out), "--disable-host-loopback"), strings.Contains(string(out), "--mtu"), nil + return strings.Contains(string(out), "--disable-host-loopback"), strings.Contains(string(out), "--mtu"), strings.Contains(string(out), "--enable-sandbox"), nil } // Configure the network namespace for a rootless container @@ -166,7 +166,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { if havePortMapping { cmdArgs = append(cmdArgs, "--api-socket", apiSocket, fmt.Sprintf("%d", ctr.state.PID)) } - dhp, mtu, err := checkSlirpFlags(path) + dhp, mtu, sandbox, err := checkSlirpFlags(path) if err != nil { return errors.Wrapf(err, "error checking slirp4netns binary %s", path) } @@ -176,6 +176,9 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { if mtu { cmdArgs = append(cmdArgs, "--mtu", "65520") } + if sandbox { + cmdArgs = append(cmdArgs, "--enable-sandbox") + } cmdArgs = append(cmdArgs, "-c", "-e", "3", "-r", "4", fmt.Sprintf("%d", ctr.state.PID), "tap0") cmd := exec.Command(path, cmdArgs...) diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index 22afa7416..6cada0801 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -107,8 +107,6 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c logrus.Debugf("Attaching to container %s exec session %s", c.ID(), sessionID) - registerResizeFunc(resize, c.execBundlePath(sessionID)) - // set up the socket path, such that it is the correct length and location for exec socketPath := buildSocketPath(c.execAttachSocketPath(sessionID)) @@ -116,6 +114,7 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c if _, err := readConmonPipeData(attachFd, ""); err != nil { return err } + // 2: then attach conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) if err != nil { @@ -127,6 +126,10 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c } }() + // Register the resize func after we've read the attach socket, as we know at this point the + // 'ctl' file has been created in conmon + registerResizeFunc(resize, c.execBundlePath(sessionID)) + // start listening on stdio of the process receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys) diff --git a/libpod/pod_api.go b/libpod/pod_api.go index e2448e92a..7c786b835 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -5,6 +5,8 @@ import ( "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -163,6 +165,16 @@ func (p *Pod) Pause() (map[string]error, error) { return nil, define.ErrPodRemoved } + if rootless.IsRootless() { + cgroupv2, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return nil, errors.Wrap(err, "failed to determine cgroupversion") + } + if !cgroupv2 { + return nil, errors.Wrap(define.ErrNoCgroups, "can not pause pods containing rootless containers with cgroup V1") + } + } + allCtrs, err := p.runtime.state.PodContainers(p) if err != nil { return nil, err |