aboutsummaryrefslogtreecommitdiff
path: root/libpod/container_internal_linux.go
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-07-04 10:51:20 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-07-05 16:05:12 +0000
commitcc6f0e85f994cab66fb63c4dd8b77b4332151748 (patch)
tree6b54655b66a8571945ccda1601533717c8375906 /libpod/container_internal_linux.go
parent33870ea2c3a3aa4e2bd3da3d84b21820c75eaf23 (diff)
downloadpodman-cc6f0e85f994cab66fb63c4dd8b77b4332151748.tar.gz
podman-cc6f0e85f994cab66fb63c4dd8b77b4332151748.tar.bz2
podman-cc6f0e85f994cab66fb63c4dd8b77b4332151748.zip
more changes to compile darwin
this should represent the last major changes to get darwin to **compile**. again, the purpose here is to get darwin to compile so that we can eventually implement a ci task that would protect against regressions for darwin compilation. i have left the manual darwin compilation largely static still and in fact now only interject (manually) two build tags to assist with the build. trevor king has great ideas on how to make this better and i will defer final implementation of those to him. Signed-off-by: baude <bbaude@redhat.com> Closes: #1047 Approved by: rhatdan
Diffstat (limited to 'libpod/container_internal_linux.go')
-rw-r--r--libpod/container_internal_linux.go265
1 files changed, 265 insertions, 0 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 41b8a86fc..327c78045 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -3,11 +3,25 @@
package libpod
import (
+ "context"
"fmt"
+ "path"
"path/filepath"
+ "strings"
+ "syscall"
+ "time"
"github.com/containerd/cgroups"
+ "github.com/containers/storage/pkg/idtools"
+ 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/rootless"
"github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
)
// cleanupCgroup cleans up residual CGroups after container execution
@@ -50,3 +64,254 @@ func (c *Container) cleanupCgroups() error {
return nil
}
+
+func (c *Container) mountSHM(shmOptions string) error {
+ 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)
+ }
+ return nil
+}
+
+func (c *Container) unmountSHM(mount string) error {
+ 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)
+ }
+ }
+ return nil
+}
+
+// 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
+}
+
+// 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
+}