diff options
-rw-r--r-- | cmd/kpod/create.go | 81 | ||||
-rw-r--r-- | cmd/kpod/run.go | 10 | ||||
-rw-r--r-- | cmd/kpod/spec.go | 72 | ||||
-rw-r--r-- | libpod/container.go | 140 | ||||
-rw-r--r-- | libpod/oci.go | 5 | ||||
-rw-r--r-- | libpod/options.go | 19 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 13 | ||||
-rw-r--r-- | libpod/sql_state.go | 11 | ||||
-rw-r--r-- | libpod/sql_state_internal.go | 14 | ||||
-rw-r--r-- | test/kpod_run_ns.bats | 18 |
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 ] +} |