github.com/circular-dark/docker@v1.7.0/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 }