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/container.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/container.go')
-rw-r--r-- | libpod/container.go | 90 |
1 files changed, 59 insertions, 31 deletions
diff --git a/libpod/container.go b/libpod/container.go index 728a29dec..710ae866b 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -76,6 +76,11 @@ type containerRuntimeInfo struct { FinishedTime time.Time `json:"finishedTime,omitempty"` // ExitCode is the exit code returned when the container stopped ExitCode int32 `json:"exitCode,omitempty"` + // OOMKilled indicates that the container was killed as it ran out of + // memory + OOMKilled bool `json:"oomKilled,omitempty"` + // PID is the PID of a running container + PID int `json:"pid,omitempty"` // TODO: Save information about image used in container if one is used } @@ -129,10 +134,10 @@ func (c *Container) Name() string { // The spec returned is the one used to create the container. The running // spec may differ slightly as mounts are added based on the image func (c *Container) Spec() *spec.Spec { - spec := new(spec.Spec) - deepcopier.Copy(c.config.Spec).To(spec) + returnSpec := new(spec.Spec) + deepcopier.Copy(c.config.Spec).To(returnSpec) - return spec + return returnSpec } // Labels returns the container's labels @@ -150,13 +155,26 @@ func (c *Container) State() (ContainerState, error) { c.lock.Lock() defer c.lock.Unlock() - if err := c.runtime.state.UpdateContainer(c); err != nil { - return ContainerStateUnknown, errors.Wrapf(err, "error updating container %s state", c.ID()) + if err := c.syncContainer(); err != nil { + return ContainerStateUnknown, err } return c.state.State, nil } +// PID returns the PID of the container +// An error is returned if the container is not running +func (c *Container) PID() (int, error) { + c.lock.Lock() + defer c.lock.Unlock() + + if err := c.syncContainer(); err != nil { + return -1, err + } + + return c.state.PID, nil +} + // The path to the container's root filesystem - where the OCI spec will be // placed, amongst other things func (c *Container) bundlePath() string { @@ -168,6 +186,32 @@ func (c *Container) attachSocketPath() string { return filepath.Join(c.runtime.ociRuntime.socketsDir, c.ID(), "attach") } +// Sync this container with on-disk state and runc status +// Should only be called with container lock held +func (c *Container) syncContainer() error { + if err := c.runtime.state.UpdateContainer(c); err != nil { + return err + } + + // If runc knows about the container, update its status in runc + // And then save back to disk + if (c.state.State != ContainerStateUnknown) && + (c.state.State != ContainerStateConfigured) { + if err := c.runtime.ociRuntime.updateContainerStatus(c); err != nil { + return err + } + if err := c.runtime.state.SaveContainer(c); err != nil { + return err + } + } + + if !c.valid { + return errors.Wrapf(ErrCtrRemoved, "container %s is not valid", c.ID()) + } + + return nil +} + // Make a new container func newContainer(rspec *spec.Spec) (*Container, error) { if rspec == nil { @@ -191,9 +235,6 @@ func newContainer(rspec *spec.Spec) (*Container, error) { // Create container root filesystem for use func (c *Container) setupStorage() error { - c.lock.Lock() - defer c.lock.Unlock() - if !c.valid { return errors.Wrapf(ErrCtrRemoved, "container %s is not valid", c.ID()) } @@ -220,9 +261,6 @@ func (c *Container) setupStorage() error { // Tear down a container's storage prior to removal func (c *Container) teardownStorage() error { - c.lock.Lock() - defer c.lock.Unlock() - if !c.valid { return errors.Wrapf(ErrCtrRemoved, "container %s is not valid", c.ID()) } @@ -251,12 +289,8 @@ func (c *Container) Init() (err error) { c.lock.Lock() defer c.lock.Unlock() - if err := c.runtime.state.UpdateContainer(c); err != nil { - return errors.Wrapf(err, "error updating container %s state", c.ID()) - } - - if !c.valid { - return errors.Wrapf(ErrCtrRemoved, "container %s is not valid", c.ID()) + if err := c.syncContainer(); err != nil { + return err } if c.state.State != ContainerStateConfigured { @@ -325,12 +359,8 @@ func (c *Container) Start() error { c.lock.Lock() defer c.lock.Unlock() - if err := c.runtime.state.UpdateContainer(c); err != nil { - return errors.Wrapf(err, "error updating container %s state", c.ID()) - } - - if !c.valid { - return ErrCtrRemoved + if err := c.syncContainer(); err != nil { + return err } // Container must be created or stopped to be started @@ -344,8 +374,10 @@ func (c *Container) Start() error { logrus.Debugf("Started container %s", c.ID()) - c.state.StartedTime = time.Now() - c.state.State = ContainerStateRunning + // Update container's state as it should be ContainerStateRunning now + if err := c.runtime.ociRuntime.updateContainerStatus(c); err != nil { + return err + } if err := c.runtime.state.SaveContainer(c); err != nil { return errors.Wrapf(err, "error saving container %s state", c.ID()) @@ -373,12 +405,8 @@ func (c *Container) Exec(cmd []string, tty bool, stdin bool) (string, error) { // Attach attaches to a container // Returns fully qualified URL of streaming server for the container func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) error { - if err := c.runtime.state.UpdateContainer(c); err != nil { - return errors.Wrapf(err, "error updating container %s state", c.ID()) - } - - if !c.valid { - return errors.Wrapf(ErrCtrRemoved, "container %s is not valid", c.ID()) + if err := c.syncContainer(); err != nil { + return err } if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused { |