summaryrefslogtreecommitdiff
path: root/libpod/container_internal.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2019-10-08 13:53:36 -0400
committerMatthew Heon <matthew.heon@pm.me>2019-10-10 10:19:32 -0400
commit6f630bc09b3e937fe3ddc4a829715bacd5b6c779 (patch)
tree4f95293e4673bd5f046847c6b669bf124e57e90c /libpod/container_internal.go
parenta7f266891ca20214f56d0bb742896e9112f4905a (diff)
downloadpodman-6f630bc09b3e937fe3ddc4a829715bacd5b6c779.tar.gz
podman-6f630bc09b3e937fe3ddc4a829715bacd5b6c779.tar.bz2
podman-6f630bc09b3e937fe3ddc4a829715bacd5b6c779.zip
Move OCI runtime implementation behind an interface
For future work, we need multiple implementations of the OCI runtime, not just a Conmon-wrapped runtime matching the runc CLI. As part of this, do some refactoring on the interface for exec (move to a struct, not a massive list of arguments). Also, add 'all' support to Kill and Stop (supported by runc and used a bit internally for removing containers). Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod/container_internal.go')
-rw-r--r--libpod/container_internal.go78
1 files changed, 51 insertions, 27 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index ac921d737..e7f541c52 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -131,13 +131,13 @@ func (c *Container) CheckpointPath() string {
}
// AttachSocketPath retrieves the path of the container's attach socket
-func (c *Container) AttachSocketPath() string {
- return filepath.Join(c.ociRuntime.socketsDir, c.ID(), "attach")
+func (c *Container) AttachSocketPath() (string, error) {
+ return c.ociRuntime.AttachSocketPath(c)
}
// exitFilePath gets the path to the container's exit file
-func (c *Container) exitFilePath() string {
- return filepath.Join(c.ociRuntime.exitsDir, c.ID())
+func (c *Container) exitFilePath() (string, error) {
+ return c.ociRuntime.ExitFilePath(c)
}
// create a bundle path and associated files for an exec session
@@ -167,12 +167,8 @@ func (c *Container) cleanupExecBundle(sessionID string) error {
if err := os.RemoveAll(c.execBundlePath(sessionID)); err != nil && !os.IsNotExist(err) {
return err
}
- // Clean up the sockets dir. Issue #3962
- // Also ignore if it doesn't exist for some reason; hence the conditional return below
- if err := os.RemoveAll(filepath.Join(c.ociRuntime.socketsDir, sessionID)); err != nil && !os.IsNotExist(err) {
- return err
- }
- return nil
+
+ return c.ociRuntime.ExecContainerCleanup(c, sessionID)
}
// the path to a containers exec session bundle
@@ -191,8 +187,8 @@ func (c *Container) execLogPath(sessionID string) string {
}
// the socket conmon creates for an exec session
-func (c *Container) execAttachSocketPath(sessionID string) string {
- return filepath.Join(c.ociRuntime.socketsDir, sessionID, "attach")
+func (c *Container) execAttachSocketPath(sessionID string) (string, error) {
+ return c.ociRuntime.ExecAttachSocketPath(c, sessionID)
}
// execExitFileDir gets the path to the container's exit file
@@ -202,7 +198,7 @@ func (c *Container) execExitFileDir(sessionID string) string {
// execOCILog returns the file path for the exec sessions oci log
func (c *Container) execOCILog(sessionID string) string {
- if !c.ociRuntime.supportsJSON {
+ if !c.ociRuntime.SupportsJSONErrors() {
return ""
}
return filepath.Join(c.execBundlePath(sessionID), "oci-log")
@@ -233,12 +229,15 @@ func (c *Container) readExecExitCode(sessionID string) (int, error) {
// Wait for the container's exit file to appear.
// When it does, update our state based on it.
func (c *Container) waitForExitFileAndSync() error {
- exitFile := c.exitFilePath()
+ exitFile, err := c.exitFilePath()
+ if err != nil {
+ return err
+ }
chWait := make(chan error)
defer close(chWait)
- _, err := WaitForFile(exitFile, chWait, time.Second*5)
+ _, err = WaitForFile(exitFile, chWait, time.Second*5)
if err != nil {
// Exit file did not appear
// Reset our state
@@ -253,7 +252,7 @@ func (c *Container) waitForExitFileAndSync() error {
return err
}
- if err := c.ociRuntime.updateContainerStatus(c, false); err != nil {
+ if err := c.ociRuntime.UpdateContainerStatus(c, false); err != nil {
return err
}
@@ -388,7 +387,7 @@ func (c *Container) syncContainer() error {
(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 {
+ if err := c.ociRuntime.UpdateContainerStatus(c, false); err != nil {
return err
}
// Only save back to DB if state changed
@@ -649,7 +648,10 @@ func (c *Container) removeConmonFiles() error {
}
// Remove the exit file so we don't leak memory in tmpfs
- exitFile := filepath.Join(c.ociRuntime.exitsDir, c.ID())
+ exitFile, err := c.exitFilePath()
+ if err != nil {
+ return err
+ }
if err := os.Remove(exitFile); err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "error removing container %s exit file", c.ID())
}
@@ -938,9 +940,13 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
}
// With the spec complete, do an OCI create
- if err := c.ociRuntime.createContainer(c, nil); err != nil {
+ if err := c.ociRuntime.CreateContainer(c, nil); err != nil {
+ // Fedora 31 is carrying a patch to display improved error
+ // messages to better handle the V2 transition. This is NOT
+ // upstream in any OCI runtime.
+ // TODO: Remove once runc supports cgroupsv2
if strings.Contains(err.Error(), "this version of runc doesn't work on cgroups v2") {
- logrus.Errorf("oci runtime %q does not support CGroups V2: use system migrate to mitigate", c.ociRuntime.name)
+ logrus.Errorf("oci runtime %q does not support CGroups V2: use system migrate to mitigate", c.ociRuntime.Name())
}
return err
}
@@ -1088,7 +1094,7 @@ func (c *Container) start() error {
logrus.Debugf("Starting container %s with command %v", c.ID(), c.config.Spec.Process.Args)
}
- if err := c.ociRuntime.startContainer(c); err != nil {
+ if err := c.ociRuntime.StartContainer(c); err != nil {
return err
}
logrus.Debugf("Started container %s", c.ID())
@@ -1110,10 +1116,28 @@ func (c *Container) start() error {
}
// Internal, non-locking function to stop container
-func (c *Container) stop(timeout uint) error {
+func (c *Container) stop(timeout uint, all bool) error {
logrus.Debugf("Stopping ctr %s (timeout %d)", c.ID(), timeout)
- if err := c.ociRuntime.stopContainer(c, timeout); err != nil {
+ // We can't use --all if CGroups aren't present.
+ // Rootless containers with CGroups v1 and NoCgroups are both cases
+ // where this can happen.
+ if all {
+ if c.config.NoCgroups {
+ all = false
+ } else if rootless.IsRootless() {
+ // Only do this check if we need to
+ unified, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ return err
+ }
+ if !unified {
+ all = false
+ }
+ }
+ }
+
+ if err := c.ociRuntime.StopContainer(c, timeout, all); err != nil {
return err
}
@@ -1150,7 +1174,7 @@ func (c *Container) pause() error {
}
}
- if err := c.ociRuntime.pauseContainer(c); err != nil {
+ if err := c.ociRuntime.PauseContainer(c); err != nil {
return err
}
@@ -1167,7 +1191,7 @@ func (c *Container) unpause() error {
return errors.Wrapf(define.ErrNoCgroups, "cannot unpause without using CGroups")
}
- if err := c.ociRuntime.unpauseContainer(c); err != nil {
+ if err := c.ociRuntime.UnpauseContainer(c); err != nil {
return err
}
@@ -1188,7 +1212,7 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
if c.state.State == define.ContainerStateRunning {
conmonPID := c.state.ConmonPID
- if err := c.stop(timeout); err != nil {
+ if err := c.stop(timeout, false); err != nil {
return err
}
// Old versions of conmon have a bug where they create the exit file before
@@ -1475,7 +1499,7 @@ func (c *Container) delete(ctx context.Context) (err error) {
span.SetTag("struct", "container")
defer span.Finish()
- if err := c.ociRuntime.deleteContainer(c); err != nil {
+ if err := c.ociRuntime.DeleteContainer(c); err != nil {
return errors.Wrapf(err, "error removing container %s from runtime", c.ID())
}