github.com/ld86/docker@v1.7.1-rc3/daemon/execdriver/lxc/lxc_template_unit_test.go (about)

     1  // +build linux
     2  
     3  package lxc
     4  
     5  import (
     6  	"bufio"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"math/rand"
    10  	"os"
    11  	"path"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/docker/docker/daemon/execdriver"
    17  	nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
    18  	"github.com/docker/libcontainer/configs"
    19  	"github.com/syndtr/gocapability/capability"
    20  )
    21  
    22  func TestLXCConfig(t *testing.T) {
    23  	root, err := ioutil.TempDir("", "TestLXCConfig")
    24  	if err != nil {
    25  		t.Fatal(err)
    26  	}
    27  	defer os.RemoveAll(root)
    28  
    29  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
    30  
    31  	// Memory is allocated randomly for testing
    32  	r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
    33  	var (
    34  		memMin = 33554432
    35  		memMax = 536870912
    36  		mem    = memMin + r.Intn(memMax-memMin)
    37  		cpuMin = 100
    38  		cpuMax = 10000
    39  		cpu    = cpuMin + r.Intn(cpuMax-cpuMin)
    40  	)
    41  
    42  	driver, err := NewDriver(root, root, "", false)
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	command := &execdriver.Command{
    47  		ID: "1",
    48  		Resources: &execdriver.Resources{
    49  			Memory:    int64(mem),
    50  			CpuShares: int64(cpu),
    51  		},
    52  		Network: &execdriver.Network{
    53  			Mtu:       1500,
    54  			Interface: nil,
    55  		},
    56  		AllowedDevices: make([]*configs.Device, 0),
    57  		ProcessConfig:  execdriver.ProcessConfig{},
    58  	}
    59  	p, err := driver.generateLXCConfig(command)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	grepFile(t, p,
    64  		fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
    65  
    66  	grepFile(t, p,
    67  		fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
    68  }
    69  
    70  func TestCustomLxcConfig(t *testing.T) {
    71  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	defer os.RemoveAll(root)
    76  
    77  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
    78  
    79  	driver, err := NewDriver(root, root, "", false)
    80  	if err != nil {
    81  		t.Fatal(err)
    82  	}
    83  	processConfig := execdriver.ProcessConfig{
    84  		Privileged: false,
    85  	}
    86  	command := &execdriver.Command{
    87  		ID: "1",
    88  		LxcConfig: []string{
    89  			"lxc.utsname = docker",
    90  			"lxc.cgroup.cpuset.cpus = 0,1",
    91  		},
    92  		Network: &execdriver.Network{
    93  			Mtu:       1500,
    94  			Interface: nil,
    95  		},
    96  		ProcessConfig: processConfig,
    97  	}
    98  
    99  	p, err := driver.generateLXCConfig(command)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  
   104  	grepFile(t, p, "lxc.utsname = docker")
   105  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   106  }
   107  
   108  func grepFile(t *testing.T, path string, pattern string) {
   109  	grepFileWithReverse(t, path, pattern, false)
   110  }
   111  
   112  func grepFileWithReverse(t *testing.T, path string, pattern string, inverseGrep bool) {
   113  	f, err := os.Open(path)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  	defer f.Close()
   118  	r := bufio.NewReader(f)
   119  	var (
   120  		line string
   121  	)
   122  	err = nil
   123  	for err == nil {
   124  		line, err = r.ReadString('\n')
   125  		if strings.Contains(line, pattern) == true {
   126  			if inverseGrep {
   127  				t.Fatalf("grepFile: pattern \"%s\" found in \"%s\"", pattern, path)
   128  			}
   129  			return
   130  		}
   131  	}
   132  	if inverseGrep {
   133  		return
   134  	}
   135  	t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
   136  }
   137  
   138  func TestEscapeFstabSpaces(t *testing.T) {
   139  	var testInputs = map[string]string{
   140  		" ":                      "\\040",
   141  		"":                       "",
   142  		"/double  space":         "/double\\040\\040space",
   143  		"/some long test string": "/some\\040long\\040test\\040string",
   144  		"/var/lib/docker":        "/var/lib/docker",
   145  		" leading":               "\\040leading",
   146  		"trailing ":              "trailing\\040",
   147  	}
   148  	for in, exp := range testInputs {
   149  		if out := escapeFstabSpaces(in); exp != out {
   150  			t.Logf("Expected %s got %s", exp, out)
   151  			t.Fail()
   152  		}
   153  	}
   154  }
   155  
   156  func TestIsDirectory(t *testing.T) {
   157  	tempDir, err := ioutil.TempDir("", "TestIsDir")
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	defer os.RemoveAll(tempDir)
   162  
   163  	tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile")
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  
   168  	if isDirectory(tempDir) != "dir" {
   169  		t.Logf("Could not identify %s as a directory", tempDir)
   170  		t.Fail()
   171  	}
   172  
   173  	if isDirectory(tempFile.Name()) != "file" {
   174  		t.Logf("Could not identify %s as a file", tempFile.Name())
   175  		t.Fail()
   176  	}
   177  }
   178  
   179  func TestCustomLxcConfigMounts(t *testing.T) {
   180  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  	defer os.RemoveAll(root)
   185  	tempDir, err := ioutil.TempDir("", "TestIsDir")
   186  	if err != nil {
   187  		t.Fatal(err)
   188  	}
   189  	defer os.RemoveAll(tempDir)
   190  
   191  	tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile")
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
   196  
   197  	driver, err := NewDriver(root, root, "", false)
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	processConfig := execdriver.ProcessConfig{
   202  		Privileged: false,
   203  	}
   204  	mounts := []execdriver.Mount{
   205  		{
   206  			Source:      tempDir,
   207  			Destination: tempDir,
   208  			Writable:    false,
   209  			Private:     true,
   210  		},
   211  		{
   212  			Source:      tempFile.Name(),
   213  			Destination: tempFile.Name(),
   214  			Writable:    true,
   215  			Private:     true,
   216  		},
   217  	}
   218  	command := &execdriver.Command{
   219  		ID: "1",
   220  		LxcConfig: []string{
   221  			"lxc.utsname = docker",
   222  			"lxc.cgroup.cpuset.cpus = 0,1",
   223  		},
   224  		Network: &execdriver.Network{
   225  			Mtu:       1500,
   226  			Interface: nil,
   227  		},
   228  		Mounts:        mounts,
   229  		ProcessConfig: processConfig,
   230  	}
   231  
   232  	p, err := driver.generateLXCConfig(command)
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  
   237  	grepFile(t, p, "lxc.utsname = docker")
   238  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   239  
   240  	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir"))
   241  	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file"))
   242  }
   243  
   244  func TestCustomLxcConfigMisc(t *testing.T) {
   245  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	defer os.RemoveAll(root)
   250  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
   251  	driver, err := NewDriver(root, root, "", true)
   252  
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	processConfig := execdriver.ProcessConfig{
   257  		Privileged: false,
   258  	}
   259  
   260  	processConfig.Env = []string{"HOSTNAME=testhost"}
   261  	command := &execdriver.Command{
   262  		ID: "1",
   263  		LxcConfig: []string{
   264  			"lxc.cgroup.cpuset.cpus = 0,1",
   265  		},
   266  		Network: &execdriver.Network{
   267  			Mtu:       1500,
   268  			Interface: nil,
   269  		},
   270  		ProcessConfig:   processConfig,
   271  		CapAdd:          []string{"net_admin", "syslog"},
   272  		CapDrop:         []string{"kill", "mknod"},
   273  		AppArmorProfile: "lxc-container-default-with-nesting",
   274  	}
   275  
   276  	p, err := driver.generateLXCConfig(command)
   277  	if err != nil {
   278  		t.Fatal(err)
   279  	}
   280  	grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting")
   281  	// hostname
   282  	grepFile(t, p, "lxc.utsname = testhost")
   283  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   284  	container := nativeTemplate.New()
   285  	for _, cap := range container.Capabilities {
   286  		realCap := execdriver.GetCapability(cap)
   287  		numCap := fmt.Sprintf("%d", realCap.Value)
   288  		if cap != "MKNOD" && cap != "KILL" {
   289  			grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap))
   290  		}
   291  	}
   292  
   293  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true)
   294  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true)
   295  }
   296  
   297  func TestCustomLxcConfigMiscOverride(t *testing.T) {
   298  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  	defer os.RemoveAll(root)
   303  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
   304  	driver, err := NewDriver(root, root, "", false)
   305  	if err != nil {
   306  		t.Fatal(err)
   307  	}
   308  	processConfig := execdriver.ProcessConfig{
   309  		Privileged: false,
   310  	}
   311  
   312  	processConfig.Env = []string{"HOSTNAME=testhost"}
   313  	command := &execdriver.Command{
   314  		ID: "1",
   315  		LxcConfig: []string{
   316  			"lxc.cgroup.cpuset.cpus = 0,1",
   317  			"lxc.network.ipv4 = 172.0.0.1",
   318  		},
   319  		Network: &execdriver.Network{
   320  			Mtu:       1500,
   321  			Interface: nil,
   322  		},
   323  		ProcessConfig: processConfig,
   324  		CapAdd:        []string{"NET_ADMIN", "SYSLOG"},
   325  		CapDrop:       []string{"KILL", "MKNOD"},
   326  	}
   327  
   328  	p, err := driver.generateLXCConfig(command)
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  
   333  	// hostname
   334  	grepFile(t, p, "lxc.utsname = testhost")
   335  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   336  	container := nativeTemplate.New()
   337  	for _, cap := range container.Capabilities {
   338  		realCap := execdriver.GetCapability(cap)
   339  		numCap := fmt.Sprintf("%d", realCap.Value)
   340  		if cap != "MKNOD" && cap != "KILL" {
   341  			grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap))
   342  		}
   343  	}
   344  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true)
   345  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true)
   346  }