Merge pull request #495 from rhatdan/tmpfs

Add support for Premount and Postmount commands.
This commit is contained in:
Mrunal Patel 2015-04-20 09:20:52 -07:00
commit bada39cf31
3 changed files with 112 additions and 0 deletions

View File

@ -18,4 +18,17 @@ type Mount struct {
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
Relabel string `json:"relabel"`
// Optional Command to be run before Source is mounted.
PremountCmds []Command `json:"premount_cmds"`
// Optional Command to be run after Source is mounted.
PostmountCmds []Command `json:"postmount_cmds"`
}
type Command struct {
Path string `json:"path"`
Args []string `json:"args"`
Env []string `json:"env"`
Dir string `json:"dir"`
}

View File

@ -4,8 +4,10 @@ import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"syscall"
"testing"
"github.com/docker/libcontainer"
@ -645,3 +647,76 @@ func TestPassExtraFiles(t *testing.T) {
t.Fatalf("expected second pipe to receive '2', got '%s'", out2)
}
}
func TestMountCmds(t *testing.T) {
if testing.Short() {
return
}
root, err := newTestRoot()
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(root)
rootfs, err := newRootfs()
if err != nil {
t.Fatal(err)
}
defer remove(rootfs)
tmpDir, err := ioutil.TempDir("", "tmpdir")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
config := newTemplateConfig(rootfs)
config.Mounts = append(config.Mounts, &configs.Mount{
Source: tmpDir,
Destination: filepath.Join(rootfs, "tmp"),
Device: "bind",
Flags: syscall.MS_BIND | syscall.MS_REC,
PremountCmds: []configs.Command{
{Path: "touch", Args: []string{filepath.Join(tmpDir, "hello")}},
{Path: "touch", Args: []string{filepath.Join(tmpDir, "world")}},
},
PostmountCmds: []configs.Command{
{Path: "cp", Args: []string{filepath.Join(rootfs, "tmp", "hello"), filepath.Join(rootfs, "tmp", "hello-backup")}},
{Path: "cp", Args: []string{filepath.Join(rootfs, "tmp", "world"), filepath.Join(rootfs, "tmp", "world-backup")}},
},
})
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
if err != nil {
t.Fatal(err)
}
container, err := factory.Create("test", config)
if err != nil {
t.Fatal(err)
}
defer container.Destroy()
pconfig := libcontainer.Process{
Args: []string{"sh", "-c", "env"},
Env: standardEnvironment,
}
err = container.Start(&pconfig)
if err != nil {
t.Fatal(err)
}
// Wait for process
waitProcess(&pconfig, t)
entries, err := ioutil.ReadDir(tmpDir)
if err != nil {
t.Fatal(err)
}
expected := []string{"hello", "hello-backup", "world", "world-backup"}
for i, e := range entries {
if e.Name() != expected[i] {
t.Errorf("Got(%s), expect %s", e.Name(), expected[i])
}
}
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
@ -24,9 +25,20 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
return newSystemError(err)
}
for _, m := range config.Mounts {
for _, precmd := range m.PremountCmds {
if err := mountCmd(precmd); err != nil {
return newSystemError(err)
}
}
if err := mountToRootfs(m, config.Rootfs, config.MountLabel); err != nil {
return newSystemError(err)
}
for _, postcmd := range m.PostmountCmds {
if err := mountCmd(postcmd); err != nil {
return newSystemError(err)
}
}
}
if err := createDevices(config); err != nil {
return newSystemError(err)
@ -62,6 +74,18 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
return nil
}
func mountCmd(cmd configs.Command) error {
command := exec.Command(cmd.Path, cmd.Args[:]...)
command.Env = cmd.Env
command.Dir = cmd.Dir
if out, err := command.CombinedOutput(); err != nil {
return fmt.Errorf("%#v failed: %s: %v", cmd, string(out), err)
}
return nil
}
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
var (
dest = m.Destination