Merge pull request #495 from rhatdan/tmpfs
Add support for Premount and Postmount commands.
This commit is contained in:
commit
bada39cf31
|
@ -18,4 +18,17 @@ type Mount struct {
|
||||||
|
|
||||||
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
|
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
|
||||||
Relabel string `json:"relabel"`
|
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"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,10 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/libcontainer"
|
"github.com/docker/libcontainer"
|
||||||
|
@ -645,3 +647,76 @@ func TestPassExtraFiles(t *testing.T) {
|
||||||
t.Fatalf("expected second pipe to receive '2', got '%s'", out2)
|
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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -24,9 +25,20 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
|
||||||
return newSystemError(err)
|
return newSystemError(err)
|
||||||
}
|
}
|
||||||
for _, m := range config.Mounts {
|
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 {
|
if err := mountToRootfs(m, config.Rootfs, config.MountLabel); err != nil {
|
||||||
return newSystemError(err)
|
return newSystemError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, postcmd := range m.PostmountCmds {
|
||||||
|
if err := mountCmd(postcmd); err != nil {
|
||||||
|
return newSystemError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := createDevices(config); err != nil {
|
if err := createDevices(config); err != nil {
|
||||||
return newSystemError(err)
|
return newSystemError(err)
|
||||||
|
@ -62,6 +74,18 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
|
||||||
return nil
|
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 {
|
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
var (
|
var (
|
||||||
dest = m.Destination
|
dest = m.Destination
|
||||||
|
|
Loading…
Reference in New Issue