summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/common_test.go3
-rw-r--r--libpod/container.go78
-rw-r--r--libpod/container.log.go73
-rw-r--r--libpod/container_api.go56
-rw-r--r--libpod/container_commit.go3
-rw-r--r--libpod/container_graph.go4
-rw-r--r--libpod/container_inspect.go5
-rw-r--r--libpod/container_internal.go98
-rw-r--r--libpod/container_internal_linux.go8
-rw-r--r--libpod/container_log_linux.go15
-rw-r--r--libpod/container_log_unsupported.go3
-rw-r--r--libpod/container_top_linux.go9
-rw-r--r--libpod/container_top_unsupported.go6
-rw-r--r--libpod/define/config.go10
-rw-r--r--libpod/define/containerstate.go73
-rw-r--r--libpod/define/version.go (renamed from libpod/version.go)2
-rw-r--r--libpod/healthcheck.go3
-rw-r--r--libpod/info.go6
-rw-r--r--libpod/logs/log.go (renamed from libpod/container_log.go)96
-rw-r--r--libpod/oci.go16
-rw-r--r--libpod/pod_api.go12
-rw-r--r--libpod/pod_top_linux.go3
-rw-r--r--libpod/runtime.go144
-rw-r--r--libpod/runtime_ctr.go12
-rw-r--r--libpod/runtime_migrate.go2
-rw-r--r--libpod/state_test.go5
-rw-r--r--libpod/stats.go4
-rw-r--r--libpod/util.go11
28 files changed, 387 insertions, 373 deletions
diff --git a/libpod/common_test.go b/libpod/common_test.go
index df730098e..ae3cb1c87 100644
--- a/libpod/common_test.go
+++ b/libpod/common_test.go
@@ -7,6 +7,7 @@ import (
"testing"
"time"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/lock"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/opencontainers/runtime-tools/generate"
@@ -49,7 +50,7 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error)
},
},
state: &ContainerState{
- State: ContainerStateRunning,
+ State: define.ContainerStateRunning,
ConfigPath: "/does/not/exist/specs/" + id,
RunDir: "/does/not/exist/tmp/",
Mounted: true,
diff --git a/libpod/container.go b/libpod/container.go
index d05baa7e0..713386477 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -21,31 +21,6 @@ import (
"github.com/pkg/errors"
)
-// ContainerStatus represents the current state of a container
-type ContainerStatus int
-
-const (
- // ContainerStateUnknown indicates that the container is in an error
- // state where information about it cannot be retrieved
- ContainerStateUnknown ContainerStatus = iota
- // ContainerStateConfigured indicates that the container has had its
- // storage configured but it has not been created in the OCI runtime
- ContainerStateConfigured ContainerStatus = iota
- // ContainerStateCreated indicates the container has been created in
- // the OCI runtime but not started
- ContainerStateCreated ContainerStatus = iota
- // ContainerStateRunning indicates the container is currently executing
- ContainerStateRunning ContainerStatus = iota
- // ContainerStateStopped indicates that the container was running but has
- // exited
- ContainerStateStopped ContainerStatus = iota
- // ContainerStatePaused indicates that the container has been paused
- ContainerStatePaused ContainerStatus = iota
- // ContainerStateExited indicates the the container has stopped and been
- // cleaned up
- ContainerStateExited ContainerStatus = iota
-)
-
// CgroupfsDefaultCgroupParent is the cgroup parent for CGroupFS in libpod
const CgroupfsDefaultCgroupParent = "/libpod_parent"
@@ -169,7 +144,7 @@ type Container struct {
// It is stored on disk in a tmpfs and recreated on reboot
type ContainerState struct {
// The current state of the running container
- State ContainerStatus `json:"state"`
+ State define.ContainerStatus `json:"state"`
// The path to the JSON OCI runtime spec for this container
ConfigPath string `json:"configPath,omitempty"`
// RunDir is a per-boot directory for container content
@@ -428,51 +403,6 @@ type ContainerNamedVolume struct {
Options []string `json:"options,omitempty"`
}
-// ContainerStatus returns a string representation for users
-// of a container state
-func (t ContainerStatus) String() string {
- switch t {
- case ContainerStateUnknown:
- return "unknown"
- case ContainerStateConfigured:
- return "configured"
- case ContainerStateCreated:
- return "created"
- case ContainerStateRunning:
- return "running"
- case ContainerStateStopped:
- return "stopped"
- case ContainerStatePaused:
- return "paused"
- case ContainerStateExited:
- return "exited"
- }
- return "bad state"
-}
-
-// StringToContainerStatus converts a string representation of a containers
-// status into an actual container status type
-func StringToContainerStatus(status string) (ContainerStatus, error) {
- switch status {
- case ContainerStateUnknown.String():
- return ContainerStateUnknown, nil
- case ContainerStateConfigured.String():
- return ContainerStateConfigured, nil
- case ContainerStateCreated.String():
- return ContainerStateCreated, nil
- case ContainerStateRunning.String():
- return ContainerStateRunning, nil
- case ContainerStateStopped.String():
- return ContainerStateStopped, nil
- case ContainerStatePaused.String():
- return ContainerStatePaused, nil
- case ContainerStateExited.String():
- return ContainerStateExited, nil
- default:
- return ContainerStateUnknown, errors.Wrapf(define.ErrInvalidArg, "unknown container state: %s", status)
- }
-}
-
// Config accessors
// Unlocked
@@ -823,13 +753,13 @@ func (c *Container) WorkingDir() string {
// Require locking
// State returns the current state of the container
-func (c *Container) State() (ContainerStatus, error) {
+func (c *Container) State() (define.ContainerStatus, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.syncContainer(); err != nil {
- return ContainerStateUnknown, err
+ return define.ContainerStateUnknown, err
}
}
return c.state.State, nil
@@ -1097,7 +1027,7 @@ func (c *Container) NamespacePath(ns LinuxNS) (string, error) {
}
}
- if c.state.State != ContainerStateRunning && c.state.State != ContainerStatePaused {
+ if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused {
return "", errors.Wrapf(define.ErrCtrStopped, "cannot get namespace path unless container %s is running", c.ID())
}
diff --git a/libpod/container.log.go b/libpod/container.log.go
new file mode 100644
index 000000000..7d0cd5bfb
--- /dev/null
+++ b/libpod/container.log.go
@@ -0,0 +1,73 @@
+package libpod
+
+import (
+ "os"
+
+ "github.com/containers/libpod/libpod/logs"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// Log is a runtime function that can read one or more container logs.
+func (r *Runtime) Log(containers []*Container, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+ for _, ctr := range containers {
+ if err := ctr.ReadLog(options, logChannel); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// ReadLog reads a containers log based on the input options and returns loglines over a channel
+func (c *Container) ReadLog(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+ // TODO Skip sending logs until journald logs can be read
+ // TODO make this not a magic string
+ if c.LogDriver() == JournaldLogging {
+ return c.readFromJournal(options, logChannel)
+ }
+ return c.readFromLogFile(options, logChannel)
+}
+
+func (c *Container) readFromLogFile(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+ t, tailLog, err := logs.GetLogFile(c.LogPath(), options)
+ if err != nil {
+ // If the log file does not exist, this is not fatal.
+ if os.IsNotExist(errors.Cause(err)) {
+ return nil
+ }
+ return errors.Wrapf(err, "unable to read log file %s for %s ", c.ID(), c.LogPath())
+ }
+ options.WaitGroup.Add(1)
+ if len(tailLog) > 0 {
+ for _, nll := range tailLog {
+ nll.CID = c.ID()
+ if nll.Since(options.Since) {
+ logChannel <- nll
+ }
+ }
+ }
+
+ go func() {
+ var partial string
+ for line := range t.Lines {
+ nll, err := logs.NewLogLine(line.Text)
+ if err != nil {
+ logrus.Error(err)
+ continue
+ }
+ if nll.Partial() {
+ partial = partial + nll.Msg
+ continue
+ } else if !nll.Partial() && len(partial) > 1 {
+ nll.Msg = partial
+ partial = ""
+ }
+ nll.CID = c.ID()
+ if nll.Since(options.Since) {
+ logChannel <- nll
+ }
+ }
+ options.WaitGroup.Done()
+ }()
+ return nil
+}
diff --git a/libpod/container_api.go b/libpod/container_api.go
index b8c339a39..8d1e5751b 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -37,9 +37,9 @@ func (c *Container) Init(ctx context.Context) (err error) {
}
}
- if !(c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateStopped ||
- c.state.State == ContainerStateExited) {
+ if !(c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateStopped ||
+ c.state.State == define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", c.ID())
}
@@ -55,7 +55,7 @@ func (c *Container) Init(ctx context.Context) (err error) {
return err
}
- if c.state.State == ContainerStateStopped {
+ if c.state.State == define.ContainerStateStopped {
// Reinitialize the container
return c.reinit(ctx, false)
}
@@ -178,14 +178,14 @@ func (c *Container) StopWithTimeout(timeout uint) error {
}
}
- if c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateUnknown ||
- c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateUnknown ||
+ c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "can only stop created, running, or stopped containers. %s is in state %s", c.ID(), c.state.State.String())
}
- if c.state.State == ContainerStateStopped ||
- c.state.State == ContainerStateExited {
+ if c.state.State == define.ContainerStateStopped ||
+ c.state.State == define.ContainerStateExited {
return define.ErrCtrStopped
}
defer c.newContainerEvent(events.Stop)
@@ -203,7 +203,7 @@ func (c *Container) Kill(signal uint) error {
}
}
- if c.state.State != ContainerStateRunning {
+ if c.state.State != define.ContainerStateRunning {
return errors.Wrapf(define.ErrCtrStateInvalid, "can only kill running containers. %s is in state %s", c.ID(), c.state.State.String())
}
@@ -241,7 +241,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir
conState := c.state.State
// TODO can probably relax this once we track exec sessions
- if conState != ContainerStateRunning {
+ if conState != define.ContainerStateRunning {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot exec into container that is not running")
}
if privileged || c.config.Privileged {
@@ -399,9 +399,9 @@ func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan re
c.lock.Unlock()
}
- if c.state.State != ContainerStateCreated &&
- c.state.State != ContainerStateRunning &&
- c.state.State != ContainerStateExited {
+ if c.state.State != define.ContainerStateCreated &&
+ c.state.State != define.ContainerStateRunning &&
+ c.state.State != define.ContainerStateExited {
return errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers")
}
defer c.newContainerEvent(events.Attach)
@@ -440,7 +440,7 @@ func (c *Container) Unmount(force bool) error {
return errors.Wrapf(err, "can't determine how many times %s is mounted, refusing to unmount", c.ID())
}
if mounted == 1 {
- if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot unmount storage for container %s as it is running or paused", c.ID())
}
if len(c.state.ExecSessions) != 0 {
@@ -464,10 +464,10 @@ func (c *Container) Pause() error {
}
}
- if c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "%q is already paused", c.ID())
}
- if c.state.State != ContainerStateRunning {
+ if c.state.State != define.ContainerStateRunning {
return errors.Wrapf(define.ErrCtrStateInvalid, "%q is not running, can't pause", c.state.State)
}
defer c.newContainerEvent(events.Pause)
@@ -485,7 +485,7 @@ func (c *Container) Unpause() error {
}
}
- if c.state.State != ContainerStatePaused {
+ if c.state.State != define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "%q is not paused, can't unpause", c.ID())
}
defer c.newContainerEvent(events.Unpause)
@@ -578,7 +578,7 @@ func (c *Container) Cleanup(ctx context.Context) error {
}
// Check if state is good
- if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, refusing to clean up", c.ID())
}
@@ -656,9 +656,9 @@ func (c *Container) Sync() error {
// If runtime knows about the container, update its status in runtime
// And then save back to disk
- if (c.state.State != ContainerStateUnknown) &&
- (c.state.State != ContainerStateConfigured) &&
- (c.state.State != ContainerStateExited) {
+ if (c.state.State != define.ContainerStateUnknown) &&
+ (c.state.State != define.ContainerStateConfigured) &&
+ (c.state.State != define.ContainerStateExited) {
oldState := c.state.State
if err := c.ociRuntime.updateContainerStatus(c, true); err != nil {
return err
@@ -687,27 +687,27 @@ func (c *Container) Refresh(ctx context.Context) error {
}
wasCreated := false
- if c.state.State == ContainerStateCreated {
+ if c.state.State == define.ContainerStateCreated {
wasCreated = true
}
wasRunning := false
- if c.state.State == ContainerStateRunning {
+ if c.state.State == define.ContainerStateRunning {
wasRunning = true
}
wasPaused := false
- if c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStatePaused {
wasPaused = true
}
// First, unpause the container if it's paused
- if c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStatePaused {
if err := c.unpause(); err != nil {
return err
}
}
// Next, if the container is running, stop it
- if c.state.State == ContainerStateRunning {
+ if c.state.State == define.ContainerStateRunning {
if err := c.stop(c.config.StopTimeout); err != nil {
return err
}
@@ -724,7 +724,7 @@ func (c *Container) Refresh(ctx context.Context) error {
// If the container is in ContainerStateStopped, we need to delete it
// from the runtime and clear conmon state
- if c.state.State == ContainerStateStopped {
+ if c.state.State == define.ContainerStateStopped {
if err := c.delete(ctx); err != nil {
return err
}
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index 82115455a..17586bfad 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/buildah"
"github.com/containers/buildah/util"
is "github.com/containers/image/storage"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
"github.com/pkg/errors"
@@ -48,7 +49,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
}
}
- if c.state.State == ContainerStateRunning && options.Pause {
+ if c.state.State == define.ContainerStateRunning && options.Pause {
if err := c.ociRuntime.pauseContainer(c); err != nil {
return nil, errors.Wrapf(err, "error pausing container %q", c.ID())
}
diff --git a/libpod/container_graph.go b/libpod/container_graph.go
index c266c5227..50dbdfbe4 100644
--- a/libpod/container_graph.go
+++ b/libpod/container_graph.go
@@ -244,13 +244,13 @@ func startNode(ctx context.Context, node *containerNode, setError bool, ctrError
// Start the container (only if it is not running)
if !ctrErrored {
- if !restart && node.container.state.State != ContainerStateRunning {
+ if !restart && node.container.state.State != define.ContainerStateRunning {
if err := node.container.initAndStart(ctx); err != nil {
ctrErrored = true
ctrErrors[node.id] = err
}
}
- if restart && node.container.state.State != ContainerStatePaused && node.container.state.State != ContainerStateUnknown {
+ if restart && node.container.state.State != define.ContainerStatePaused && node.container.state.State != define.ContainerStateUnknown {
if err := node.container.restartWithTimeout(ctx, node.container.config.StopTimeout); err != nil {
ctrErrored = true
ctrErrors[node.id] = err
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 3ac774060..6085f1210 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -5,6 +5,7 @@ import (
"time"
"github.com/containers/image/manifest"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/driver"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -255,8 +256,8 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
State: &InspectContainerState{
OciVersion: spec.Version,
Status: runtimeInfo.State.String(),
- Running: runtimeInfo.State == ContainerStateRunning,
- Paused: runtimeInfo.State == ContainerStatePaused,
+ Running: runtimeInfo.State == define.ContainerStateRunning,
+ Paused: runtimeInfo.State == define.ContainerStatePaused,
OOMKilled: runtimeInfo.OOMKilled,
Dead: runtimeInfo.State.String() == "bad state",
Pid: runtimeInfo.PID,
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index fcd6a990a..43d2b6e61 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -156,7 +156,7 @@ func (c *Container) waitForExitFileAndSync() error {
// Reset our state
c.state.ExitCode = -1
c.state.FinishedTime = time.Now()
- c.state.State = ContainerStateStopped
+ c.state.State = define.ContainerStateStopped
if err2 := c.save(); err2 != nil {
logrus.Errorf("Error saving container %s state: %v", c.ID(), err2)
@@ -241,9 +241,9 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (restarted bool, er
// Is the container running again?
// If so, we don't have to do anything
- if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
return false, nil
- } else if c.state.State == ContainerStateUnknown {
+ } else if c.state.State == define.ContainerStateUnknown {
return false, errors.Wrapf(define.ErrInternal, "invalid container state encountered in restart attempt!")
}
@@ -267,13 +267,13 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (restarted bool, er
return false, err
}
- if c.state.State == ContainerStateStopped {
+ if c.state.State == define.ContainerStateStopped {
// Reinitialize the container if we need to
if err := c.reinit(ctx, true); err != nil {
return false, err
}
- } else if c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateExited {
+ } else if c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateExited {
// Initialize the container
if err := c.init(ctx, true); err != nil {
return false, err
@@ -295,9 +295,9 @@ func (c *Container) syncContainer() error {
}
// If runtime knows about the container, update its status in runtime
// And then save back to disk
- if (c.state.State != ContainerStateUnknown) &&
- (c.state.State != ContainerStateConfigured) &&
- (c.state.State != ContainerStateExited) {
+ if (c.state.State != define.ContainerStateUnknown) &&
+ (c.state.State != define.ContainerStateConfigured) &&
+ (c.state.State != define.ContainerStateExited) {
oldState := c.state.State
// TODO: optionally replace this with a stat for the exit file
if err := c.ociRuntime.updateContainerStatus(c, false); err != nil {
@@ -307,8 +307,8 @@ func (c *Container) syncContainer() error {
if c.state.State != oldState {
// Check for a restart policy match
if c.config.RestartPolicy != RestartPolicyNone && c.config.RestartPolicy != RestartPolicyNo &&
- (oldState == ContainerStateRunning || oldState == ContainerStatePaused) &&
- (c.state.State == ContainerStateStopped || c.state.State == ContainerStateExited) &&
+ (oldState == define.ContainerStateRunning || oldState == define.ContainerStatePaused) &&
+ (c.state.State == define.ContainerStateStopped || c.state.State == define.ContainerStateExited) &&
!c.state.StoppedByUser {
c.state.RestartPolicyMatch = true
}
@@ -336,7 +336,7 @@ func (c *Container) setupStorage(ctx context.Context) error {
return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid", c.ID())
}
- if c.state.State != ContainerStateConfigured {
+ if c.state.State != define.ContainerStateConfigured {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s must be in Configured state to have storage set up", c.ID())
}
@@ -418,7 +418,7 @@ func (c *Container) setupStorage(ctx context.Context) error {
// Tear down a container's storage prior to removal
func (c *Container) teardownStorage() error {
- if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID())
}
@@ -454,8 +454,8 @@ func resetState(state *ContainerState) error {
state.PID = 0
state.Mountpoint = ""
state.Mounted = false
- if state.State != ContainerStateExited {
- state.State = ContainerStateConfigured
+ if state.State != define.ContainerStateExited {
+ state.State = define.ContainerStateConfigured
}
state.ExecSessions = make(map[string]*ExecSession)
state.NetworkStatus = nil
@@ -609,7 +609,7 @@ func (c *Container) isStopped() (bool, error) {
if err != nil {
return true, err
}
- return (c.state.State != ContainerStateRunning && c.state.State != ContainerStatePaused), nil
+ return (c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused), nil
}
// save container state to the database
@@ -625,10 +625,10 @@ func (c *Container) save() error {
// Otherwise, this function will return with error if there are dependencies of this container that aren't running.
func (c *Container) prepareToStart(ctx context.Context, recursive bool) (err error) {
// Container must be created or stopped to be started
- if !(c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateCreated ||
- c.state.State == ContainerStateStopped ||
- c.state.State == ContainerStateExited) {
+ if !(c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateCreated ||
+ c.state.State == define.ContainerStateStopped ||
+ c.state.State == define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s must be in Created or Stopped state to be started", c.ID())
}
@@ -654,13 +654,13 @@ func (c *Container) prepareToStart(ctx context.Context, recursive bool) (err err
return err
}
- if c.state.State == ContainerStateStopped {
+ if c.state.State == define.ContainerStateStopped {
// Reinitialize the container if we need to
if err := c.reinit(ctx, false); err != nil {
return err
}
- } else if c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateExited {
+ } else if c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateExited {
// Or initialize it if necessary
if err := c.init(ctx, false); err != nil {
return err
@@ -763,7 +763,7 @@ func (c *Container) getAllDependencies(visited map[string]*Container) error {
}
// if the dependency is already running, we can assume its dependencies are also running
// so no need to add them to those we need to start
- if status != ContainerStateRunning {
+ if status != define.ContainerStateRunning {
visited[depID] = dep
if err := dep.getAllDependencies(visited); err != nil {
return err
@@ -795,7 +795,7 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
if err != nil {
return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID())
}
- if state != ContainerStateRunning {
+ if state != define.ContainerStateRunning {
notRunning = append(notRunning, dep)
}
depCtrs[dep] = depCtr
@@ -824,7 +824,7 @@ func (c *Container) checkDependenciesRunningLocked(depCtrs map[string]*Container
return nil, err
}
- if depCtr.state.State != ContainerStateRunning {
+ if depCtr.state.State != define.ContainerStateRunning {
notRunning = append(notRunning, dep)
}
}
@@ -875,7 +875,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
c.state.ExitCode = 0
c.state.Exited = false
- c.state.State = ContainerStateCreated
+ c.state.State = define.ContainerStateCreated
c.state.StoppedByUser = false
c.state.RestartPolicyMatch = false
@@ -906,7 +906,7 @@ func (c *Container) cleanupRuntime(ctx context.Context) error {
// If the container is not ContainerStateStopped or
// ContainerStateCreated, do nothing.
- if c.state.State != ContainerStateStopped && c.state.State != ContainerStateCreated {
+ if c.state.State != define.ContainerStateStopped && c.state.State != define.ContainerStateCreated {
return nil
}
@@ -922,10 +922,10 @@ func (c *Container) cleanupRuntime(ctx context.Context) error {
// If we were Stopped, we are now Exited, as we've removed ourself
// from the runtime.
// If we were Created, we are now Configured.
- if c.state.State == ContainerStateStopped {
- c.state.State = ContainerStateExited
- } else if c.state.State == ContainerStateCreated {
- c.state.State = ContainerStateConfigured
+ if c.state.State == define.ContainerStateStopped {
+ c.state.State = define.ContainerStateExited
+ } else if c.state.State == define.ContainerStateCreated {
+ c.state.State = define.ContainerStateConfigured
}
if c.valid {
@@ -964,16 +964,16 @@ func (c *Container) reinit(ctx context.Context, retainRetries bool) error {
// Does not lock or check validity
func (c *Container) initAndStart(ctx context.Context) (err error) {
// If we are ContainerStateUnknown, throw an error
- if c.state.State == ContainerStateUnknown {
+ if c.state.State == define.ContainerStateUnknown {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is in an unknown state", c.ID())
}
// If we are running, do nothing
- if c.state.State == ContainerStateRunning {
+ if c.state.State == define.ContainerStateRunning {
return nil
}
// If we are paused, throw an error
- if c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot start paused container %s", c.ID())
}
@@ -991,14 +991,14 @@ func (c *Container) initAndStart(ctx context.Context) (err error) {
// If we are ContainerStateStopped we need to remove from runtime
// And reset to ContainerStateConfigured
- if c.state.State == ContainerStateStopped {
+ if c.state.State == define.ContainerStateStopped {
logrus.Debugf("Recreating container %s in OCI runtime", c.ID())
if err := c.reinit(ctx, false); err != nil {
return err
}
- } else if c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateExited {
+ } else if c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateExited {
if err := c.init(ctx, false); err != nil {
return err
}
@@ -1019,7 +1019,7 @@ func (c *Container) start() error {
}
logrus.Debugf("Started container %s", c.ID())
- c.state.State = ContainerStateRunning
+ c.state.State = define.ContainerStateRunning
if c.config.HealthCheckConfig != nil {
if err := c.updateHealthStatus(HealthCheckStarting); err != nil {
@@ -1060,7 +1060,7 @@ func (c *Container) pause() error {
logrus.Debugf("Paused container %s", c.ID())
- c.state.State = ContainerStatePaused
+ c.state.State = define.ContainerStatePaused
return c.save()
}
@@ -1073,20 +1073,20 @@ func (c *Container) unpause() error {
logrus.Debugf("Unpaused container %s", c.ID())
- c.state.State = ContainerStateRunning
+ c.state.State = define.ContainerStateRunning
return c.save()
}
// Internal, non-locking function to restart a container
func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err error) {
- if c.state.State == ContainerStateUnknown || c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateUnknown || c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "unable to restart a container in a paused or unknown state")
}
c.newContainerEvent(events.Restart)
- if c.state.State == ContainerStateRunning {
+ if c.state.State == define.ContainerStateRunning {
if err := c.stop(timeout); err != nil {
return err
}
@@ -1102,13 +1102,13 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
return err
}
- if c.state.State == ContainerStateStopped {
+ if c.state.State == define.ContainerStateStopped {
// Reinitialize the container if we need to
if err := c.reinit(ctx, false); err != nil {
return err
}
- } else if c.state.State == ContainerStateConfigured ||
- c.state.State == ContainerStateExited {
+ } else if c.state.State == define.ContainerStateConfigured ||
+ c.state.State == define.ContainerStateExited {
// Initialize the container
if err := c.init(ctx, false); err != nil {
return err
@@ -1482,12 +1482,12 @@ func (c *Container) copyWithTarFromImage(src, dest string) error {
// If it is, we'll remove the container anyways.
// Returns nil if safe to remove, or an error describing why it's unsafe if not.
func (c *Container) checkReadyForRemoval() error {
- if c.state.State == ContainerStateUnknown {
+ if c.state.State == define.ContainerStateUnknown {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is in invalid state", c.ID())
}
- if c.state.State == ContainerStateRunning ||
- c.state.State == ContainerStatePaused {
+ if c.state.State == define.ContainerStateRunning ||
+ c.state.State == define.ContainerStatePaused {
return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove container %s as it is %s - running or paused containers cannot be removed", c.ID(), c.state.State.String())
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index e93e0cad8..fad45233a 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -573,7 +573,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
return err
}
- if c.state.State != ContainerStateRunning {
+ if c.state.State != define.ContainerStateRunning {
return errors.Wrapf(define.ErrCtrStateInvalid, "%q is not running, cannot checkpoint", c.state.State)
}
@@ -605,7 +605,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
logrus.Debugf("Checkpointed container %s", c.ID())
if !options.KeepRunning {
- c.state.State = ContainerStateStopped
+ c.state.State = define.ContainerStateStopped
// Cleanup Storage and Network
if err := c.cleanup(ctx); err != nil {
@@ -664,7 +664,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return err
}
- if (c.state.State != ContainerStateConfigured) && (c.state.State != ContainerStateExited) {
+ if (c.state.State != define.ContainerStateConfigured) && (c.state.State != define.ContainerStateExited) {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID())
}
@@ -781,7 +781,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
logrus.Debugf("Restored container %s", c.ID())
- c.state.State = ContainerStateRunning
+ c.state.State = define.ContainerStateRunning
if !options.Keep {
// Delete all checkpoint related files. At this point, in theory, all files
diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go
index e549673a6..8a87a8796 100644
--- a/libpod/container_log_linux.go
+++ b/libpod/container_log_linux.go
@@ -9,6 +9,7 @@ import (
"strings"
"time"
+ "github.com/containers/libpod/libpod/logs"
journal "github.com/coreos/go-systemd/sdjournal"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -27,7 +28,7 @@ const (
bufLen = 16384
)
-func (c *Container) readFromJournal(options *LogOptions, logChannel chan *LogLine) error {
+func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
var config journal.JournalReaderConfig
config.NumFromTail = options.Tail
config.Formatter = journalFormatter
@@ -79,7 +80,7 @@ func (c *Container) readFromJournal(options *LogOptions, logChannel chan *LogLin
// because we are reusing bytes, we need to make
// sure the old data doesn't get into the new line
bytestr := string(bytes[:ec])
- logLine, err2 := newLogLine(bytestr)
+ logLine, err2 := logs.NewLogLine(bytestr)
if err2 != nil {
logrus.Error(err2)
continue
@@ -98,7 +99,7 @@ func (c *Container) readFromJournal(options *LogOptions, logChannel chan *LogLin
func journalFormatter(entry *journal.JournalEntry) (string, error) {
usec := entry.RealtimeTimestamp
- tsString := time.Unix(0, int64(usec)*int64(time.Microsecond)).Format(logTimeFormat)
+ tsString := time.Unix(0, int64(usec)*int64(time.Microsecond)).Format(logs.LogTimeFormat)
output := fmt.Sprintf("%s ", tsString)
priority, ok := entry.Fields["PRIORITY"]
if !ok {
@@ -114,9 +115,9 @@ func journalFormatter(entry *journal.JournalEntry) (string, error) {
// if CONTAINER_PARTIAL_MESSAGE is defined, the log type is "P"
if _, ok := entry.Fields["CONTAINER_PARTIAL_MESSAGE"]; ok {
- output += fmt.Sprintf("%s ", partialLogType)
+ output += fmt.Sprintf("%s ", logs.PartialLogType)
} else {
- output += fmt.Sprintf("%s ", fullLogType)
+ output += fmt.Sprintf("%s ", logs.FullLogType)
}
// Finally, append the message
@@ -129,12 +130,12 @@ func journalFormatter(entry *journal.JournalEntry) (string, error) {
}
type FollowBuffer struct {
- logChannel chan *LogLine
+ logChannel chan *logs.LogLine
}
func (f FollowBuffer) Write(p []byte) (int, error) {
bytestr := string(p)
- logLine, err := newLogLine(bytestr)
+ logLine, err := logs.NewLogLine(bytestr)
if err != nil {
return -1, err
}
diff --git a/libpod/container_log_unsupported.go b/libpod/container_log_unsupported.go
index 380d317b5..2c4492b10 100644
--- a/libpod/container_log_unsupported.go
+++ b/libpod/container_log_unsupported.go
@@ -4,9 +4,10 @@ package libpod
import (
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/libpod/logs"
"github.com/pkg/errors"
)
-func (c *Container) readFromJournal(options *LogOptions, logChannel chan *LogLine) error {
+func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
return errors.Wrapf(define.ErrOSNotSupported, "Journald logging only enabled with systemd on linux")
}
diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go
index 2e0e83c05..ce471838d 100644
--- a/libpod/container_top_linux.go
+++ b/libpod/container_top_linux.go
@@ -6,6 +6,7 @@ import (
"strconv"
"strings"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/psgo"
"github.com/pkg/errors"
@@ -18,7 +19,7 @@ func (c *Container) Top(descriptors []string) ([]string, error) {
if err != nil {
return nil, errors.Wrapf(err, "unable to look up state for %s", c.ID())
}
- if conStat != ContainerStateRunning {
+ if conStat != define.ContainerStateRunning {
return nil, errors.Errorf("top can only be used on running containers")
}
@@ -60,9 +61,3 @@ func (c *Container) GetContainerPidInformation(descriptors []string) ([]string,
}
return res, nil
}
-
-// GetContainerPidInformationDescriptors returns a string slice of all supported
-// format descriptors of GetContainerPidInformation.
-func GetContainerPidInformationDescriptors() ([]string, error) {
- return psgo.ListDescriptors(), nil
-}
diff --git a/libpod/container_top_unsupported.go b/libpod/container_top_unsupported.go
index 2117f913d..382c98b54 100644
--- a/libpod/container_top_unsupported.go
+++ b/libpod/container_top_unsupported.go
@@ -15,9 +15,3 @@ import "github.com/containers/libpod/libpod/define"
func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) {
return nil, define.ErrNotImplemented
}
-
-// GetContainerPidInformationDescriptors returns a string slice of all supported
-// format descriptors of GetContainerPidInformation.
-func GetContainerPidInformationDescriptors() ([]string, error) {
- return nil, define.ErrNotImplemented
-}
diff --git a/libpod/define/config.go b/libpod/define/config.go
index 256a4b21f..d8d6ccf55 100644
--- a/libpod/define/config.go
+++ b/libpod/define/config.go
@@ -3,8 +3,18 @@ package define
var (
// DefaultInitPath is the default path to the container-init binary
DefaultInitPath = "/usr/libexec/podman/catatonit"
+ // DefaultInfraImage to use for infra container
+ DefaultInfraImage = "k8s.gcr.io/pause:3.1"
+ // DefaultInfraCommand to be run in an infra container
+ DefaultInfraCommand = "/pause"
)
// CtrRemoveTimeout is the default number of seconds to wait after stopping a container
// before sending the kill signal
const CtrRemoveTimeout = 10
+
+// InfoData holds the info type, i.e store, host etc and the data for each type
+type InfoData struct {
+ Type string
+ Data map[string]interface{}
+}
diff --git a/libpod/define/containerstate.go b/libpod/define/containerstate.go
new file mode 100644
index 000000000..ab2527b3e
--- /dev/null
+++ b/libpod/define/containerstate.go
@@ -0,0 +1,73 @@
+package define
+
+import "github.com/pkg/errors"
+
+// ContainerStatus represents the current state of a container
+type ContainerStatus int
+
+const (
+ // ContainerStateUnknown indicates that the container is in an error
+ // state where information about it cannot be retrieved
+ ContainerStateUnknown ContainerStatus = iota
+ // ContainerStateConfigured indicates that the container has had its
+ // storage configured but it has not been created in the OCI runtime
+ ContainerStateConfigured ContainerStatus = iota
+ // ContainerStateCreated indicates the container has been created in
+ // the OCI runtime but not started
+ ContainerStateCreated ContainerStatus = iota
+ // ContainerStateRunning indicates the container is currently executing
+ ContainerStateRunning ContainerStatus = iota
+ // ContainerStateStopped indicates that the container was running but has
+ // exited
+ ContainerStateStopped ContainerStatus = iota
+ // ContainerStatePaused indicates that the container has been paused
+ ContainerStatePaused ContainerStatus = iota
+ // ContainerStateExited indicates the the container has stopped and been
+ // cleaned up
+ ContainerStateExited ContainerStatus = iota
+)
+
+// ContainerStatus returns a string representation for users
+// of a container state
+func (t ContainerStatus) String() string {
+ switch t {
+ case ContainerStateUnknown:
+ return "unknown"
+ case ContainerStateConfigured:
+ return "configured"
+ case ContainerStateCreated:
+ return "created"
+ case ContainerStateRunning:
+ return "running"
+ case ContainerStateStopped:
+ return "stopped"
+ case ContainerStatePaused:
+ return "paused"
+ case ContainerStateExited:
+ return "exited"
+ }
+ return "bad state"
+}
+
+// StringToContainerStatus converts a string representation of a containers
+// status into an actual container status type
+func StringToContainerStatus(status string) (ContainerStatus, error) {
+ switch status {
+ case ContainerStateUnknown.String():
+ return ContainerStateUnknown, nil
+ case ContainerStateConfigured.String():
+ return ContainerStateConfigured, nil
+ case ContainerStateCreated.String():
+ return ContainerStateCreated, nil
+ case ContainerStateRunning.String():
+ return ContainerStateRunning, nil
+ case ContainerStateStopped.String():
+ return ContainerStateStopped, nil
+ case ContainerStatePaused.String():
+ return ContainerStatePaused, nil
+ case ContainerStateExited.String():
+ return ContainerStateExited, nil
+ default:
+ return ContainerStateUnknown, errors.Wrapf(ErrInvalidArg, "unknown container state: %s", status)
+ }
+}
diff --git a/libpod/version.go b/libpod/define/version.go
index d2b99a275..0f9f49050 100644
--- a/libpod/version.go
+++ b/libpod/define/version.go
@@ -1,4 +1,4 @@
-package libpod
+package define
import (
"runtime"
diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go
index 3e36a2c95..f4ea6c694 100644
--- a/libpod/healthcheck.go
+++ b/libpod/healthcheck.go
@@ -9,6 +9,7 @@ import (
"strings"
"time"
+ "github.com/containers/libpod/libpod/define"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -169,7 +170,7 @@ func checkHealthCheckCanBeRun(c *Container) (HealthCheckStatus, error) {
if err != nil {
return HealthCheckInternalError, err
}
- if cstate != ContainerStateRunning {
+ if cstate != define.ContainerStateRunning {
return HealthCheckContainerStopped, errors.Errorf("container %s is not running", c.ID())
}
if !c.HasHealthCheck() {
diff --git a/libpod/info.go b/libpod/info.go
index c96293e3d..4a89fa648 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -19,12 +19,6 @@ import (
"github.com/pkg/errors"
)
-// InfoData holds the info type, i.e store, host etc and the data for each type
-type InfoData struct {
- Type string
- Data map[string]interface{}
-}
-
// top-level "host" info
func (r *Runtime) hostInfo() (map[string]interface{}, error) {
// lets say OS, arch, number of cpus, amount of memory, maybe os distribution/version, hostname, kernel version, uptime
diff --git a/libpod/container_log.go b/libpod/logs/log.go
index 374e5a1fc..488291cfe 100644
--- a/libpod/container_log.go
+++ b/libpod/logs/log.go
@@ -1,31 +1,29 @@
-package libpod
+package logs
import (
"fmt"
"io/ioutil"
- "os"
"strings"
"sync"
"time"
"github.com/hpcloud/tail"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
const (
- // logTimeFormat is the time format used in the log.
+ // LogTimeFormat is the time format used in the log.
// It is a modified version of RFC3339Nano that guarantees trailing
// zeroes are not trimmed, taken from
// https://github.com/golang/go/issues/19635
- logTimeFormat = "2006-01-02T15:04:05.000000000Z07:00"
+ LogTimeFormat = "2006-01-02T15:04:05.000000000Z07:00"
- // partialLogType signifies a log line that exceeded the buffer
+ // PartialLogType signifies a log line that exceeded the buffer
// length and needed to spill into a new line
- partialLogType = "P"
+ PartialLogType = "P"
- // fullLogType signifies a log line is full
- fullLogType = "F"
+ // FullLogType signifies a log line is full
+ FullLogType = "F"
)
// LogOptions is the options you can use for logs
@@ -48,72 +46,8 @@ type LogLine struct {
CID string
}
-// Log is a runtime function that can read one or more container logs.
-func (r *Runtime) Log(containers []*Container, options *LogOptions, logChannel chan *LogLine) error {
- for _, ctr := range containers {
- if err := ctr.ReadLog(options, logChannel); err != nil {
- return err
- }
- }
- return nil
-}
-
-// ReadLog reads a containers log based on the input options and returns loglines over a channel
-func (c *Container) ReadLog(options *LogOptions, logChannel chan *LogLine) error {
- // TODO Skip sending logs until journald logs can be read
- // TODO make this not a magic string
- if c.LogDriver() == JournaldLogging {
- return c.readFromJournal(options, logChannel)
- }
- return c.readFromLogFile(options, logChannel)
-}
-
-func (c *Container) readFromLogFile(options *LogOptions, logChannel chan *LogLine) error {
- t, tailLog, err := getLogFile(c.LogPath(), options)
- if err != nil {
- // If the log file does not exist, this is not fatal.
- if os.IsNotExist(errors.Cause(err)) {
- return nil
- }
- return errors.Wrapf(err, "unable to read log file %s for %s ", c.ID(), c.LogPath())
- }
- options.WaitGroup.Add(1)
- if len(tailLog) > 0 {
- for _, nll := range tailLog {
- nll.CID = c.ID()
- if nll.Since(options.Since) {
- logChannel <- nll
- }
- }
- }
-
- go func() {
- var partial string
- for line := range t.Lines {
- nll, err := newLogLine(line.Text)
- if err != nil {
- logrus.Error(err)
- continue
- }
- if nll.Partial() {
- partial = partial + nll.Msg
- continue
- } else if !nll.Partial() && len(partial) > 1 {
- nll.Msg = partial
- partial = ""
- }
- nll.CID = c.ID()
- if nll.Since(options.Since) {
- logChannel <- nll
- }
- }
- options.WaitGroup.Done()
- }()
- return nil
-}
-
-// getLogFile returns an hp tail for a container given options
-func getLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error) {
+// GetLogFile returns an hp tail for a container given options
+func GetLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error) {
var (
whence int
err error
@@ -154,7 +88,7 @@ func getTailLog(path string, tail int) ([]*LogLine, error) {
if len(splitContent[i]) == 0 {
continue
}
- nll, err := newLogLine(splitContent[i])
+ nll, err := NewLogLine(splitContent[i])
if err != nil {
return nil, err
}
@@ -191,7 +125,7 @@ func (l *LogLine) String(options *LogOptions) string {
out = fmt.Sprintf("%s ", cid)
}
if options.Timestamps {
- out = out + fmt.Sprintf("%s ", l.Time.Format(logTimeFormat))
+ out = out + fmt.Sprintf("%s ", l.Time.Format(LogTimeFormat))
}
return out + l.Msg
}
@@ -201,13 +135,13 @@ func (l *LogLine) Since(since time.Time) bool {
return l.Time.After(since)
}
-// newLogLine creates a logLine struct from a container log string
-func newLogLine(line string) (*LogLine, error) {
+// NewLogLine creates a logLine struct from a container log string
+func NewLogLine(line string) (*LogLine, error) {
splitLine := strings.Split(line, " ")
if len(splitLine) < 4 {
return nil, errors.Errorf("'%s' is not a valid container log line", line)
}
- logTime, err := time.Parse(logTimeFormat, splitLine[0])
+ logTime, err := time.Parse(LogTimeFormat, splitLine[0])
if err != nil {
return nil, errors.Wrapf(err, "unable to convert time %s from container log", splitLine[0])
}
@@ -222,7 +156,7 @@ func newLogLine(line string) (*LogLine, error) {
// Partial returns a bool if the log line is a partial log type
func (l *LogLine) Partial() bool {
- if l.ParseLogType == partialLogType {
+ if l.ParseLogType == PartialLogType {
return true
}
return false
diff --git a/libpod/oci.go b/libpod/oci.go
index 343738a3a..efb5e42cc 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -217,7 +217,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro
// If not using the OCI runtime, we don't need to do most of this.
if !useRuntime {
// If the container's not running, nothing to do.
- if ctr.state.State != ContainerStateRunning && ctr.state.State != ContainerStatePaused {
+ if ctr.state.State != define.ContainerStateRunning && ctr.state.State != define.ContainerStatePaused {
return nil
}
@@ -233,7 +233,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro
}
// Alright, it exists. Transition to Stopped state.
- ctr.state.State = ContainerStateStopped
+ ctr.state.State = define.ContainerStateStopped
// Read the exit file to get our stopped time and exit code.
return ctr.handleExitFile(exitFile, info)
@@ -264,7 +264,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro
ctr.removeConmonFiles()
ctr.state.ExitCode = -1
ctr.state.FinishedTime = time.Now()
- ctr.state.State = ContainerStateExited
+ ctr.state.State = define.ContainerStateExited
return nil
}
return errors.Wrapf(err, "error getting container %s state. stderr/out: %s", ctr.ID(), out)
@@ -283,13 +283,13 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro
switch state.Status {
case "created":
- ctr.state.State = ContainerStateCreated
+ ctr.state.State = define.ContainerStateCreated
case "paused":
- ctr.state.State = ContainerStatePaused
+ ctr.state.State = define.ContainerStatePaused
case "running":
- ctr.state.State = ContainerStateRunning
+ ctr.state.State = define.ContainerStateRunning
case "stopped":
- ctr.state.State = ContainerStateStopped
+ ctr.state.State = define.ContainerStateStopped
default:
return errors.Wrapf(define.ErrInternal, "unrecognized status returned by runtime for container %s: %s",
ctr.ID(), state.Status)
@@ -297,7 +297,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container, useRuntime bool) erro
// Only grab exit status if we were not already stopped
// If we were, it should already be in the database
- if ctr.state.State == ContainerStateStopped && oldState != ContainerStateStopped {
+ if ctr.state.State == define.ContainerStateStopped && oldState != define.ContainerStateStopped {
var fi os.FileInfo
chWait := make(chan error)
defer close(chWait)
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 3126ced4c..c7b0353bd 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -113,7 +113,7 @@ func (p *Pod) StopWithTimeout(ctx context.Context, cleanup bool, timeout int) (m
}
// Ignore containers that are not running
- if ctr.state.State != ContainerStateRunning {
+ if ctr.state.State != define.ContainerStateRunning {
ctr.lock.Unlock()
continue
}
@@ -181,7 +181,7 @@ func (p *Pod) Pause() (map[string]error, error) {
}
// Ignore containers that are not running
- if ctr.state.State != ContainerStateRunning {
+ if ctr.state.State != define.ContainerStateRunning {
ctr.lock.Unlock()
continue
}
@@ -240,7 +240,7 @@ func (p *Pod) Unpause() (map[string]error, error) {
}
// Ignore containers that are not paused
- if ctr.state.State != ContainerStatePaused {
+ if ctr.state.State != define.ContainerStatePaused {
ctr.lock.Unlock()
continue
}
@@ -353,7 +353,7 @@ func (p *Pod) Kill(signal uint) (map[string]error, error) {
}
// Ignore containers that are not running
- if ctr.state.State != ContainerStateRunning {
+ if ctr.state.State != define.ContainerStateRunning {
ctr.lock.Unlock()
continue
}
@@ -383,7 +383,7 @@ func (p *Pod) Kill(signal uint) (map[string]error, error) {
// Status gets the status of all containers in the pod
// Returns a map of Container ID to Container Status
-func (p *Pod) Status() (map[string]ContainerStatus, error) {
+func (p *Pod) Status() (map[string]define.ContainerStatus, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -403,7 +403,7 @@ func (p *Pod) Status() (map[string]ContainerStatus, error) {
}
// Now that all containers are locked, get their status
- status := make(map[string]ContainerStatus, len(allCtrs))
+ status := make(map[string]define.ContainerStatus, len(allCtrs))
for _, ctr := range allCtrs {
if err := ctr.syncContainer(); err != nil {
return nil, err
diff --git a/libpod/pod_top_linux.go b/libpod/pod_top_linux.go
index e08e5e83a..80221c3a9 100644
--- a/libpod/pod_top_linux.go
+++ b/libpod/pod_top_linux.go
@@ -6,6 +6,7 @@ import (
"strconv"
"strings"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/psgo"
)
@@ -34,7 +35,7 @@ func (p *Pod) GetPodPidInformation(descriptors []string) ([]string, error) {
c.lock.Unlock()
return nil, err
}
- if c.state.State == ContainerStateRunning {
+ if c.state.State == define.ContainerStateRunning {
pid := strconv.Itoa(c.state.PID)
pids = append(pids, pid)
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 152af031a..5a618f592 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -10,6 +10,7 @@ import (
"strings"
"sync"
"syscall"
+ "time"
"github.com/BurntSushi/toml"
is "github.com/containers/image/storage"
@@ -73,9 +74,8 @@ var (
OverrideConfigPath = etcDir + "/containers/libpod.conf"
// DefaultInfraImage to use for infra container
- DefaultInfraImage = "k8s.gcr.io/pause:3.1"
+
// DefaultInfraCommand to be run in an infra container
- DefaultInfraCommand = "/pause"
// DefaultSHMLockPath is the default path for SHM locks
DefaultSHMLockPath = "/libpod_lock"
@@ -285,14 +285,11 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
},
ConmonPath: []string{
"/usr/libexec/podman/conmon",
- "/usr/libexec/crio/conmon",
"/usr/local/lib/podman/conmon",
- "/usr/local/libexec/crio/conmon",
"/usr/bin/conmon",
"/usr/sbin/conmon",
"/usr/local/bin/conmon",
"/usr/local/sbin/conmon",
- "/usr/lib/crio/bin/conmon",
},
ConmonEnvVars: []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
@@ -305,8 +302,8 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
NoPivotRoot: false,
CNIConfigDir: etcDir + "/cni/net.d/",
CNIPluginDir: []string{"/usr/libexec/cni", "/usr/lib/cni", "/usr/local/lib/cni", "/opt/cni/bin"},
- InfraCommand: DefaultInfraCommand,
- InfraImage: DefaultInfraImage,
+ InfraCommand: define.DefaultInfraCommand,
+ InfraImage: define.DefaultInfraImage,
EnablePortReservation: true,
EnableLabeling: true,
NumLocks: 2048,
@@ -314,6 +311,46 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
}, nil
}
+// SetXdgRuntimeDir ensures the XDG_RUNTIME_DIR env variable is set
+// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
+// It internally calls EnableLinger() so that the user's processes are not
+// killed once the session is terminated. EnableLinger() also attempts to
+// get the runtime directory when XDG_RUNTIME_DIR is not specified.
+func SetXdgRuntimeDir() error {
+ if !rootless.IsRootless() {
+ return nil
+ }
+
+ runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
+
+ runtimeDirLinger, err := rootless.EnableLinger()
+ if err != nil {
+ return errors.Wrapf(err, "error enabling user session")
+ }
+ if runtimeDir == "" && runtimeDirLinger != "" {
+ if _, err := os.Stat(runtimeDirLinger); err != nil && os.IsNotExist(err) {
+ chWait := make(chan error)
+ defer close(chWait)
+ if _, err := WaitForFile(runtimeDirLinger, chWait, time.Second*10); err != nil {
+ return errors.Wrapf(err, "waiting for directory '%s'", runtimeDirLinger)
+ }
+ }
+ runtimeDir = runtimeDirLinger
+ }
+
+ if runtimeDir == "" {
+ var err error
+ runtimeDir, err = util.GetRootlessRuntimeDir()
+ if err != nil {
+ return err
+ }
+ }
+ if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil {
+ return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
+ }
+ return nil
+}
+
func getDefaultTmpDir() (string, error) {
if !rootless.IsRootless() {
return "/var/run/libpod", nil
@@ -336,25 +373,6 @@ func getDefaultTmpDir() (string, error) {
return filepath.Join(libpodRuntimeDir, "tmp"), nil
}
-// SetXdgRuntimeDir ensures the XDG_RUNTIME_DIR env variable is set
-// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
-func SetXdgRuntimeDir(val string) error {
- if !rootless.IsRootless() {
- return nil
- }
- if val == "" {
- var err error
- val, err = util.GetRootlessRuntimeDir()
- if err != nil {
- return err
- }
- }
- if err := os.Setenv("XDG_RUNTIME_DIR", val); err != nil {
- return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
- }
- return nil
-}
-
// NewRuntime creates a new container runtime
// Options can be passed to override the default configuration for the runtime
func NewRuntime(ctx context.Context, options ...RuntimeOption) (runtime *Runtime, err error) {
@@ -376,7 +394,7 @@ func NewRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
func homeDir() (string, error) {
home := os.Getenv("HOME")
if home == "" {
- usr, err := user.Current()
+ usr, err := user.LookupId(fmt.Sprintf("%d", rootless.GetRootlessUID()))
if err != nil {
return "", errors.Wrapf(err, "unable to resolve HOME directory")
}
@@ -394,28 +412,33 @@ func getRootlessConfigPath() (string, error) {
return filepath.Join(home, ".config/containers/libpod.conf"), nil
}
-func getConfigPath() string {
+func getConfigPath() (string, error) {
if rootless.IsRootless() {
- rootlessConfigPath, err := getRootlessConfigPath()
+ path, err := getRootlessConfigPath()
if err != nil {
- if _, err := os.Stat(rootlessConfigPath); err == nil {
- return rootlessConfigPath
- }
+ return "", err
+ }
+ if _, err := os.Stat(path); err == nil {
+ return path, nil
}
+ return "", err
}
if _, err := os.Stat(OverrideConfigPath); err == nil {
// Use the override configuration path
- return OverrideConfigPath
+ return OverrideConfigPath, nil
}
if _, err := os.Stat(ConfigPath); err == nil {
- return ConfigPath
+ return ConfigPath, nil
}
- return ""
+ return "", nil
}
// DefaultRuntimeConfig reads default config path and returns the RuntimeConfig
func DefaultRuntimeConfig() (*RuntimeConfig, error) {
- configPath := getConfigPath()
+ configPath, err := getConfigPath()
+ if err != nil {
+ return nil, err
+ }
contents, err := ioutil.ReadFile(configPath)
if err != nil {
@@ -463,8 +486,10 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes")
- configPath := getConfigPath()
- rootlessConfigPath := ""
+ configPath, err := getConfigPath()
+ if err != nil {
+ return nil, err
+ }
if rootless.IsRootless() {
home, err := homeDir()
if err != nil {
@@ -476,23 +501,6 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
runtime.config.SignaturePolicyPath = newPath
}
}
-
- rootlessConfigPath, err = getRootlessConfigPath()
- if err != nil {
- return nil, err
- }
-
- runtimeDir, err := util.GetRootlessRuntimeDir()
- if err != nil {
- return nil, err
- }
-
- // containers/image uses XDG_RUNTIME_DIR to locate the auth file.
- // So make sure the env variable is set.
- if err := SetXdgRuntimeDir(runtimeDir); err != nil {
- return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
- }
-
}
if userConfigPath != "" {
@@ -602,7 +610,13 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
return nil, errors.Wrapf(err, "error configuring runtime")
}
}
- if rootlessConfigPath != "" {
+
+ if rootless.IsRootless() && configPath == "" {
+ configPath, err := getRootlessConfigPath()
+ if err != nil {
+ return nil, err
+ }
+
// storage.conf
storageConfFile, err := storage.DefaultConfigFile(rootless.IsRootless())
if err != nil {
@@ -615,16 +629,16 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
}
if configPath != "" {
- os.MkdirAll(filepath.Dir(rootlessConfigPath), 0755)
- file, err := os.OpenFile(rootlessConfigPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ os.MkdirAll(filepath.Dir(configPath), 0755)
+ file, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
if err != nil && !os.IsExist(err) {
- return nil, errors.Wrapf(err, "cannot open file %s", rootlessConfigPath)
+ return nil, errors.Wrapf(err, "cannot open file %s", configPath)
}
if err == nil {
defer file.Close()
enc := toml.NewEncoder(file)
if err := enc.Encode(runtime.config); err != nil {
- os.Remove(rootlessConfigPath)
+ os.Remove(configPath)
}
}
}
@@ -1194,21 +1208,21 @@ func (r *Runtime) refresh(alivePath string) error {
}
// Info returns the store and host information
-func (r *Runtime) Info() ([]InfoData, error) {
- info := []InfoData{}
+func (r *Runtime) Info() ([]define.InfoData, error) {
+ info := []define.InfoData{}
// get host information
hostInfo, err := r.hostInfo()
if err != nil {
return nil, errors.Wrapf(err, "error getting host info")
}
- info = append(info, InfoData{Type: "host", Data: hostInfo})
+ info = append(info, define.InfoData{Type: "host", Data: hostInfo})
// get store information
storeInfo, err := r.storeInfo()
if err != nil {
return nil, errors.Wrapf(err, "error getting store info")
}
- info = append(info, InfoData{Type: "store", Data: storeInfo})
+ info = append(info, define.InfoData{Type: "store", Data: storeInfo})
reg, err := sysreg.GetRegistries()
if err != nil {
@@ -1228,7 +1242,7 @@ func (r *Runtime) Info() ([]InfoData, error) {
return nil, errors.Wrapf(err, "error getting registries")
}
registries["blocked"] = breg
- info = append(info, InfoData{Type: "registries", Data: registries})
+ info = append(info, define.InfoData{Type: "registries", Data: registries})
return info, nil
}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 79e18dcd1..0d0f700a6 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -133,7 +133,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container, restore bo
logrus.Debugf("Allocated lock %d for container %s", ctr.lock.ID(), ctr.ID())
ctr.valid = true
- ctr.state.State = ContainerStateConfigured
+ ctr.state.State = config2.ContainerStateConfigured
ctr.runtime = r
if ctr.config.OCIRuntime == "" {
@@ -370,7 +370,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
}
- if c.state.State == ContainerStatePaused {
+ if c.state.State == config2.ContainerStatePaused {
if err := c.ociRuntime.killContainer(c, 9); err != nil {
return err
}
@@ -384,7 +384,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
// Check that the container's in a good state to be removed
- if c.state.State == ContainerStateRunning {
+ if c.state.State == config2.ContainerStateRunning {
if err := c.ociRuntime.stopContainer(c, c.StopTimeout()); err != nil {
return errors.Wrapf(err, "cannot remove container %s as it could not be stopped", c.ID())
}
@@ -464,8 +464,8 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
// Delete the container.
// Not needed in Configured and Exited states, where the container
// doesn't exist in the runtime
- if c.state.State != ContainerStateConfigured &&
- c.state.State != ContainerStateExited {
+ if c.state.State != config2.ContainerStateConfigured &&
+ c.state.State != config2.ContainerStateExited {
if err := c.delete(ctx); err != nil {
if cleanupErr == nil {
cleanupErr = err
@@ -582,7 +582,7 @@ func (r *Runtime) GetAllContainers() ([]*Container, error) {
func (r *Runtime) GetRunningContainers() ([]*Container, error) {
running := func(c *Container) bool {
state, _ := c.State()
- return state == ContainerStateRunning
+ return state == config2.ContainerStateRunning
}
return r.GetContainers(running)
}
diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go
index e32e6edf6..ad45579d3 100644
--- a/libpod/runtime_migrate.go
+++ b/libpod/runtime_migrate.go
@@ -5,6 +5,7 @@ package libpod
import (
"context"
"fmt"
+ "github.com/containers/libpod/pkg/util"
"io/ioutil"
"os"
"path/filepath"
@@ -12,7 +13,6 @@ import (
"syscall"
"github.com/containers/libpod/pkg/rootless"
- "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
diff --git a/libpod/state_test.go b/libpod/state_test.go
index be68a2d69..26a1dee7d 100644
--- a/libpod/state_test.go
+++ b/libpod/state_test.go
@@ -8,6 +8,7 @@ import (
"testing"
"time"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/lock"
"github.com/containers/storage"
"github.com/stretchr/testify/assert"
@@ -700,7 +701,7 @@ func TestSaveAndUpdateContainer(t *testing.T) {
retrievedCtr, err := state.Container(testCtr.ID())
require.NoError(t, err)
- retrievedCtr.state.State = ContainerStateStopped
+ retrievedCtr.state.State = define.ContainerStateStopped
retrievedCtr.state.ExitCode = 127
retrievedCtr.state.FinishedTime = time.Now()
@@ -729,7 +730,7 @@ func TestSaveAndUpdateContainerSameNamespaceSucceeds(t *testing.T) {
retrievedCtr, err := state.Container(testCtr.ID())
assert.NoError(t, err)
- retrievedCtr.state.State = ContainerStateStopped
+ retrievedCtr.state.State = define.ContainerStateStopped
retrievedCtr.state.ExitCode = 127
retrievedCtr.state.FinishedTime = time.Now()
diff --git a/libpod/stats.go b/libpod/stats.go
index e003f145b..da383e9d9 100644
--- a/libpod/stats.go
+++ b/libpod/stats.go
@@ -26,7 +26,7 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
}
}
- if c.state.State != ContainerStateRunning {
+ if c.state.State != define.ContainerStateRunning {
return stats, define.ErrCtrStateInvalid
}
@@ -61,7 +61,7 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit)
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
stats.PIDs = 0
- if conState == ContainerStateRunning {
+ if conState == define.ContainerStateRunning {
stats.PIDs = cgroupStats.Pids.Current
}
stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
diff --git a/libpod/util.go b/libpod/util.go
index 7b3a03785..b0c25074b 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -24,17 +24,6 @@ const (
DefaultTransport = "docker://"
)
-// OpenExclusiveFile opens a file for writing and ensure it doesn't already exist
-func OpenExclusiveFile(path string) (*os.File, error) {
- baseDir := filepath.Dir(path)
- if baseDir != "" {
- if _, err := os.Stat(baseDir); err != nil {
- return nil, err
- }
- }
- return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
-}
-
// FuncTimer helps measure the execution time of a function
// For debug purposes, do not leave in code
// used like defer FuncTimer("foo")