diff options
Diffstat (limited to 'libpod/container_internal.go')
-rw-r--r-- | libpod/container_internal.go | 249 |
1 files changed, 4 insertions, 245 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 22b398709..452be176c 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -8,7 +8,6 @@ import ( "io" "io/ioutil" "os" - "path" "path/filepath" "strings" "syscall" @@ -17,14 +16,12 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/chrootarchive" - "github.com/containers/storage/pkg/idtools" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/stringid" 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/projectatomic/libpod/pkg/chrootuser" "github.com/projectatomic/libpod/pkg/hooks" "github.com/projectatomic/libpod/pkg/hooks/exec" @@ -33,7 +30,6 @@ import ( "github.com/projectatomic/libpod/pkg/util" "github.com/sirupsen/logrus" "github.com/ulule/deepcopier" - "golang.org/x/sys/unix" "golang.org/x/text/language" ) @@ -748,9 +744,8 @@ func (c *Container) mountStorage() (err error) { if !mounted { shmOptions := fmt.Sprintf("mode=1777,size=%d", c.config.ShmSize) - 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) + if err := c.mountSHM(shmOptions); err != nil { + return err } if err := os.Chown(c.config.ShmDir, c.RootUID(), c.RootGID()); err != nil { return errors.Wrapf(err, "failed to chown %s", c.config.ShmDir) @@ -786,53 +781,6 @@ func (c *Container) mountStorage() (err error) { return c.save() } -// prepare mounts the container and sets up other required resources like net -// namespaces -func (c *Container) prepare() (err error) { - // Mount storage if not mounted - if err := c.mountStorage(); err != nil { - return err - } - - // Set up network namespace if not already set up - if c.config.CreateNetNS && c.state.NetNS == nil && !c.config.PostConfigureNetNS { - if err := c.runtime.createNetNS(c); err != nil { - // Tear down storage before exiting to make sure we - // don't leak mounts - if err2 := c.cleanupStorage(); err2 != nil { - logrus.Errorf("Error cleaning up storage for container %s: %v", c.ID(), err2) - } - return err - } - } - - return nil -} - -// cleanupNetwork unmounts and cleans up the container's network -func (c *Container) cleanupNetwork() error { - if c.state.NetNS == nil { - logrus.Debugf("Network is already cleaned up, skipping...") - return nil - } - - // Stop the container's network namespace (if it has one) - if err := c.runtime.teardownNetNS(c); err != nil { - logrus.Errorf("unable to cleanup network for container %s: %q", c.ID(), err) - } - - c.state.NetNS = nil - c.state.IPs = nil - c.state.Interfaces = nil - c.state.Routes = nil - - if c.valid { - return c.save() - } - - return nil -} - // cleanupStorage unmounts and cleans up the container's root filesystem func (c *Container) cleanupStorage() error { if !c.state.Mounted { @@ -842,10 +790,8 @@ func (c *Container) cleanupStorage() error { } 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) - } + if err := c.unmountSHM(mount); err != nil { + return err } } if c.config.Rootfs != "" { @@ -1178,193 +1124,6 @@ func (c *Container) generateHosts() (string, error) { return c.writeStringToRundir("hosts", hosts) } -// Generate spec for a container -// Accepts a map of the container's dependencies -func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { - g := generate.NewFromSpec(c.config.Spec) - - // If network namespace was requested, add it now - if c.config.CreateNetNS { - if c.config.PostConfigureNetNS { - g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, "") - } else { - g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path()) - } - } - - // Remove the default /dev/shm mount to ensure we overwrite it - g.RemoveMount("/dev/shm") - - // Add bind mounts to container - for dstPath, srcPath := range c.state.BindMounts { - newMount := spec.Mount{ - Type: "bind", - Source: srcPath, - Destination: dstPath, - Options: []string{"rw", "bind"}, - } - if !MountExists(g.Mounts(), dstPath) { - g.AddMount(newMount) - } else { - logrus.Warnf("User mount overriding libpod mount at %q", dstPath) - } - } - - var err error - if !rootless.IsRootless() { - if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { - return nil, errors.Wrapf(err, "error setting up OCI Hooks") - } - } - - // Bind builtin image volumes - if c.config.Rootfs == "" && c.config.ImageVolumes { - if err := c.addImageVolumes(ctx, &g); err != nil { - return nil, errors.Wrapf(err, "error mounting image volumes") - } - } - - if c.config.User != "" { - if !c.state.Mounted { - return nil, errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to translate User field", c.ID()) - } - uid, gid, err := chrootuser.GetUser(c.state.Mountpoint, c.config.User) - if err != nil { - return nil, err - } - // User and Group must go together - g.SetProcessUID(uid) - g.SetProcessGID(gid) - } - - // Add addition groups if c.config.GroupAdd is not empty - if len(c.config.Groups) > 0 { - if !c.state.Mounted { - return nil, errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to add additional groups", c.ID()) - } - for _, group := range c.config.Groups { - gid, err := chrootuser.GetGroup(c.state.Mountpoint, group) - if err != nil { - return nil, err - } - g.AddProcessAdditionalGid(gid) - } - } - - // Look up and add groups the user belongs to, if a group wasn't directly specified - if !rootless.IsRootless() && !strings.Contains(c.config.User, ":") { - groups, err := chrootuser.GetAdditionalGroupsForUser(c.state.Mountpoint, uint64(g.Config.Process.User.UID)) - if err != nil && errors.Cause(err) != chrootuser.ErrNoSuchUser { - return nil, err - } - for _, gid := range groups { - g.AddProcessAdditionalGid(gid) - } - } - - // Add shared namespaces from other containers - if c.config.IPCNsCtr != "" { - if err := c.addNamespaceContainer(&g, IPCNS, c.config.IPCNsCtr, spec.IPCNamespace); err != nil { - return nil, err - } - } - if c.config.MountNsCtr != "" { - if err := c.addNamespaceContainer(&g, MountNS, c.config.MountNsCtr, spec.MountNamespace); err != nil { - return nil, err - } - } - if c.config.NetNsCtr != "" { - if err := c.addNamespaceContainer(&g, NetNS, c.config.NetNsCtr, spec.NetworkNamespace); err != nil { - return nil, err - } - } - if c.config.PIDNsCtr != "" { - if err := c.addNamespaceContainer(&g, PIDNS, c.config.PIDNsCtr, string(spec.PIDNamespace)); err != nil { - return nil, err - } - } - if c.config.UserNsCtr != "" { - if err := c.addNamespaceContainer(&g, UserNS, c.config.UserNsCtr, spec.UserNamespace); err != nil { - return nil, err - } - } - if c.config.UTSNsCtr != "" { - if err := c.addNamespaceContainer(&g, UTSNS, c.config.UTSNsCtr, spec.UTSNamespace); err != nil { - return nil, err - } - } - if c.config.CgroupNsCtr != "" { - if err := c.addNamespaceContainer(&g, CgroupNS, c.config.CgroupNsCtr, spec.CgroupNamespace); err != nil { - return nil, err - } - } - - if c.config.Rootfs == "" { - if err := idtools.MkdirAllAs(c.state.RealMountpoint, 0700, c.RootUID(), c.RootGID()); err != nil { - return nil, err - } - } - - g.SetRootPath(c.state.RealMountpoint) - g.AddAnnotation(crioAnnotations.Created, c.config.CreatedTime.Format(time.RFC3339Nano)) - g.AddAnnotation("org.opencontainers.image.stopSignal", fmt.Sprintf("%d", c.config.StopSignal)) - - g.SetHostname(c.Hostname()) - g.AddProcessEnv("HOSTNAME", g.Config.Hostname) - - // Only add container environment variable if not already present - foundContainerEnv := false - for _, env := range g.Config.Process.Env { - if strings.HasPrefix(env, "container=") { - foundContainerEnv = true - break - } - } - if !foundContainerEnv { - g.AddProcessEnv("container", "libpod") - } - - if rootless.IsRootless() { - g.SetLinuxCgroupsPath("") - } else if c.runtime.config.CgroupManager == SystemdCgroupsManager { - // When runc is set to use Systemd as a cgroup manager, it - // expects cgroups to be passed as follows: - // slice:prefix:name - systemdCgroups := fmt.Sprintf("%s:libpod:%s", path.Base(c.config.CgroupParent), c.ID()) - logrus.Debugf("Setting CGroups for container %s to %s", c.ID(), systemdCgroups) - g.SetLinuxCgroupsPath(systemdCgroups) - } else { - cgroupPath, err := c.CGroupPath() - if err != nil { - return nil, err - } - logrus.Debugf("Setting CGroup path for container %s to %s", c.ID(), cgroupPath) - g.SetLinuxCgroupsPath(cgroupPath) - } - - return g.Config, nil -} - -// Add an existing container's namespace to the spec -func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr string, specNS string) error { - nsCtr, err := c.runtime.state.Container(ctr) - if err != nil { - return errors.Wrapf(err, "error retrieving dependency %s of container %s from state", ctr, c.ID()) - } - - // TODO need unlocked version of this for use in pods - nsPath, err := nsCtr.NamespacePath(ns) - if err != nil { - return err - } - - if err := g.AddOrReplaceLinuxNamespace(specNS, nsPath); err != nil { - return err - } - - return nil -} - func (c *Container) addImageVolumes(ctx context.Context, g *generate.Generator) error { mountPoint := c.state.Mountpoint if !c.state.Mounted { |