exec_test.go: Test case for rootfsPropagation="private"

A test case to test rootfsPropagation="private" and making sure shared
volumes work.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
Vivek Goyal 2015-10-01 17:03:02 -04:00
parent 175e4b8aec
commit 6a851e1195
1 changed files with 113 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
@ -1049,7 +1050,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
defer os.RemoveAll(dir1host)
// Make this dir a "shared" mount point. This will make sure a
// slave relation ship can be established in container.
// slave relationship can be established in container.
err = syscall.Mount(dir1host, dir1host, "bind", syscall.MS_BIND|syscall.MS_REC, "")
ok(t, err)
err = syscall.Mount("", dir1host, "", syscall.MS_SHARED|syscall.MS_REC, "")
@ -1138,3 +1139,114 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
t.Fatalf("Mount on host %s did not propagate in container at %s\n", dir2host, dir2cont)
}
}
// Launch container with rootfsPropagation 0 so no propagation flags are
// applied. Also bind mount a volume /mnt1host at /mnt1cont at the time of
// launch. Now do a mount in container (/mnt1cont/mnt2cont) and this new
// mount should propagate to host (/mnt1host/mnt2cont)
func TestRootfsPropagationSharedMount(t *testing.T) {
var dir1cont string
var dir2cont string
dir1cont = "/root/mnt1cont"
if testing.Short() {
return
}
rootfs, err := newRootfs()
ok(t, err)
defer remove(rootfs)
config := newTemplateConfig(rootfs)
config.RootPropagation = syscall.MS_PRIVATE
// Bind mount a volume
dir1host, err := ioutil.TempDir("", "mnt1host")
ok(t, err)
defer os.RemoveAll(dir1host)
// Make this dir a "shared" mount point. This will make sure a
// shared relationship can be established in container.
err = syscall.Mount(dir1host, dir1host, "bind", syscall.MS_BIND|syscall.MS_REC, "")
ok(t, err)
err = syscall.Mount("", dir1host, "", syscall.MS_SHARED|syscall.MS_REC, "")
ok(t, err)
defer unmountOp(dir1host)
config.Mounts = append(config.Mounts, &configs.Mount{
Source: dir1host,
Destination: dir1cont,
Device: "bind",
Flags: syscall.MS_BIND | syscall.MS_REC})
// TODO: systemd specific processing
f := factory
container, err := f.Create("testSharedMount", config)
ok(t, err)
defer container.Destroy()
stdinR, stdinW, err := os.Pipe()
ok(t, err)
pconfig := &libcontainer.Process{
Args: []string{"cat"},
Env: standardEnvironment,
Stdin: stdinR,
}
err = container.Start(pconfig)
stdinR.Close()
defer stdinW.Close()
ok(t, err)
// Create mnt1host/mnt2cont. This will become visible inside container
// at mnt1cont/mnt2cont. Bind mount itself on top of it. This
// should be visible on host now.
dir2host, err := ioutil.TempDir(dir1host, "mnt2cont")
ok(t, err)
defer os.RemoveAll(dir2host)
dir2cont = filepath.Join(dir1cont, filepath.Base(dir2host))
// Mount something in container and see if it is visible on host.
var stdout2 bytes.Buffer
stdinR2, stdinW2, err := os.Pipe()
ok(t, err)
// Provide CAP_SYS_ADMIN
processCaps := append(config.Capabilities, "CAP_SYS_ADMIN")
pconfig2 := &libcontainer.Process{
Args: []string{"mount", "--bind", dir2cont, dir2cont},
Env: standardEnvironment,
Stdin: stdinR2,
Stdout: &stdout2,
Capabilities: processCaps,
}
err = container.Start(pconfig2)
stdinR2.Close()
defer stdinW2.Close()
ok(t, err)
// Wait for process
stdinW2.Close()
waitProcess(pconfig2, t)
stdinW.Close()
waitProcess(pconfig, t)
defer unmountOp(dir2host)
// Check if mount is visible on host or not.
out, err := exec.Command("findmnt", "-n", "-f", "-oTARGET", dir2host).CombinedOutput()
outtrim := strings.TrimSpace(string(out))
if err != nil {
t.Logf("findmnt error %q: %q", err, outtrim)
}
if string(outtrim) != dir2host {
t.Fatalf("Mount in container on %s did not propagate to host on %s. finmnt output=%s", dir2cont, dir2host, outtrim)
}
}