summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/kpod/create.go81
-rw-r--r--cmd/kpod/run.go10
-rw-r--r--cmd/kpod/spec.go72
-rw-r--r--libpod/container.go140
-rw-r--r--libpod/oci.go5
-rw-r--r--libpod/options.go19
-rw-r--r--libpod/runtime_ctr.go13
-rw-r--r--libpod/sql_state.go11
-rw-r--r--libpod/sql_state_internal.go14
-rw-r--r--test/kpod_run_ns.bats18
10 files changed, 310 insertions, 73 deletions
diff --git a/cmd/kpod/create.go b/cmd/kpod/create.go
index 57dce6fbf..9a4539c14 100644
--- a/cmd/kpod/create.go
+++ b/cmd/kpod/create.go
@@ -81,20 +81,20 @@ type createConfig struct {
groupAdd []uint32 // group-add
hostname string //hostname
image string
- interactive bool //interactive
- ip6Address string //ipv6
- ipAddress string //ip
- labels map[string]string //label
- linkLocalIP []string // link-local-ip
- logDriver string // log-driver
- logDriverOpt []string // log-opt
- macAddress string //mac-address
- name string //name
- network string //network
- networkAlias []string //network-alias
- nsIPC string // ipc
- nsNET string //net
- pidMode container.PidMode //pid
+ interactive bool //interactive
+ ipcMode container.IpcMode //ipc
+ ip6Address string //ipv6
+ ipAddress string //ip
+ labels map[string]string //label
+ linkLocalIP []string // link-local-ip
+ logDriver string // log-driver
+ logDriverOpt []string // log-opt
+ macAddress string //mac-address
+ name string //name
+ netMode container.NetworkMode //net
+ network string //network
+ networkAlias []string //network-alias
+ pidMode container.PidMode //pid
nsUser string
pod string //pod
privileged bool //privileged
@@ -102,7 +102,8 @@ type createConfig struct {
publishAll bool //publish-all
readOnlyRootfs bool //read-only
resources createResourceConfig
- rm bool //rm
+ rm bool //rm
+ shmDir string
sigProxy bool //sig-proxy
stopSignal string // stop-signal
stopTimeout int64 // stop-timeout
@@ -112,6 +113,7 @@ type createConfig struct {
tty bool //tty
user uint32 //user
group uint32 // group
+ utsMode container.UTSMode //uts
volumes []string //volume
volumesFrom []string //volumes-from
workDir string //workdir
@@ -201,7 +203,8 @@ func createCmd(c *cli.Context) error {
}
// Gather up the options for NewContainer which consist of With... funcs
options = append(options, libpod.WithRootFSFromImage(imageID, imageName, false))
- options = append(options, libpod.WithSELinuxMountLabel(createConfig.mountLabel))
+ options = append(options, libpod.WithSELinuxLabels(createConfig.processLabel, createConfig.mountLabel))
+ options = append(options, libpod.WithShmDir(createConfig.shmDir))
ctr, err := runtime.NewContainer(runtimeSpec, options...)
if err != nil {
return err
@@ -230,6 +233,26 @@ func parseSecurityOpt(config *createConfig, securityOpts []string) error {
err error
)
+ if config.pidMode.IsHost() {
+ labelOpts = append(labelOpts, label.DisableSecOpt()...)
+ } else if config.pidMode.IsContainer() {
+ ctr, err := config.runtime.LookupContainer(config.pidMode.Container())
+ if err != nil {
+ return errors.Wrapf(err, "container %q not found", config.pidMode.Container())
+ }
+ labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...)
+ }
+
+ if config.ipcMode.IsHost() {
+ labelOpts = append(labelOpts, label.DisableSecOpt()...)
+ } else if config.ipcMode.IsContainer() {
+ ctr, err := config.runtime.LookupContainer(config.ipcMode.Container())
+ if err != nil {
+ return errors.Wrapf(err, "container %q not found", config.ipcMode.Container())
+ }
+ labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...)
+ }
+
for _, opt := range securityOpts {
if opt == "no-new-privileges" {
config.noNewPrivileges = true
@@ -354,6 +377,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
if !c.Bool("detach") && !tty {
tty = true
}
+
pidMode := container.PidMode(c.String("pid"))
if !pidMode.Valid() {
return nil, errors.Errorf("--pid %q is not valid", c.String("pid"))
@@ -363,6 +387,25 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
return nil, errors.Errorf("--rm and --detach can not be specified together")
}
+ utsMode := container.UTSMode(c.String("uts"))
+ if !utsMode.Valid() {
+ return nil, errors.Errorf("--uts %q is not valid", c.String("uts"))
+ }
+ ipcMode := container.IpcMode(c.String("ipc"))
+ if !ipcMode.Valid() {
+ return nil, errors.Errorf("--ipc %q is not valid", ipcMode)
+ }
+ shmDir := ""
+ if ipcMode.IsHost() {
+ shmDir = "/dev/shm"
+ } else if ipcMode.IsContainer() {
+ ctr, err := runtime.LookupContainer(ipcMode.Container())
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", ipcMode.Container())
+ }
+ shmDir = ctr.ShmDir()
+ }
+
config := &createConfig{
runtime: runtime,
capAdd: c.StringSlice("cap-add"),
@@ -390,8 +433,9 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
name: c.String("name"),
network: c.String("network"),
networkAlias: c.StringSlice("network-alias"),
- nsIPC: c.String("ipc"),
- nsNET: c.String("net"),
+ ipcMode: ipcMode,
+ netMode: container.NetworkMode(c.String("network")),
+ utsMode: utsMode,
pidMode: pidMode,
pod: c.String("pod"),
privileged: c.Bool("privileged"),
@@ -426,6 +470,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
ulimit: c.StringSlice("ulimit"),
},
rm: c.Bool("rm"),
+ shmDir: shmDir,
sigProxy: c.Bool("sig-proxy"),
stopSignal: c.String("stop-signal"),
stopTimeout: c.Int64("stop-timeout"),
diff --git a/cmd/kpod/run.go b/cmd/kpod/run.go
index ec68d8b97..eb3dee88c 100644
--- a/cmd/kpod/run.go
+++ b/cmd/kpod/run.go
@@ -85,9 +85,11 @@ func runCmd(c *cli.Context) error {
if err != nil {
return errors.Wrapf(err, "unable to parse new container options")
}
+
// Gather up the options for NewContainer which consist of With... funcs
options = append(options, libpod.WithRootFSFromImage(imageID, imageName, false))
- options = append(options, libpod.WithSELinuxMountLabel(createConfig.mountLabel))
+ options = append(options, libpod.WithSELinuxLabels(createConfig.processLabel, createConfig.mountLabel))
+ options = append(options, libpod.WithShmDir(createConfig.shmDir))
ctr, err := runtime.NewContainer(runtimeSpec, options...)
if err != nil {
return err
@@ -130,14 +132,14 @@ func runCmd(c *cli.Context) error {
if err := ctr.Start(); err != nil {
return errors.Wrapf(err, "unable to start container %q", ctr.ID())
}
- logrus.Debug("started container ", ctr.ID())
-
if createConfig.detach {
fmt.Printf("%s\n", ctr.ID())
+ return nil
}
wg.Wait()
+
if createConfig.rm {
return runtime.RemoveContainer(ctr, true)
}
- return nil
+ return ctr.CleanupStorage()
}
diff --git a/cmd/kpod/spec.go b/cmd/kpod/spec.go
index 8d9189a0d..b2a439a9b 100644
--- a/cmd/kpod/spec.go
+++ b/cmd/kpod/spec.go
@@ -49,7 +49,7 @@ func blockAccessToKernelFilesystems(config *createConfig, g *generate.Generator)
func addPidNS(config *createConfig, g *generate.Generator) error {
pidMode := config.pidMode
if pidMode.IsHost() {
- return g.RemoveLinuxNamespace("pid")
+ return g.RemoveLinuxNamespace(libpod.PIDNamespace)
}
if pidMode.IsContainer() {
ctr, err := config.runtime.LookupContainer(pidMode.Container())
@@ -68,6 +68,65 @@ func addPidNS(config *createConfig, g *generate.Generator) error {
return nil
}
+func addNetNS(config *createConfig, g *generate.Generator) error {
+ netMode := config.netMode
+ if netMode.IsHost() {
+ return g.RemoveLinuxNamespace(libpod.NetNamespace)
+ }
+ if netMode.IsNone() {
+ return libpod.ErrNotImplemented
+ }
+ if netMode.IsBridge() {
+ return libpod.ErrNotImplemented
+ }
+ if netMode.IsContainer() {
+ ctr, err := config.runtime.LookupContainer(netMode.ConnectedContainer())
+ if err != nil {
+ return errors.Wrapf(err, "container %q not found", netMode.ConnectedContainer())
+ }
+ pid, err := ctr.PID()
+ if err != nil {
+ return errors.Wrapf(err, "Failed to get pid of container %q", netMode.ConnectedContainer())
+ }
+ nsPath := fmt.Sprintf("/proc/%d/ns/net", pid)
+ if err := g.AddOrReplaceLinuxNamespace(libpod.NetNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func addUTSNS(config *createConfig, g *generate.Generator) error {
+ utsMode := config.utsMode
+ if utsMode.IsHost() {
+ return g.RemoveLinuxNamespace(libpod.UTSNamespace)
+ }
+ return nil
+}
+
+func addIpcNS(config *createConfig, g *generate.Generator) error {
+ ipcMode := config.ipcMode
+ if ipcMode.IsHost() {
+ return g.RemoveLinuxNamespace(libpod.IPCNamespace)
+ }
+ if ipcMode.IsContainer() {
+ ctr, err := config.runtime.LookupContainer(ipcMode.Container())
+ if err != nil {
+ return errors.Wrapf(err, "container %q not found", ipcMode.Container())
+ }
+ pid, err := ctr.PID()
+ if err != nil {
+ return errors.Wrapf(err, "Failed to get pid of container %q", ipcMode.Container())
+ }
+ nsPath := fmt.Sprintf("/proc/%d/ns/ipc", pid)
+ if err := g.AddOrReplaceLinuxNamespace(libpod.IPCNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
func addRlimits(config *createConfig, g *generate.Generator) error {
var (
ul *units.Ulimit
@@ -210,6 +269,17 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
return nil, err
}
+ if err := addNetNS(config, &g); err != nil {
+ return nil, err
+ }
+
+ if err := addUTSNS(config, &g); err != nil {
+ return nil, err
+ }
+
+ if err := addIpcNS(config, &g); err != nil {
+ return nil, err
+ }
configSpec := g.Spec()
if config.seccompProfilePath != "" && config.seccompProfilePath != "unconfined" {
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
+}
diff --git a/libpod/oci.go b/libpod/oci.go
index 4abbc5122..6ea6bb64f 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -37,6 +37,11 @@ const (
// Timeout before declaring that runc has failed to kill a given container
killContainerTimeout = 5 * time.Second
+ // DefaultShmSize is the default shm size
+ DefaultShmSize = 64 * 1024 * 1024
+ // NsRunDir is the default directory in which running network namespaces
+ // are stored
+ NsRunDir = "/var/run/netns"
)
// OCIRuntime represents an OCI-compatible runtime that libpod can call into
diff --git a/libpod/options.go b/libpod/options.go
index 59141115d..07c25faf9 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -21,7 +21,7 @@ const (
// MountNamespace represents the mount namespace
MountNamespace = "mount"
// NetNamespace represents the network namespace
- NetNamespace = "net"
+ NetNamespace = "network"
// PIDNamespace represents the PID namespace
PIDNamespace = "pid"
// UserNamespace represents the user namespace
@@ -252,13 +252,26 @@ func WithNoPivotRoot(noPivot bool) RuntimeOption {
// Container Creation Options
-// WithSELinuxMountLabel sets the mount label for SELinux
-func WithSELinuxMountLabel(mountLabel string) CtrCreateOption {
+// WithShmDir sets the directory that should be mounted on /dev/shm
+func WithShmDir(dir string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
}
+ ctr.config.ShmDir = dir
+ return nil
+ }
+}
+
+// WithSELinuxLabels sets the mount label for SELinux
+func WithSELinuxLabels(processLabel, mountLabel string) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return ErrCtrFinalized
+ }
+
+ ctr.config.ProcessLabel = processLabel
ctr.config.MountLabel = mountLabel
return nil
}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 58074cc43..5fb29abb5 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -1,6 +1,9 @@
package libpod
import (
+ "os"
+ "path/filepath"
+
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -54,6 +57,16 @@ func (r *Runtime) NewContainer(spec *spec.Spec, options ...CtrCreateOption) (c *
}
}()
+ if ctr.config.ShmDir == "" {
+ ctr.config.ShmDir = filepath.Join(ctr.bundlePath(), "shm")
+ if err := os.MkdirAll(ctr.config.ShmDir, 0700); err != nil {
+ if !os.IsExist(err) {
+ return nil, errors.Wrapf(err, "unable to create shm %q dir", ctr.config.ShmDir)
+ }
+ }
+ ctr.config.Mounts = append(ctr.config.Mounts, ctr.config.ShmDir)
+ }
+
// If the container is in a pod, add it to the pod
if ctr.pod != nil {
if err := ctr.pod.addContainer(ctr); err != nil {
diff --git a/libpod/sql_state.go b/libpod/sql_state.go
index 7c2061fca..fb6be85d7 100644
--- a/libpod/sql_state.go
+++ b/libpod/sql_state.go
@@ -16,7 +16,7 @@ import (
// DBSchema is the current DB schema version
// Increments every time a change is made to the database's tables
-const DBSchema = 1
+const DBSchema = 2
// SQLState is a state implementation backed by a persistent SQLite3 database
type SQLState struct {
@@ -230,7 +230,7 @@ func (s *SQLState) HasContainer(id string) (bool, error) {
func (s *SQLState) AddContainer(ctr *Container) (err error) {
const (
addCtr = `INSERT INTO containers VALUES (
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
);`
addCtrState = `INSERT INTO containerState VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?
@@ -265,11 +265,18 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
}
}()
+ mounts, err := json.Marshal(ctr.config.Mounts)
+ if err != nil {
+ return errors.Wrapf(err, "error marshaling container %s monunts to JSON", ctr.ID())
+ }
// Add static container information
_, err = tx.Exec(addCtr,
ctr.ID(),
ctr.Name(),
+ ctr.config.ProcessLabel,
ctr.config.MountLabel,
+ string(mounts),
+ ctr.config.ShmDir,
ctr.config.StaticDir,
boolToSQL(ctr.config.Stdin),
string(labelsJSON),
diff --git a/libpod/sql_state_internal.go b/libpod/sql_state_internal.go
index 6e0142b9b..3aee8f638 100644
--- a/libpod/sql_state_internal.go
+++ b/libpod/sql_state_internal.go
@@ -166,7 +166,10 @@ func prepareDB(db *sql.DB) (err error) {
CREATE TABLE IF NOT EXISTS containers(
Id TEXT NOT NULL PRIMARY KEY,
Name TEXT NOT NULL UNIQUE,
+ ProcessLabel TEXT NOT NULL,
MountLabel TEXT NOT NULL,
+ Mounts TEXT NOT NULL,
+ ShmDir TEXT NOT NULL,
StaticDir TEXT NOT NULL,
Stdin INTEGER NOT NULL,
LabelsJSON TEXT NOT NULL,
@@ -267,7 +270,10 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string) (*Contai
var (
id string
name string
+ processLabel string
mountLabel string
+ mounts string
+ shmDir string
staticDir string
stdin int
labelsJSON string
@@ -290,7 +296,10 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string) (*Contai
err := row.Scan(
&id,
&name,
+ &processLabel,
&mountLabel,
+ &mounts,
+ &shmDir,
&staticDir,
&stdin,
&labelsJSON,
@@ -325,7 +334,12 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string) (*Contai
ctr.config.RootfsImageID = rootfsImageID
ctr.config.RootfsImageName = rootfsImageName
ctr.config.UseImageConfig = boolFromSQL(useImageConfig)
+ ctr.config.ProcessLabel = processLabel
ctr.config.MountLabel = mountLabel
+ if err := json.Unmarshal([]byte(mounts), &ctr.config.Mounts); err != nil {
+ return nil, errors.Wrapf(err, "error parsing container %s mounts JSON", id)
+ }
+ ctr.config.ShmDir = shmDir
ctr.config.StaticDir = staticDir
ctr.config.Stdin = boolFromSQL(stdin)
ctr.config.StopSignal = stopSignal
diff --git a/test/kpod_run_ns.bats b/test/kpod_run_ns.bats
index 233f8158b..c1b269587 100644
--- a/test/kpod_run_ns.bats
+++ b/test/kpod_run_ns.bats
@@ -30,3 +30,21 @@ function setup() {
echo $output
[ "$status" -ne 0 ]
}
+
+@test "run ipcns test" {
+
+ ${KPOD_BINARY} ${KPOD_OPTIONS} pull ${ALPINE}
+
+ tmp=$(mktemp /dev/shm/foo.XXXXX)
+ run ${KPOD_BINARY} ${KPOD_OPTIONS} run --ipc=host ${ALPINE} ls $tmp
+ echo $output
+ out=$(echo $output | tr -d '\r')
+ [ "$status" -eq 0 ]
+ [ $out != $tmp ]
+
+ rm -f $tmp
+
+ run ${KPOD_BINARY} ${KPOD_OPTIONS} run --ipc=badpid ${ALPINE} sh -c 'echo $$'
+ echo $output
+ [ "$status" -ne 0 ]
+}