diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2017-11-21 13:44:22 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-11-21 20:09:09 +0000 |
commit | 8e76ebcf6e8925d5fa6a8c9ab517d665b44c7b63 (patch) | |
tree | cd9c15e37a00927ccd8c31b3cde40f46fe82b736 /libpod/oci.go | |
parent | 7b736e333315e6f533b9677712a0c2e037cc293b (diff) | |
download | podman-8e76ebcf6e8925d5fa6a8c9ab517d665b44c7b63.tar.gz podman-8e76ebcf6e8925d5fa6a8c9ab517d665b44c7b63.tar.bz2 podman-8e76ebcf6e8925d5fa6a8c9ab517d665b44c7b63.zip |
Add ability to update container status from runc
Wire this in to all state-bound container operations to ensure
syncronization of container state.
Also exposes PID of running containers via API.
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Closes: #56
Approved by: rhatdan
Diffstat (limited to 'libpod/oci.go')
-rw-r--r-- | libpod/oci.go | 92 |
1 files changed, 83 insertions, 9 deletions
diff --git a/libpod/oci.go b/libpod/oci.go index 9fa2d3788..3ad3fdd8e 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -4,9 +4,11 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "os" "os/exec" "path/filepath" + "strconv" "syscall" "time" @@ -15,6 +17,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" + kwait "k8s.io/apimachinery/pkg/util/wait" // TODO import these functions into libpod and remove the import // Trying to keep libpod from depending on CRI-O code @@ -255,19 +258,90 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string) error } // updateContainerStatus retrieves the current status of the container from the -// runtime -// remove nolint when implemented -func (r *OCIRuntime) updateContainerStatus(ctr *Container) error { //nolint - return ErrNotImplemented +// runtime. It updates the container's state but does not save it. +func (r *OCIRuntime) updateContainerStatus(ctr *Container) error { + state := new(spec.State) + + out, err := exec.Command(r.path, "state", ctr.ID()).CombinedOutput() + if err != nil { + return errors.Wrapf(err, "error getting container %s state. stderr/out: %s", ctr.ID(), out) + } + + if err := json.NewDecoder(bytes.NewBuffer(out)).Decode(state); err != nil { + return errors.Wrapf(err, "error decoding container status for container %s", ctr.ID()) + } + + ctr.state.PID = state.Pid + + switch state.Status { + case "created": + ctr.state.State = ContainerStateCreated + case "paused": + ctr.state.State = ContainerStatePaused + case "running": + ctr.state.State = ContainerStateRunning + case "stopped": + ctr.state.State = ContainerStateStopped + default: + return errors.Wrapf(ErrInternal, "unrecognized status returned by runc for container %s: %s", + ctr.ID(), state.Status) + } + + if ctr.state.State == ContainerStateStopped { + exitFile := filepath.Join(r.exitsDir, ctr.ID()) + var fi os.FileInfo + err = kwait.ExponentialBackoff( + kwait.Backoff{ + Duration: 500 * time.Millisecond, + Factor: 1.2, + Steps: 6, + }, + func() (bool, error) { + var err error + fi, err = os.Stat(exitFile) + if err != nil { + // wait longer + return false, nil + } + return true, nil + }) + if err != nil { + ctr.state.ExitCode = -1 + ctr.state.FinishedTime = time.Now() + return errors.Wrapf(err, "no exit file for container %s found", ctr.ID()) + } + + ctr.state.FinishedTime = getFinishedTime(fi) + statusCodeStr, err := ioutil.ReadFile(exitFile) + if err != nil { + return errors.Wrapf(err, "failed to read exit file for container %s", ctr.ID()) + } + statusCode, err := strconv.Atoi(string(statusCodeStr)) + if err != nil { + return errors.Wrapf(err, "error convertaing exit status code for container %s to int", + ctr.ID()) + } + ctr.state.ExitCode = int32(statusCode) + + oomFilePath := filepath.Join(ctr.bundlePath(), "oom") + if _, err = os.Stat(oomFilePath); err == nil { + ctr.state.OOMKilled = true + } + + } + + return nil } // startContainer starts the given container -// remove nolint when function is complete -func (r *OCIRuntime) startContainer(ctr *Container) error { //nolint +// Sets time the container was started, but does not save it. +func (r *OCIRuntime) startContainer(ctr *Container) error { // TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers? - err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "start", ctr.ID()) + if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "start", ctr.ID()); err != nil { + return err + } - // TODO record start time in container struct + ctr.state.StartedTime = time.Now() - return err + return nil } |