diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_api.go | 35 | ||||
-rw-r--r-- | libpod/container_internal.go | 22 | ||||
-rw-r--r-- | libpod/container_log_linux.go | 2 | ||||
-rw-r--r-- | libpod/define/exec_codes.go | 6 | ||||
-rw-r--r-- | libpod/events/journal_linux.go | 4 | ||||
-rw-r--r-- | libpod/healthcheck_linux.go | 4 | ||||
-rw-r--r-- | libpod/image/image.go | 33 | ||||
-rw-r--r-- | libpod/kube.go | 23 | ||||
-rw-r--r-- | libpod/logs/log.go | 3 | ||||
-rw-r--r-- | libpod/oci.go | 9 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 4 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 86 | ||||
-rw-r--r-- | libpod/oci_missing.go | 4 | ||||
-rw-r--r-- | libpod/reset.go | 13 | ||||
-rw-r--r-- | libpod/runtime_pod_infra_linux.go | 2 |
15 files changed, 129 insertions, 121 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go index 5e8fcea47..039619ea6 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -282,24 +282,13 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri opts.Resize = resize opts.DetachKeys = detachKeys - pid := 0 - pipeDataChan, attachChan, err := c.ociRuntime.ExecContainer(c, sessionID, opts) - // if pipeDataChan isn't nil, we should set the err - if pipeDataChan != nil { - pidData := <-pipeDataChan - if pidData.err != nil { - err = pidData.err - } - pid = pidData.data - } + pid, attachChan, err := c.ociRuntime.ExecContainer(c, sessionID, opts) if err != nil { ec := define.ExecErrorCodeGeneric // Conmon will pass a non-zero exit code from the runtime as a pid here. // we differentiate a pid with an exit code by sending it as negative, so reverse // that change and return the exit code the runtime failed with. - // Make sure the value is not ErrorConmonRead, as that is a podman set bogus value - // and not sent by conmon (and thus has no special meaning) - if pid < 0 && pid != define.ErrorConmonRead { + if pid < 0 { ec = -1 * pid } return ec, err @@ -329,24 +318,18 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri lastErr := <-attachChan - exitCodeData := <-pipeDataChan - if exitCodeData.err != nil { + exitCode, err := c.readExecExitCode(sessionID) + if err != nil { if lastErr != nil { logrus.Errorf(lastErr.Error()) } - lastErr = exitCodeData.err + lastErr = err } - if exitCodeData.data != 0 { + if exitCode != 0 { if lastErr != nil { logrus.Errorf(lastErr.Error()) } - // ErrorConmonRead is a bogus value set by podman to indicate reading a value from - // conmon failed. Since it is specifically not a valid exit code, we should set - // a generic error here - if exitCodeData.data == define.ErrorConmonRead { - exitCodeData.data = define.ExecErrorCodeGeneric - } - lastErr = errors.Wrapf(define.ErrOCIRuntime, "non zero exit code: %d", exitCodeData.data) + lastErr = errors.Wrapf(define.ErrOCIRuntime, "non zero exit code: %d", exitCode) } // Lock again @@ -357,7 +340,7 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri // Sync the container again to pick up changes in state if err := c.syncContainer(); err != nil { logrus.Errorf("error syncing container %s state to remove exec session %s", c.ID(), sessionID) - return exitCodeData.data, lastErr + return exitCode, lastErr } // Remove the exec session from state @@ -365,7 +348,7 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri if err := c.save(); err != nil { logrus.Errorf("Error removing exec session %s from container %s state: %v", sessionID, c.ID(), err) } - return exitCodeData.data, lastErr + return exitCode, lastErr } // AttachStreams contains streams that will be attached to the container diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 60b13f125..a0805c1fa 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -206,6 +206,28 @@ func (c *Container) execOCILog(sessionID string) string { return filepath.Join(c.execBundlePath(sessionID), "oci-log") } +// readExecExitCode reads the exit file for an exec session and returns +// the exit code +func (c *Container) readExecExitCode(sessionID string) (int, error) { + exitFile := filepath.Join(c.execExitFileDir(sessionID), c.ID()) + chWait := make(chan error) + defer close(chWait) + + _, err := WaitForFile(exitFile, chWait, time.Second*5) + if err != nil { + return -1, err + } + ec, err := ioutil.ReadFile(exitFile) + if err != nil { + return -1, err + } + ecInt, err := strconv.Atoi(string(ec)) + if err != nil { + return -1, err + } + return ecInt, nil +} + // Wait for the container's exit file to appear. // When it does, update our state based on it. func (c *Container) waitForExitFileAndSync() error { diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index 748715ed3..03010d8ed 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -11,7 +11,7 @@ import ( "time" "github.com/containers/libpod/libpod/logs" - journal "github.com/coreos/go-systemd/sdjournal" + journal "github.com/coreos/go-systemd/v22/sdjournal" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/libpod/define/exec_codes.go b/libpod/define/exec_codes.go index c2ec08666..f94616b33 100644 --- a/libpod/define/exec_codes.go +++ b/libpod/define/exec_codes.go @@ -1,7 +1,6 @@ package define import ( - "math" "strings" "github.com/pkg/errors" @@ -18,11 +17,6 @@ const ( ExecErrorCodeCannotInvoke = 126 // ExecErrorCodeNotFound is the error code to return when a command cannot be found ExecErrorCodeNotFound = 127 - // ErrorConmonRead is a bogus value that can neither be a valid PID or exit code. It is - // used because conmon will send a negative value when sending a PID back over a pipe FD - // to signify something went wrong in the runtime. We need to differentiate between that - // value and a failure on the podman side of reading that value. Thus, we use ErrorConmonRead - ErrorConmonRead = math.MinInt32 - 1 ) // TranslateExecErrorToExitCode takes an error and checks whether it diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go index 9e6fffc29..482435038 100644 --- a/libpod/events/journal_linux.go +++ b/libpod/events/journal_linux.go @@ -7,8 +7,8 @@ import ( "strconv" "time" - "github.com/coreos/go-systemd/journal" - "github.com/coreos/go-systemd/sdjournal" + "github.com/coreos/go-systemd/v22/journal" + "github.com/coreos/go-systemd/v22/sdjournal" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go index dca72430d..5da2d311b 100644 --- a/libpod/healthcheck_linux.go +++ b/libpod/healthcheck_linux.go @@ -9,8 +9,8 @@ import ( "strings" "github.com/containers/libpod/pkg/rootless" - "github.com/coreos/go-systemd/dbus" - godbus "github.com/godbus/dbus" + "github.com/coreos/go-systemd/v22/dbus" + godbus "github.com/godbus/dbus/v5" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/libpod/image/image.go b/libpod/image/image.go index 43fd52a1a..5f914ed79 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -916,12 +916,7 @@ func (i *Image) imageInspectInfo(ctx context.Context) (*types.ImageInspectInfo, return i.inspectInfo, nil } -// Inspect returns an image's inspect data -func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { - span, _ := opentracing.StartSpanFromContext(ctx, "imageInspect") - span.SetTag("type", "image") - defer span.Finish() - +func (i *Image) inspect(ctx context.Context, calculateSize bool) (*inspect.ImageData, error) { ociv1Img, err := i.ociv1Image(ctx) if err != nil { ociv1Img = &ociv1.Image{} @@ -936,8 +931,10 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { } size := int64(-1) - if usize, err := i.Size(ctx); err == nil { - size = int64(*usize) + if calculateSize { + if usize, err := i.Size(ctx); err == nil { + size = int64(*usize) + } } repoTags, err := i.RepoTags() @@ -1002,6 +999,26 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { return data, nil } +// Inspect returns an image's inspect data +func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { + span, _ := opentracing.StartSpanFromContext(ctx, "imageInspect") + + span.SetTag("type", "image") + defer span.Finish() + + return i.inspect(ctx, true) +} + +// InspectNoSize returns an image's inspect data without calculating the size for the image +func (i *Image) InspectNoSize(ctx context.Context) (*inspect.ImageData, error) { + span, _ := opentracing.StartSpanFromContext(ctx, "imageInspectNoSize") + + span.SetTag("type", "image") + defer span.Finish() + + return i.inspect(ctx, false) +} + // Import imports and image into the store and returns an image func (ir *Runtime) Import(ctx context.Context, path, reference string, writer io.Writer, signingOptions SigningOptions, imageConfig ociv1.Image) (*Image, error) { src, err := tarball.Transport.ParseReference(path) diff --git a/libpod/kube.go b/libpod/kube.go index 7a5ab670d..5511d303d 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -468,11 +468,26 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) { return nil, err } + var selinuxOpts v1.SELinuxOptions + opts := strings.SplitN(c.config.Spec.Annotations[InspectAnnotationLabel], ":", 2) + if len(opts) == 2 { + switch opts[0] { + case "type": + selinuxOpts.Type = opts[1] + case "level": + selinuxOpts.Level = opts[1] + } + } + if len(opts) == 1 { + if opts[0] == "disable" { + selinuxOpts.Type = "spc_t" + } + } + sc := v1.SecurityContext{ - Capabilities: newCaps, - Privileged: &priv, - // TODO How do we know if selinux were passed into podman - //SELinuxOptions: + Capabilities: newCaps, + Privileged: &priv, + SELinuxOptions: &selinuxOpts, // RunAsNonRoot is an optional parameter; our first implementations should be root only; however // I'm leaving this as a bread-crumb for later //RunAsNonRoot: &nonRoot, diff --git a/libpod/logs/log.go b/libpod/logs/log.go index 200ef3e99..6ad2a305f 100644 --- a/libpod/logs/log.go +++ b/libpod/logs/log.go @@ -167,8 +167,7 @@ func (l *LogLine) String(options *LogOptions) string { var out string if options.Multi { if options.UseName { - cname := l.CName - out = fmt.Sprintf("%s ", cname) + out = l.CName + " " } else { cid := l.CID if len(cid) > 12 { diff --git a/libpod/oci.go b/libpod/oci.go index 41d420664..27edebefc 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -70,7 +70,7 @@ type OCIRuntime interface { // ExecContainer executes a command in a running container. // Returns an int (exit code), error channel (errors from attach), and // error (errors that occurred attempting to start the exec session). - ExecContainer(ctr *Container, sessionID string, options *ExecOptions) (chan DataAndErr, chan error, error) + ExecContainer(ctr *Container, sessionID string, options *ExecOptions) (int, chan error, error) // ExecStopContainer stops a given exec session in a running container. // SIGTERM with be sent initially, then SIGKILL after the given timeout. // If timeout is 0, SIGKILL will be sent immediately, and SIGTERM will @@ -159,10 +159,3 @@ type HTTPAttachStreams struct { Stdout bool Stderr bool } - -// DataAndErr is a generic structure for passing around an int and an error -// it is especially useful for getting information from conmon -type DataAndErr struct { - data int - err error -} diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index 5a8198d05..46c70e7eb 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -119,8 +119,8 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c socketPath := buildSocketPath(sockPath) // 2: read from attachFd that the parent process has set up the console socket - if pipeData := readConmonPipeData(attachFd, ""); pipeData.err != nil { - return pipeData.err + if _, err := readConmonPipeData(attachFd, ""); err != nil { + return err } // 2: then attach diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index f260e3a39..a5530e448 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -30,7 +30,7 @@ import ( "github.com/containers/libpod/pkg/util" "github.com/containers/libpod/utils" pmount "github.com/containers/storage/pkg/mount" - "github.com/coreos/go-systemd/activation" + "github.com/coreos/go-systemd/v22/activation" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux" "github.com/opencontainers/selinux/go-selinux/label" @@ -595,29 +595,31 @@ func (r *ConmonOCIRuntime) AttachResize(ctr *Container, newSize remotecommand.Te // ExecContainer executes a command in a running container // TODO: Split into Create/Start/Attach/Wait -func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options *ExecOptions) (chan DataAndErr, chan error, error) { +func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options *ExecOptions) (int, chan error, error) { if options == nil { - return nil, nil, errors.Wrapf(define.ErrInvalidArg, "must provide an ExecOptions struct to ExecContainer") + return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide an ExecOptions struct to ExecContainer") } if len(options.Cmd) == 0 { - return nil, nil, errors.Wrapf(define.ErrInvalidArg, "must provide a command to execute") + return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide a command to execute") } if sessionID == "" { - return nil, nil, errors.Wrapf(define.ErrEmptyID, "must provide a session ID for exec") + return -1, nil, errors.Wrapf(define.ErrEmptyID, "must provide a session ID for exec") } // create sync pipe to receive the pid parentSyncPipe, childSyncPipe, err := newPipe() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating socket pair") + return -1, nil, errors.Wrapf(err, "error creating socket pair") } + defer errorhandling.CloseQuiet(parentSyncPipe) + // create start pipe to set the cgroup before running // attachToExec is responsible for closing parentStartPipe childStartPipe, parentStartPipe, err := newPipe() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating socket pair") + return -1, nil, errors.Wrapf(err, "error creating socket pair") } // We want to make sure we close the parent{Start,Attach}Pipes if we fail @@ -636,7 +638,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options // attachToExec is responsible for closing parentAttachPipe parentAttachPipe, childAttachPipe, err := newPipe() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating socket pair") + return -1, nil, errors.Wrapf(err, "error creating socket pair") } defer func() { @@ -656,7 +658,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options runtimeDir, err := util.GetRuntimeDir() if err != nil { - return nil, nil, err + return -1, nil, err } finalEnv := make([]string, 0, len(options.Env)) @@ -666,7 +668,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options processFile, err := prepareProcessExec(c, options.Cmd, finalEnv, options.Terminal, options.Cwd, options.User, sessionID) if err != nil { - return nil, nil, err + return -1, nil, err } var ociLog string @@ -715,7 +717,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options conmonEnv, extraFiles, err := r.configureConmonEnv(runtimeDir) if err != nil { - return nil, nil, err + return -1, nil, err } if options.PreserveFDs > 0 { @@ -746,10 +748,10 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options childrenClosed = true if err != nil { - return nil, nil, errors.Wrapf(err, "cannot start container %s", c.ID()) + return -1, nil, errors.Wrapf(err, "cannot start container %s", c.ID()) } if err := r.moveConmonToCgroupAndSignal(c, execCmd, parentStartPipe); err != nil { - return nil, nil, err + return -1, nil, err } if options.PreserveFDs > 0 { @@ -772,16 +774,9 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options }() attachToExecCalled = true - dataChan := make(chan DataAndErr) - go func() { - // read the exec pid - dataChan <- readConmonPipeData(parentSyncPipe, ociLog) - // read the exec exit code - dataChan <- readConmonPipeData(parentSyncPipe, ociLog) - errorhandling.CloseQuiet(parentSyncPipe) - }() + pid, err := readConmonPipeData(parentSyncPipe, ociLog) - return dataChan, attachChan, err + return pid, attachChan, err } // ExecStopContainer stops a given exec session in a running container. @@ -1211,14 +1206,14 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co return err } - pipeData := readConmonPipeData(parentSyncPipe, ociLog) - if pipeData.err != nil { + pid, err := readConmonPipeData(parentSyncPipe, ociLog) + if err != nil { if err2 := r.DeleteContainer(ctr); err2 != nil { logrus.Errorf("Error removing container %s from runtime after creation failed", ctr.ID()) } - return pipeData.err + return err } - ctr.state.PID = pipeData.data + ctr.state.PID = pid conmonPID, err := readConmonPidFile(ctr.config.ConmonPidFile) if err != nil { @@ -1530,7 +1525,7 @@ func readConmonPidFile(pidFile string) (int, error) { } // readConmonPipeData attempts to read a syncInfo struct from the pipe -func readConmonPipeData(pipe *os.File, ociLog string) DataAndErr { +func readConmonPipeData(pipe *os.File, ociLog string) (int, error) { // syncInfo is used to return data from monitor process to daemon type syncInfo struct { Data int `json:"data"` @@ -1557,7 +1552,7 @@ func readConmonPipeData(pipe *os.File, ociLog string) DataAndErr { ch <- syncStruct{si: si} }() - data := define.ErrorConmonRead + data := -1 select { case ss := <-ch: if ss.err != nil { @@ -1566,17 +1561,11 @@ func readConmonPipeData(pipe *os.File, ociLog string) DataAndErr { if err == nil { var ociErr ociError if err := json.Unmarshal(ociLogData, &ociErr); err == nil { - return DataAndErr{ - data: data, - err: getOCIRuntimeError(ociErr.Msg), - } + return -1, getOCIRuntimeError(ociErr.Msg) } } } - return DataAndErr{ - data: data, - err: errors.Wrapf(ss.err, "container create failed (no logs from conmon)"), - } + return -1, errors.Wrapf(ss.err, "container create failed (no logs from conmon)") } logrus.Debugf("Received: %d", ss.si.Data) if ss.si.Data < 0 { @@ -1585,36 +1574,21 @@ func readConmonPipeData(pipe *os.File, ociLog string) DataAndErr { if err == nil { var ociErr ociError if err := json.Unmarshal(ociLogData, &ociErr); err == nil { - return DataAndErr{ - data: ss.si.Data, - err: getOCIRuntimeError(ociErr.Msg), - } + return ss.si.Data, getOCIRuntimeError(ociErr.Msg) } } } // If we failed to parse the JSON errors, then print the output as it is if ss.si.Message != "" { - return DataAndErr{ - data: ss.si.Data, - err: getOCIRuntimeError(ss.si.Message), - } - } - return DataAndErr{ - data: ss.si.Data, - err: errors.Wrapf(define.ErrInternal, "container create failed"), + return ss.si.Data, getOCIRuntimeError(ss.si.Message) } + return ss.si.Data, errors.Wrapf(define.ErrInternal, "container create failed") } data = ss.si.Data case <-time.After(define.ContainerCreateTimeout): - return DataAndErr{ - data: data, - err: errors.Wrapf(define.ErrInternal, "container creation timeout"), - } - } - return DataAndErr{ - data: data, - err: nil, + return -1, errors.Wrapf(define.ErrInternal, "container creation timeout") } + return data, nil } // writeConmonPipeData writes nonse data to a pipe diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index 1b7c1979d..ff7eea625 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -121,8 +121,8 @@ func (r *MissingRuntime) AttachResize(ctr *Container, newSize remotecommand.Term } // ExecContainer is not available as the runtime is missing -func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions) (chan DataAndErr, chan error, error) { - return nil, nil, r.printError() +func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions) (int, chan error, error) { + return -1, nil, r.printError() } // ExecStopContainer is not available as the runtime is missing. diff --git a/libpod/reset.go b/libpod/reset.go index a35b476a4..ae0a0cde9 100644 --- a/libpod/reset.go +++ b/libpod/reset.go @@ -7,6 +7,7 @@ import ( "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -87,12 +88,22 @@ func (r *Runtime) Reset(ctx context.Context) error { } prevError = err } - if err := os.RemoveAll(r.config.TmpDir); err != nil { + + runtimeDir, err := util.GetRuntimeDir() + if err != nil { + return err + } + tempDir := r.config.TmpDir + if r.config.TmpDir == runtimeDir { + tempDir = filepath.Join(r.config.TmpDir, "containers") + } + if err := os.RemoveAll(tempDir); err != nil { if prevError != nil { logrus.Error(prevError) } prevError = err } + if rootless.IsRootless() { configPath := filepath.Join(os.Getenv("HOME"), ".config/containers") if err := os.RemoveAll(configPath); err != nil { diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index 27735a9b2..279cafa39 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -147,7 +147,7 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container, return nil, err } - data, err := newImage.Inspect(ctx) + data, err := newImage.InspectNoSize(ctx) if err != nil { return nil, err } |