aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2018-01-11 15:14:44 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-01-16 14:58:06 +0000
commitfe0e1cd11bd1d98c7687a58011746f6b189c8d67 (patch)
tree87acffc9fced79a34f1da82e5eb24fe8c3f08cd0
parent333f664da7ef96462d5e72aaa8a24a17c3e648b8 (diff)
downloadpodman-fe0e1cd11bd1d98c7687a58011746f6b189c8d67.tar.gz
podman-fe0e1cd11bd1d98c7687a58011746f6b189c8d67.tar.bz2
podman-fe0e1cd11bd1d98c7687a58011746f6b189c8d67.zip
Add support for joining shared namespaces in libpod
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #220 Approved by: rhatdan
-rw-r--r--libpod/container.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 226985d9f..89b042d12 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -63,6 +63,49 @@ const (
// CgroupParent is the default prefix to a cgroup path in libpod
var CgroupParent = "/libpod_parent"
+// LinuxNS represents a Linux namespace
+type LinuxNS int
+
+const (
+ // InvalidNS is an invalid namespace
+ InvalidNS LinuxNS = iota
+ // IPCNS is the IPC namespace
+ IPCNS LinuxNS = iota
+ // MntNS is the mount namespace
+ MountNS LinuxNS = iota
+ // NetNS is the network namespace
+ NetNS LinuxNS = iota
+ // PIDNS is the PID namespace
+ PIDNS LinuxNS = iota
+ // UserNS is the user namespace
+ UserNS LinuxNS = iota
+ // UTSNS is the UTS namespace
+ UTSNS LinuxNS = iota
+)
+
+// String returns a string representation of a Linux namespace
+// It is guaranteed to be the name of the namespace in /proc for valid ns types
+func (ns LinuxNS) String() string {
+ switch ns {
+ case InvalidNS:
+ return "invalid"
+ case IPCNS:
+ return "ipc"
+ case MountNS:
+ return "mnt"
+ case NetNS:
+ return "net"
+ case PIDNS:
+ return "pid"
+ case UserNS:
+ return "user"
+ case UTSNS:
+ return "uts"
+ default:
+ return "unknown"
+ }
+}
+
// Container is a single OCI container
type Container struct {
config *ContainerConfig
@@ -484,6 +527,26 @@ func (c *Container) MountPoint() (string, error) {
return c.state.Mountpoint, nil
}
+// NamespacePath returns the path of one of the container's namespaces
+// If the container is not running, an error will be returned
+func (c *Container) NamespacePath(ns LinuxNS) (string, error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ if err := c.syncContainer(); err != nil {
+ return "", errors.Wrapf(err, "error updating container %s state", c.ID())
+ }
+
+ if c.state.State != ContainerStateRunning {
+ return "", errors.Wrapf(ErrCtrStopped, "cannot get namespace path unless container %s is running", c.ID())
+ }
+
+ if ns == InvalidNS {
+ return "", errors.Wrapf(ErrInvalidArg, "invalid namespace requested from container %s", c.ID())
+ }
+
+ return fmt.Sprintf("/proc/%d/ns/%s", c.state.PID, ns.String()), nil
+}
+
// The path to the container's root filesystem - where the OCI spec will be
// placed, amongst other things
func (c *Container) bundlePath() string {
@@ -766,6 +829,98 @@ func (c *Container) Init() (err error) {
g.SetProcessGID(gid)
}
+ // Add shared namespaces from other containers
+ if c.config.IPCNsCtr != "" {
+ ipcCtr, err := c.runtime.state.Container(c.config.IPCNsCtr)
+ if err != nil {
+ return err
+ }
+
+ nsPath, err := ipcCtr.NamespacePath(IPCNS)
+ if err != nil {
+ return err
+ }
+
+ if err := g.AddOrReplaceLinuxNamespace(spec.IPCNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+ if c.config.MountNsCtr != "" {
+ mountCtr, err := c.runtime.state.Container(c.config.MountNsCtr)
+ if err != nil {
+ return err
+ }
+
+ nsPath, err := mountCtr.NamespacePath(MountNS)
+ if err != nil {
+ return err
+ }
+
+ if err := g.AddOrReplaceLinuxNamespace(spec.MountNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+ if c.config.NetNsCtr != "" {
+ netCtr, err := c.runtime.state.Container(c.config.NetNsCtr)
+ if err != nil {
+ return err
+ }
+
+ nsPath, err := netCtr.NamespacePath(NetNS)
+ if err != nil {
+ return err
+ }
+
+ if err := g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+ if c.config.PIDNsCtr != "" {
+ pidCtr, err := c.runtime.state.Container(c.config.PIDNsCtr)
+ if err != nil {
+ return err
+ }
+
+ nsPath, err := pidCtr.NamespacePath(PIDNS)
+ if err != nil {
+ return err
+ }
+
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), nsPath); err != nil {
+ return err
+ }
+ }
+ if c.config.UserNsCtr != "" {
+ userCtr, err := c.runtime.state.Container(c.config.UserNsCtr)
+ if err != nil {
+ return err
+ }
+
+ nsPath, err := userCtr.NamespacePath(UserNS)
+ if err != nil {
+ return err
+ }
+
+ if err := g.AddOrReplaceLinuxNamespace(spec.UserNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+ if c.config.UTSNsCtr != "" {
+ utsCtr, err := c.runtime.state.Container(c.config.UTSNsCtr)
+ if err != nil {
+ return err
+ }
+
+ nsPath, err := utsCtr.NamespacePath(UTSNS)
+ if err != nil {
+ return err
+ }
+
+ if err := g.AddOrReplaceLinuxNamespace(spec.UTSNamespace, nsPath); err != nil {
+ return err
+ }
+ }
+
c.runningSpec = g.Spec()
c.runningSpec.Root.Path = c.state.Mountpoint
c.runningSpec.Annotations[crioAnnotations.Created] = c.config.CreatedTime.Format(time.RFC3339Nano)