aboutsummaryrefslogtreecommitdiff
path: root/libpod/container.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-21 13:44:22 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2017-11-21 20:09:09 +0000
commit8e76ebcf6e8925d5fa6a8c9ab517d665b44c7b63 (patch)
treecd9c15e37a00927ccd8c31b3cde40f46fe82b736 /libpod/container.go
parent7b736e333315e6f533b9677712a0c2e037cc293b (diff)
downloadpodman-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.go90
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 {