container_create: set mount propagation

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-09-27 14:49:29 +02:00
parent e41ba62b19
commit c70198617f
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9

View file

@ -14,6 +14,7 @@ import (
"time"
"github.com/docker/distribution/reference"
dockermounts "github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/symlink"
"github.com/kubernetes-incubator/cri-o/libkpod"
@ -103,6 +104,36 @@ func addOCIBindMounts(mountLabel string, containerConfig *pb.ContainerConfig, sp
}
options = append(options, []string{"rbind", "rprivate"}...)
// mount propagation
mountInfos, err := dockermounts.GetMounts()
if err != nil {
return nil, nil, err
}
switch mount.GetPropagation() {
case pb.MountPropagation_PROPAGATION_PRIVATE:
options = append(options, "rprivate")
// Since default root propagation in runc is rprivate ignore
// setting the root propagation
case pb.MountPropagation_PROPAGATION_BIDIRECTIONAL:
if err := ensureShared(src, mountInfos); err != nil {
return nil, nil, err
}
options = append(options, "rshared")
specgen.SetLinuxRootPropagation("rshared")
case pb.MountPropagation_PROPAGATION_HOST_TO_CONTAINER:
if err := ensureSharedOrSlave(src, mountInfos); err != nil {
return nil, nil, err
}
options = append(options, "rslave")
if specgen.Spec().Linux.RootfsPropagation != "rshared" &&
specgen.Spec().Linux.RootfsPropagation != "rslave" {
specgen.SetLinuxRootPropagation("rslave")
}
default:
logrus.Warnf("Unknown propagation mode for hostPath %q", mount.HostPath)
options = append(options, "rprivate")
}
if mount.SelinuxRelabel {
// Need a way in kubernetes to determine if the volume is shared or private
if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP {
@ -126,6 +157,74 @@ func addOCIBindMounts(mountLabel string, containerConfig *pb.ContainerConfig, sp
return volumes, ociMounts, nil
}
// Ensure mount point on which path is mounted, is shared.
func ensureShared(path string, mountInfos []*dockermounts.Info) error {
sourceMount, optionalOpts, err := getSourceMount(path, mountInfos)
if err != nil {
return err
}
// Make sure source mount point is shared.
optsSplit := strings.Split(optionalOpts, " ")
for _, opt := range optsSplit {
if strings.HasPrefix(opt, "shared:") {
return nil
}
}
return fmt.Errorf("path %q is mounted on %q but it is not a shared mount", path, sourceMount)
}
// Ensure mount point on which path is mounted, is either shared or slave.
func ensureSharedOrSlave(path string, mountInfos []*dockermounts.Info) error {
sourceMount, optionalOpts, err := getSourceMount(path, mountInfos)
if err != nil {
return err
}
// Make sure source mount point is shared.
optsSplit := strings.Split(optionalOpts, " ")
for _, opt := range optsSplit {
if strings.HasPrefix(opt, "shared:") {
return nil
} else if strings.HasPrefix(opt, "master:") {
return nil
}
}
return fmt.Errorf("path %q is mounted on %q but it is not a shared or slave mount", path, sourceMount)
}
func getMountInfo(mountInfos []*dockermounts.Info, dir string) *dockermounts.Info {
for _, m := range mountInfos {
if m.Mountpoint == dir {
return m
}
}
return nil
}
func getSourceMount(source string, mountInfos []*dockermounts.Info) (string, string, error) {
mountinfo := getMountInfo(mountInfos, source)
if mountinfo != nil {
return source, mountinfo.Optional, nil
}
path := source
for {
path = filepath.Dir(path)
mountinfo = getMountInfo(mountInfos, path)
if mountinfo != nil {
return path, mountinfo.Optional, nil
}
if path == "/" {
break
}
}
// If we are here, we did not find parent mount. Something is wrong.
return "", "", fmt.Errorf("Could not find source mount of %s", source)
}
func addImageVolumes(rootfs string, s *Server, containerInfo *storage.ContainerInfo, specgen *generate.Generator, mountLabel string) ([]rspec.Mount, error) {
mounts := []rspec.Mount{}
for dest := range containerInfo.Config.Config.Volumes {