Browse Source

LXC TEMPLATE WILL CREATE MOUNT

Lxc driver was throwing errors for mounts where the mount point does not exist in the container.
This adds a create=dir/file mount option to the lxc template, to alleviate this issue.

Docker-DCO-1.1-Signed-off-by: Abin Shahab <ashahab@altiscale.com> (github: ashahab-altiscale)
Abin Shahab 10 years ago
parent
commit
b36bf98174

+ 21 - 5
daemon/execdriver/lxc/lxc_template.go

@@ -1,11 +1,11 @@
 package lxc
 
 import (
-	"strings"
-	"text/template"
-
 	"github.com/docker/docker/daemon/execdriver"
 	"github.com/docker/libcontainer/label"
+	"os"
+	"strings"
+	"text/template"
 )
 
 const LxcTemplate = `
@@ -70,10 +70,11 @@ lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts {{formatMo
 lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs {{formatMountLabel "size=65536k,nosuid,nodev,noexec" ""}} 0 0
 
 {{range $value := .Mounts}}
+{{$createVal := isDirectory $value.Source}}
 {{if $value.Writable}}
-lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,rw 0 0
+lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,rw,create={{$createVal}} 0 0
 {{else}}
-lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,ro 0 0
+lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,ro,create={{$createVal}} 0 0
 {{end}}
 {{end}}
 
@@ -117,6 +118,20 @@ func escapeFstabSpaces(field string) string {
 	return strings.Replace(field, " ", "\\040", -1)
 }
 
+func isDirectory(source string) string {
+	f, err := os.Stat(source)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return "dir"
+		}
+		return ""
+	}
+	if f.IsDir() {
+		return "dir"
+	}
+	return "file"
+}
+
 func getMemorySwap(v *execdriver.Resources) int64 {
 	// By default, MemorySwap is set to twice the size of RAM.
 	// If you want to omit MemorySwap, set it to `-1'.
@@ -143,6 +158,7 @@ func init() {
 		"getMemorySwap":     getMemorySwap,
 		"escapeFstabSpaces": escapeFstabSpaces,
 		"formatMountLabel":  label.FormatMountLabel,
+		"isDirectory":       isDirectory,
 	}
 	LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
 	if err != nil {

+ 88 - 0
daemon/execdriver/lxc/lxc_template_unit_test.go

@@ -140,3 +140,91 @@ func TestEscapeFstabSpaces(t *testing.T) {
 		}
 	}
 }
+
+func TestIsDirectory(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "TestIsDir")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+
+	tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if isDirectory(tempDir) != "dir" {
+		t.Logf("Could not identify %s as a directory", tempDir)
+		t.Fail()
+	}
+
+	if isDirectory(tempFile.Name()) != "file" {
+		t.Logf("Could not identify %s as a file", tempFile.Name())
+		t.Fail()
+	}
+}
+
+func TestCustomLxcConfigMounts(t *testing.T) {
+	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(root)
+	tempDir, err := ioutil.TempDir("", "TestIsDir")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+
+	tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile")
+	if err != nil {
+		t.Fatal(err)
+	}
+	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
+
+	driver, err := NewDriver(root, "", false)
+	if err != nil {
+		t.Fatal(err)
+	}
+	processConfig := execdriver.ProcessConfig{
+		Privileged: false,
+	}
+	mounts := []execdriver.Mount{
+		{
+			Source:      tempDir,
+			Destination: tempDir,
+			Writable:    false,
+			Private:     true,
+		},
+		{
+			Source:      tempFile.Name(),
+			Destination: tempFile.Name(),
+			Writable:    true,
+			Private:     true,
+		},
+	}
+	command := &execdriver.Command{
+		ID: "1",
+		LxcConfig: []string{
+			"lxc.utsname = docker",
+			"lxc.cgroup.cpuset.cpus = 0,1",
+		},
+		Network: &execdriver.Network{
+			Mtu:       1500,
+			Interface: nil,
+		},
+		Mounts:        mounts,
+		ProcessConfig: processConfig,
+	}
+
+	p, err := driver.generateLXCConfig(command)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	grepFile(t, p, "lxc.utsname = docker")
+	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
+
+	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir"))
+	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file"))
+}