mirror of https://github.com/containers/podman.git
Add support for joining shared namespaces in libpod
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #220 Approved by: rhatdan
This commit is contained in:
parent
333f664da7
commit
fe0e1cd11b
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue