github.com/dougm/docker@v1.5.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 "github.com/docker/docker/daemon/execdriver" 9 nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" 10 "github.com/docker/libcontainer/devices" 11 "github.com/docker/libcontainer/security/capabilities" 12 "github.com/syndtr/gocapability/capability" 13 "io/ioutil" 14 "math/rand" 15 "os" 16 "path" 17 "strings" 18 "testing" 19 "time" 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 rand.Seed(time.Now().UTC().UnixNano()) 33 var ( 34 memMin = 33554432 35 memMax = 536870912 36 mem = memMin + rand.Intn(memMax-memMin) 37 cpuMin = 100 38 cpuMax = 10000 39 cpu = cpuMin + rand.Intn(cpuMax-cpuMin) 40 ) 41 42 driver, err := NewDriver(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([]*devices.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, "", 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, "", 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, "", 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: &execdriver.NetworkInterface{ 269 Gateway: "10.10.10.1", 270 IPAddress: "10.10.10.10", 271 IPPrefixLen: 24, 272 Bridge: "docker0", 273 }, 274 }, 275 ProcessConfig: processConfig, 276 CapAdd: []string{"net_admin", "syslog"}, 277 CapDrop: []string{"kill", "mknod"}, 278 AppArmorProfile: "lxc-container-default-with-nesting", 279 } 280 281 p, err := driver.generateLXCConfig(command) 282 if err != nil { 283 t.Fatal(err) 284 } 285 // network 286 grepFile(t, p, "lxc.network.type = veth") 287 grepFile(t, p, "lxc.network.link = docker0") 288 grepFile(t, p, "lxc.network.name = eth0") 289 grepFile(t, p, "lxc.network.ipv4 = 10.10.10.10/24") 290 grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1") 291 grepFile(t, p, "lxc.network.flags = up") 292 grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting") 293 // hostname 294 grepFile(t, p, "lxc.utsname = testhost") 295 grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") 296 container := nativeTemplate.New() 297 for _, cap := range container.Capabilities { 298 realCap := capabilities.GetCapability(cap) 299 numCap := fmt.Sprintf("%d", realCap.Value) 300 if cap != "MKNOD" && cap != "KILL" { 301 grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) 302 } 303 } 304 305 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) 306 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) 307 } 308 309 func TestCustomLxcConfigMiscOverride(t *testing.T) { 310 root, err := ioutil.TempDir("", "TestCustomLxcConfig") 311 if err != nil { 312 t.Fatal(err) 313 } 314 defer os.RemoveAll(root) 315 os.MkdirAll(path.Join(root, "containers", "1"), 0777) 316 driver, err := NewDriver(root, "", false) 317 if err != nil { 318 t.Fatal(err) 319 } 320 processConfig := execdriver.ProcessConfig{ 321 Privileged: false, 322 } 323 324 processConfig.Env = []string{"HOSTNAME=testhost"} 325 command := &execdriver.Command{ 326 ID: "1", 327 LxcConfig: []string{ 328 "lxc.cgroup.cpuset.cpus = 0,1", 329 "lxc.network.ipv4 = 172.0.0.1", 330 }, 331 Network: &execdriver.Network{ 332 Mtu: 1500, 333 Interface: &execdriver.NetworkInterface{ 334 Gateway: "10.10.10.1", 335 IPAddress: "10.10.10.10", 336 IPPrefixLen: 24, 337 Bridge: "docker0", 338 }, 339 }, 340 ProcessConfig: processConfig, 341 CapAdd: []string{"NET_ADMIN", "SYSLOG"}, 342 CapDrop: []string{"KILL", "MKNOD"}, 343 } 344 345 p, err := driver.generateLXCConfig(command) 346 if err != nil { 347 t.Fatal(err) 348 } 349 // network 350 grepFile(t, p, "lxc.network.type = veth") 351 grepFile(t, p, "lxc.network.link = docker0") 352 grepFile(t, p, "lxc.network.name = eth0") 353 grepFile(t, p, "lxc.network.ipv4 = 172.0.0.1") 354 grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1") 355 grepFile(t, p, "lxc.network.flags = up") 356 357 // hostname 358 grepFile(t, p, "lxc.utsname = testhost") 359 grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") 360 container := nativeTemplate.New() 361 for _, cap := range container.Capabilities { 362 realCap := capabilities.GetCapability(cap) 363 numCap := fmt.Sprintf("%d", realCap.Value) 364 if cap != "MKNOD" && cap != "KILL" { 365 grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) 366 } 367 } 368 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) 369 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) 370 }