diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2018-01-11 17:41:59 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-01-16 14:58:06 +0000 |
commit | d2ec1f76287a55d05ef1378fa31d5474c2bcc0bf (patch) | |
tree | 76b28c21de1167a85f04f6a9c596f8c17702b671 | |
parent | 2ac4192bd3674577c6ab51d6d53a16cb291d0196 (diff) | |
download | podman-d2ec1f76287a55d05ef1378fa31d5474c2bcc0bf.tar.gz podman-d2ec1f76287a55d05ef1378fa31d5474c2bcc0bf.tar.bz2 podman-d2ec1f76287a55d05ef1378fa31d5474c2bcc0bf.zip |
Add API for sharing namespaces
Remove existing code for sharing namespaces and replace with use
of this API
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Closes: #220
Approved by: rhatdan
-rw-r--r-- | cmd/podman/spec.go | 73 | ||||
-rw-r--r-- | libpod/container.go | 1 | ||||
-rw-r--r-- | libpod/options.go | 190 |
3 files changed, 193 insertions, 71 deletions
diff --git a/cmd/podman/spec.go b/cmd/podman/spec.go index 4c17bb62c..35c6ef130 100644 --- a/cmd/podman/spec.go +++ b/cmd/podman/spec.go @@ -2,7 +2,6 @@ package main import ( "encoding/json" - "fmt" "io/ioutil" "strings" @@ -53,21 +52,10 @@ func blockAccessToKernelFilesystems(config *createConfig, g *generate.Generator) func addPidNS(config *createConfig, g *generate.Generator) error { pidMode := config.PidMode if pidMode.IsHost() { - return g.RemoveLinuxNamespace(libpod.PIDNamespace) + return g.RemoveLinuxNamespace(string(spec.PIDNamespace)) } if pidMode.IsContainer() { - ctr, err := config.Runtime.LookupContainer(pidMode.Container()) - if err != nil { - return errors.Wrapf(err, "container %q not found", pidMode.Container()) - } - pid, err := ctr.PID() - if err != nil { - return errors.Wrapf(err, "Failed to get pid of container %q", pidMode.Container()) - } - pidNsPath := fmt.Sprintf("/proc/%d/ns/pid", pid) - if err := g.AddOrReplaceLinuxNamespace(libpod.PIDNamespace, pidNsPath); err != nil { - return err - } + logrus.Debug("using container pidmode") } return nil } @@ -76,7 +64,7 @@ func addNetNS(config *createConfig, g *generate.Generator) error { netMode := config.NetMode if netMode.IsHost() { logrus.Debug("Using host netmode") - return g.RemoveLinuxNamespace(libpod.NetNamespace) + return g.RemoveLinuxNamespace(spec.NetworkNamespace) } else if netMode.IsNone() { logrus.Debug("Using none netmode") return nil @@ -85,18 +73,6 @@ func addNetNS(config *createConfig, g *generate.Generator) error { return nil } else if netMode.IsContainer() { logrus.Debug("Using container netmode") - 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 - } } else { return errors.Errorf("unknown network mode") } @@ -106,7 +82,7 @@ func addNetNS(config *createConfig, g *generate.Generator) error { func addUTSNS(config *createConfig, g *generate.Generator) error { utsMode := config.UtsMode if utsMode.IsHost() { - return g.RemoveLinuxNamespace(libpod.UTSNamespace) + return g.RemoveLinuxNamespace(spec.UTSNamespace) } return nil } @@ -114,21 +90,10 @@ func addUTSNS(config *createConfig, g *generate.Generator) error { func addIpcNS(config *createConfig, g *generate.Generator) error { ipcMode := config.IpcMode if ipcMode.IsHost() { - return g.RemoveLinuxNamespace(libpod.IPCNamespace) + return g.RemoveLinuxNamespace(spec.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 - } + logrus.Debug("Using container ipcmode") } return nil @@ -580,9 +545,33 @@ func (c *createConfig) GetContainerCreateOptions() ([]libpod.CtrCreateOption, er options = append(options, libpod.WithName(c.Name)) } // TODO parse ports into libpod format and include - if !c.NetMode.IsHost() { + if !c.NetMode.IsHost() && !c.NetMode.IsContainer() { options = append(options, libpod.WithNetNS([]ocicni.PortMapping{})) + } else if c.NetMode.IsContainer() { + connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.ConnectedContainer()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.NetMode.ConnectedContainer()) + } + + options = append(options, libpod.WithNetNSFrom(connectedCtr)) } + if c.PidMode.IsContainer() { + connectedCtr, err := c.Runtime.LookupContainer(c.PidMode.Container()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.PidMode.Container()) + } + + options = append(options, libpod.WithPIDNSFrom(connectedCtr)) + } + if c.IpcMode.IsContainer() { + connectedCtr, err := c.Runtime.LookupContainer(c.IpcMode.Container()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.IpcMode.Container()) + } + + options = append(options, libpod.WithIPCNSFrom(connectedCtr)) + } + options = append(options, libpod.WithStopSignal(c.StopSignal)) options = append(options, libpod.WithStopTimeout(c.StopTimeout)) return options, nil diff --git a/libpod/container.go b/libpod/container.go index 7003396ac..cd8cb4a6e 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -133,7 +133,6 @@ type Container struct { // TODO enable pod support // TODO Add readonly support // TODO add SHM size support -// TODO add shared namespace support // containerRuntimeInfo contains the current state of the container // It is stored on disk in a tmpfs and recreated on reboot diff --git a/libpod/options.go b/libpod/options.go index 8a9cf94b6..a62a13053 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1,7 +1,6 @@ package libpod import ( - "fmt" "path/filepath" "regexp" "syscall" @@ -13,27 +12,9 @@ import ( ) var ( - ctrNotImplemented = func(c *Container) error { - return fmt.Errorf("NOT IMPLEMENTED") - } nameRegex = regexp.MustCompile("[a-zA-Z0-9_-]+") ) -const ( - // IPCNamespace represents the IPC namespace - IPCNamespace = "ipc" - // MountNamespace represents the mount namespace - MountNamespace = "mount" - // NetNamespace represents the network namespace - NetNamespace = "network" - // PIDNamespace represents the PID namespace - PIDNamespace = "pid" - // UserNamespace represents the user namespace - UserNamespace = "user" - // UTSNamespace represents the UTS namespace - UTSNamespace = "uts" -) - // Runtime Creation Options // WithStorageConfig uses the given configuration to set up container storage @@ -341,15 +322,6 @@ func WithStdin() CtrCreateOption { } } -// WithSharedNamespaces sets a container to share namespaces with another -// container. If the from container belongs to a pod, the new container will -// be added to the pod. -// By default no namespaces are shared. To share a namespace, add the Namespace -// string constant to the map as a key -func WithSharedNamespaces(from *Container, namespaces map[string]string) CtrCreateOption { - return ctrNotImplemented -} - // WithPod adds the container to a pod func (r *Runtime) WithPod(pod *Pod) CtrCreateOption { return func(ctr *Container) error { @@ -434,6 +406,164 @@ func WithStopTimeout(timeout uint) CtrCreateOption { } } +// WithIPCNSFrom indicates the the container should join the IPC namespace of +// the given container +func WithIPCNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + ctr.config.IPCNsCtr = nsCtr.ID() + + return nil + } +} + +// WithMountNSFrom indicates the the container should join the mount namespace +// of the given container +func WithMountNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + ctr.config.MountNsCtr = nsCtr.ID() + + return nil + } +} + +// WithNetNSFrom indicates the the container should join the network namespace +// of the given container +func WithNetNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + if ctr.config.CreateNetNS { + return errors.Wrapf(ErrInvalidArg, "cannot join another container's net ns as we are making a new net ns") + } + + ctr.config.NetNsCtr = nsCtr.ID() + + return nil + } +} + +// WithPIDNSFrom indicates the the container should join the PID namespace of +// the given container +func WithPIDNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + ctr.config.PIDNsCtr = nsCtr.ID() + + return nil + } +} + +// WithUserNSFrom indicates the the container should join the user namespace of +// the given container +func WithUserNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + ctr.config.UserNsCtr = nsCtr.ID() + + return nil + } +} + +// WithUTSNSFrom indicates the the container should join the UTS namespace of +// the given container +func WithUTSNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + ctr.config.UTSNsCtr = nsCtr.ID() + + return nil + } +} + +// WithCgroupNSFrom indicates the the container should join the CGroup namespace +// of the given container +func WithCgroupNSFrom(nsCtr *Container) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + if !nsCtr.valid { + return ErrCtrRemoved + } + + if nsCtr.ID() == ctr.ID() { + return errors.Wrapf(ErrInvalidArg, "must specify another container") + } + + ctr.config.CgroupNsCtr = nsCtr.ID() + + return nil + } +} + // WithNetNS indicates that the container should be given a new network // namespace with a minimal configuration // An optional array of port mappings can be provided @@ -443,6 +573,10 @@ func WithNetNS(portMappings []ocicni.PortMapping) CtrCreateOption { return ErrCtrFinalized } + if ctr.config.NetNsCtr != "" { + return errors.Wrapf(ErrInvalidArg, "container is already set to join another container's net ns, cannot create a new net ns") + } + ctr.config.CreateNetNS = true copy(ctr.config.PortMappings, portMappings) |