aboutsummaryrefslogtreecommitdiff
path: root/libpod/container.go
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2017-11-30 09:37:57 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2017-12-02 15:32:56 +0000
commitadf8809521733283c364ec7de27c783e324185e8 (patch)
tree427ed0c858ee54e760d0b3691e61765cd7429098 /libpod/container.go
parent1f01faf4375b2dc667b2794e4decdf360d6e32b8 (diff)
downloadpodman-adf8809521733283c364ec7de27c783e324185e8.tar.gz
podman-adf8809521733283c364ec7de27c783e324185e8.tar.bz2
podman-adf8809521733283c364ec7de27c783e324185e8.zip
Add NetMode, UTSMode and IPCMode
Allow kpod create/run to create contianers in different network namespaces, uts namespaces and IPC Namespaces. This patch just handles the simple join the host, or another containers namespaces. Lots more work needed to full integrate --net Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #64 Approved by: mheon
Diffstat (limited to 'libpod/container.go')
-rw-r--r--libpod/container.go140
1 files changed, 95 insertions, 45 deletions
diff --git a/libpod/container.go b/libpod/container.go
index e69037353..31fbbbcc5 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -7,19 +7,25 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "strconv"
"sync"
+ "syscall"
"time"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
+ "github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/term"
spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
crioAnnotations "github.com/projectatomic/libpod/pkg/annotations"
"github.com/sirupsen/logrus"
"github.com/ulule/deepcopier"
+ "golang.org/x/sys/unix"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/remotecommand"
)
@@ -86,7 +92,6 @@ type containerRuntimeInfo struct {
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
}
@@ -101,8 +106,12 @@ type ContainerConfig struct {
RootfsImageID string `json:"rootfsImageID,omitempty"`
RootfsImageName string `json:"rootfsImageName,omitempty"`
UseImageConfig bool `json:"useImageConfig"`
+ // SELinux process label for container
+ ProcessLabel string `json:"ProcessLabel,omitempty"`
// SELinux mount label for root filesystem
MountLabel string `json:"MountLabel,omitempty"`
+ // Src path to be mounted on /dev/shm in container
+ ShmDir string `json:"ShmDir,omitempty"`
// Static directory for container content that will persist across
// reboot
StaticDir string `json:"staticDir"`
@@ -113,6 +122,8 @@ type ContainerConfig struct {
// Labels is a set of key-value pairs providing additional information
// about a container
Labels map[string]string `json:"labels,omitempty"`
+ // Mounts list contains all additional mounts by the container runtime.
+ Mounts []string
// StopSignal is the signal that will be used to stop the container
StopSignal uint `json:"stopSignal,omitempty"`
// Shared namespaces with container
@@ -120,7 +131,6 @@ type ContainerConfig struct {
SharedNamespaceMap map[string]string `json:"sharedNamespaces"`
// Time container was created
CreatedTime time.Time `json:"createdTime"`
-
// TODO save log location here and pass into OCI code
// TODO allow overriding of log path
}
@@ -155,6 +165,16 @@ func (c *Container) Name() string {
return c.config.Name
}
+// ShmDir returns the sources path to be mounted on /dev/shm in container
+func (c *Container) ShmDir() string {
+ return c.config.ShmDir
+}
+
+// ProcessLabel returns the selinux ProcessLabel of the container
+func (c *Container) ProcessLabel() string {
+ return c.config.ProcessLabel
+}
+
// Spec returns the container's OCI runtime spec
// 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
@@ -307,7 +327,7 @@ func (c *Container) syncContainer() error {
if err := c.runtime.ociRuntime.updateContainerStatus(c); err != nil {
return err
}
- if err := c.runtime.state.SaveContainer(c); err != nil {
+ if err := c.save(); err != nil {
return err
}
}
@@ -376,13 +396,8 @@ func (c *Container) teardownStorage() error {
return errors.Wrapf(ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID())
}
- if c.state.Mounted {
- if err := c.runtime.storageService.StopContainer(c.ID()); err != nil {
- return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID())
- }
-
- c.state.Mounted = false
- c.state.Mountpoint = ""
+ if err := c.cleanupStorage(); err != nil {
+ return errors.Wrapf(err, "failed to cleanup container %s storage", c.ID())
}
if err := c.runtime.storageService.DeleteContainer(c.ID()); err != nil {
@@ -426,8 +441,10 @@ func (c *Container) Init() (err error) {
}()
// Make the OCI runtime spec we will use
- c.runningSpec = new(spec.Spec)
- deepcopier.Copy(c.config.Spec).To(c.runningSpec)
+ g := generate.NewFromSpec(c.config.Spec)
+ // Mount ShmDir from host into container
+ g.AddBindMount(c.config.ShmDir, "/dev/shm", []string{"rw"})
+ c.runningSpec = g.Spec()
c.runningSpec.Root.Path = c.state.Mountpoint
c.runningSpec.Annotations[crioAnnotations.Created] = c.config.CreatedTime.Format(time.RFC3339Nano)
c.runningSpec.Annotations["org.opencontainers.image.stopSignal"] = fmt.Sprintf("%d", c.config.StopSignal)
@@ -455,11 +472,7 @@ func (c *Container) Init() (err error) {
c.state.State = ContainerStateCreated
- if err := c.runtime.state.SaveContainer(c); err != nil {
- return errors.Wrapf(err, "error saving container %s state", c.ID())
- }
-
- return nil
+ return c.save()
}
// Start starts a container
@@ -471,6 +484,19 @@ func (c *Container) Start() error {
return err
}
+ mounted, err := mount.Mounted(c.config.ShmDir)
+ if err != nil {
+ return errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir)
+ }
+
+ if !mounted {
+ shmOptions := "mode=1777,size=" + strconv.Itoa(DefaultShmSize)
+ if err := unix.Mount("shm", c.config.ShmDir, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV,
+ label.FormatMountLabel(shmOptions, c.config.MountLabel)); err != nil {
+ return errors.Wrapf(err, "failed to mount shm tmpfs %q", c.config.ShmDir)
+ }
+ }
+
// Container must be created or stopped to be started
if !(c.state.State == ContainerStateCreated || c.state.State == ContainerStateStopped) {
return errors.Wrapf(ErrCtrStateInvalid, "container %s must be in Created or Stopped state to be started", c.ID())
@@ -510,11 +536,7 @@ func (c *Container) Start() error {
return err
}
- if err := c.runtime.state.SaveContainer(c); err != nil {
- return errors.Wrapf(err, "error saving container %s state", c.ID())
- }
-
- return nil
+ return c.save()
}
// Stop uses the container's stop signal (or SIGTERM if no signal was specified)
@@ -544,18 +566,7 @@ func (c *Container) Stop(timeout int64) error {
return err
}
- // Also unmount storage
- if err := c.runtime.storageService.StopContainer(c.ID()); err != nil {
- return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID())
- }
- c.state.Mountpoint = ""
- c.state.Mounted = false
-
- if err := c.runtime.state.SaveContainer(c); err != nil {
- return errors.Wrapf(err, "error saving container %s state", c.ID())
- }
-
- return nil
+ return c.cleanupStorage()
}
// Kill sends a signal to a container
@@ -638,8 +649,8 @@ func (c *Container) Mount(label string) (string, error) {
c.state.Mounted = true
c.config.MountLabel = mountLabel
- if err := c.runtime.state.SaveContainer(c); err != nil {
- return "", errors.Wrapf(err, "error saving container %s state", c.ID())
+ if err := c.save(); err != nil {
+ return "", err
}
return mountPoint, nil
@@ -669,7 +680,7 @@ func (c *Container) Unmount() error {
c.state.Mountpoint = ""
c.state.Mounted = false
- return c.runtime.state.SaveContainer(c)
+ return c.save()
}
// Pause pauses a container
@@ -698,10 +709,7 @@ func (c *Container) Pause() error {
return err
}
- if err := c.runtime.state.SaveContainer(c); err != nil {
- return errors.Wrapf(err, "error saving container %s state", c.ID())
- }
- return nil
+ return c.save()
}
// Unpause unpauses a container
@@ -727,10 +735,7 @@ func (c *Container) Unpause() error {
return err
}
- if err := c.runtime.state.SaveContainer(c); err != nil {
- return errors.Wrapf(err, "error saving container %s state", c.ID())
- }
- return nil
+ return c.save()
}
// Export exports a container's root filesystem as a tar archive
@@ -809,3 +814,48 @@ func (c *Container) isStopped() (bool, error) {
}
return c.state.State == ContainerStateStopped, nil
}
+
+// nil container state to the database
+func (c *Container) save() error {
+ if err := c.runtime.state.SaveContainer(c); err != nil {
+ return errors.Wrapf(err, "error saving container %s state", c.ID())
+ }
+ return nil
+}
+
+// CleanupStorage unmounts all mount points in container and cleans up container storage
+func (c *Container) CleanupStorage() error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ if err := c.syncContainer(); err != nil {
+ return err
+ }
+ return c.cleanupStorage()
+}
+
+func (c *Container) cleanupStorage() error {
+
+ if c.state.Mounted {
+ for _, mount := range c.config.Mounts {
+ if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil {
+ if err != syscall.EINVAL {
+ logrus.Warnf("container %s failed to unmount %s : %v", c.ID(), mount, err)
+ }
+ }
+ }
+ c.config.Mounts = []string{}
+
+ // Also unmount storage
+ if err := c.runtime.storageService.StopContainer(c.ID()); err != nil {
+ return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID())
+ }
+ }
+
+ c.state.Mountpoint = ""
+ c.state.Mounted = false
+
+ if err := c.runtime.state.SaveContainer(c); err != nil {
+ return errors.Wrapf(err, "error saving container %s state", c.ID())
+ }
+ return nil
+}