github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_update_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "os/exec" 9 "strings" 10 "time" 11 12 "github.com/docker/docker/api/types" 13 "github.com/docker/docker/integration-cli/checker" 14 "github.com/docker/docker/integration-cli/request" 15 "github.com/docker/docker/pkg/parsers/kernel" 16 "github.com/go-check/check" 17 "github.com/kr/pty" 18 ) 19 20 func (s *DockerSuite) TestUpdateRunningContainer(c *check.C) { 21 testRequires(c, DaemonIsLinux) 22 testRequires(c, memoryLimitSupport) 23 24 name := "test-update-container" 25 dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "top") 26 dockerCmd(c, "update", "-m", "500M", name) 27 28 c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "524288000") 29 30 file := "/sys/fs/cgroup/memory/memory.limit_in_bytes" 31 out, _ := dockerCmd(c, "exec", name, "cat", file) 32 c.Assert(strings.TrimSpace(out), checker.Equals, "524288000") 33 } 34 35 func (s *DockerSuite) TestUpdateRunningContainerWithRestart(c *check.C) { 36 testRequires(c, DaemonIsLinux) 37 testRequires(c, memoryLimitSupport) 38 39 name := "test-update-container" 40 dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "top") 41 dockerCmd(c, "update", "-m", "500M", name) 42 dockerCmd(c, "restart", name) 43 44 c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "524288000") 45 46 file := "/sys/fs/cgroup/memory/memory.limit_in_bytes" 47 out, _ := dockerCmd(c, "exec", name, "cat", file) 48 c.Assert(strings.TrimSpace(out), checker.Equals, "524288000") 49 } 50 51 func (s *DockerSuite) TestUpdateStoppedContainer(c *check.C) { 52 testRequires(c, DaemonIsLinux) 53 testRequires(c, memoryLimitSupport) 54 55 name := "test-update-container" 56 file := "/sys/fs/cgroup/memory/memory.limit_in_bytes" 57 dockerCmd(c, "run", "--name", name, "-m", "300M", "busybox", "cat", file) 58 dockerCmd(c, "update", "-m", "500M", name) 59 60 c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "524288000") 61 62 out, _ := dockerCmd(c, "start", "-a", name) 63 c.Assert(strings.TrimSpace(out), checker.Equals, "524288000") 64 } 65 66 func (s *DockerSuite) TestUpdatePausedContainer(c *check.C) { 67 testRequires(c, DaemonIsLinux) 68 testRequires(c, cpuShare) 69 70 name := "test-update-container" 71 dockerCmd(c, "run", "-d", "--name", name, "--cpu-shares", "1000", "busybox", "top") 72 dockerCmd(c, "pause", name) 73 dockerCmd(c, "update", "--cpu-shares", "500", name) 74 75 c.Assert(inspectField(c, name, "HostConfig.CPUShares"), checker.Equals, "500") 76 77 dockerCmd(c, "unpause", name) 78 file := "/sys/fs/cgroup/cpu/cpu.shares" 79 out, _ := dockerCmd(c, "exec", name, "cat", file) 80 c.Assert(strings.TrimSpace(out), checker.Equals, "500") 81 } 82 83 func (s *DockerSuite) TestUpdateWithUntouchedFields(c *check.C) { 84 testRequires(c, DaemonIsLinux) 85 testRequires(c, memoryLimitSupport) 86 testRequires(c, cpuShare) 87 88 name := "test-update-container" 89 dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "--cpu-shares", "800", "busybox", "top") 90 dockerCmd(c, "update", "-m", "500M", name) 91 92 // Update memory and not touch cpus, `cpuset.cpus` should still have the old value 93 out := inspectField(c, name, "HostConfig.CPUShares") 94 c.Assert(out, check.Equals, "800") 95 96 file := "/sys/fs/cgroup/cpu/cpu.shares" 97 out, _ = dockerCmd(c, "exec", name, "cat", file) 98 c.Assert(strings.TrimSpace(out), checker.Equals, "800") 99 } 100 101 func (s *DockerSuite) TestUpdateContainerInvalidValue(c *check.C) { 102 testRequires(c, DaemonIsLinux) 103 testRequires(c, memoryLimitSupport) 104 105 name := "test-update-container" 106 dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "true") 107 out, _, err := dockerCmdWithError("update", "-m", "2M", name) 108 c.Assert(err, check.NotNil) 109 expected := "Minimum memory limit allowed is 4MB" 110 c.Assert(out, checker.Contains, expected) 111 } 112 113 func (s *DockerSuite) TestUpdateContainerWithoutFlags(c *check.C) { 114 testRequires(c, DaemonIsLinux) 115 testRequires(c, memoryLimitSupport) 116 117 name := "test-update-container" 118 dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "true") 119 _, _, err := dockerCmdWithError("update", name) 120 c.Assert(err, check.NotNil) 121 } 122 123 func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) { 124 testRequires(c, DaemonIsLinux, kernelMemorySupport) 125 126 name := "test-update-container" 127 dockerCmd(c, "run", "-d", "--name", name, "--kernel-memory", "50M", "busybox", "top") 128 dockerCmd(c, "update", "--kernel-memory", "100M", name) 129 130 c.Assert(inspectField(c, name, "HostConfig.KernelMemory"), checker.Equals, "104857600") 131 132 file := "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes" 133 out, _ := dockerCmd(c, "exec", name, "cat", file) 134 c.Assert(strings.TrimSpace(out), checker.Equals, "104857600") 135 } 136 137 func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) { 138 testRequires(c, DaemonIsLinux, kernelMemorySupport) 139 140 isNewKernel := kernel.CheckKernelVersion(4, 6, 0) 141 name := "test-update-container" 142 dockerCmd(c, "run", "-d", "--name", name, "busybox", "top") 143 _, _, err := dockerCmdWithError("update", "--kernel-memory", "100M", name) 144 // Update kernel memory to a running container without kernel memory initialized 145 // is not allowed before kernel version 4.6. 146 if !isNewKernel { 147 c.Assert(err, check.NotNil) 148 } else { 149 c.Assert(err, check.IsNil) 150 } 151 152 dockerCmd(c, "pause", name) 153 _, _, err = dockerCmdWithError("update", "--kernel-memory", "200M", name) 154 if !isNewKernel { 155 c.Assert(err, check.NotNil) 156 } else { 157 c.Assert(err, check.IsNil) 158 } 159 dockerCmd(c, "unpause", name) 160 161 dockerCmd(c, "stop", name) 162 dockerCmd(c, "update", "--kernel-memory", "300M", name) 163 dockerCmd(c, "start", name) 164 165 c.Assert(inspectField(c, name, "HostConfig.KernelMemory"), checker.Equals, "314572800") 166 167 file := "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes" 168 out, _ := dockerCmd(c, "exec", name, "cat", file) 169 c.Assert(strings.TrimSpace(out), checker.Equals, "314572800") 170 } 171 172 func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) { 173 testRequires(c, DaemonIsLinux) 174 testRequires(c, memoryLimitSupport) 175 testRequires(c, swapMemorySupport) 176 177 name := "test-update-container" 178 dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top") 179 dockerCmd(c, "update", "--memory-swap", "600M", name) 180 181 c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600") 182 183 file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes" 184 out, _ := dockerCmd(c, "exec", name, "cat", file) 185 c.Assert(strings.TrimSpace(out), checker.Equals, "629145600") 186 } 187 188 func (s *DockerSuite) TestUpdateInvalidSwapMemory(c *check.C) { 189 testRequires(c, DaemonIsLinux) 190 testRequires(c, memoryLimitSupport) 191 testRequires(c, swapMemorySupport) 192 193 name := "test-update-container" 194 dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top") 195 _, _, err := dockerCmdWithError("update", "--memory-swap", "200M", name) 196 // Update invalid swap memory should fail. 197 // This will pass docker config validation, but failed at kernel validation 198 c.Assert(err, check.NotNil) 199 200 // Update invalid swap memory with failure should not change HostConfig 201 c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "314572800") 202 c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "524288000") 203 204 dockerCmd(c, "update", "--memory-swap", "600M", name) 205 206 c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600") 207 208 file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes" 209 out, _ := dockerCmd(c, "exec", name, "cat", file) 210 c.Assert(strings.TrimSpace(out), checker.Equals, "629145600") 211 } 212 213 func (s *DockerSuite) TestUpdateStats(c *check.C) { 214 testRequires(c, DaemonIsLinux) 215 testRequires(c, memoryLimitSupport) 216 testRequires(c, cpuCfsQuota) 217 name := "foo" 218 dockerCmd(c, "run", "-d", "-ti", "--name", name, "-m", "500m", "busybox") 219 220 c.Assert(waitRun(name), checker.IsNil) 221 222 getMemLimit := func(id string) uint64 { 223 resp, body, err := request.Get(fmt.Sprintf("/containers/%s/stats?stream=false", id)) 224 c.Assert(err, checker.IsNil) 225 c.Assert(resp.Header.Get("Content-Type"), checker.Equals, "application/json") 226 227 var v *types.Stats 228 err = json.NewDecoder(body).Decode(&v) 229 c.Assert(err, checker.IsNil) 230 body.Close() 231 232 return v.MemoryStats.Limit 233 } 234 preMemLimit := getMemLimit(name) 235 236 dockerCmd(c, "update", "--cpu-quota", "2000", name) 237 238 curMemLimit := getMemLimit(name) 239 240 c.Assert(preMemLimit, checker.Equals, curMemLimit) 241 242 } 243 244 func (s *DockerSuite) TestUpdateMemoryWithSwapMemory(c *check.C) { 245 testRequires(c, DaemonIsLinux) 246 testRequires(c, memoryLimitSupport) 247 testRequires(c, swapMemorySupport) 248 249 name := "test-update-container" 250 dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "busybox", "top") 251 out, _, err := dockerCmdWithError("update", "--memory", "800M", name) 252 c.Assert(err, checker.NotNil) 253 c.Assert(out, checker.Contains, "Memory limit should be smaller than already set memoryswap limit") 254 255 dockerCmd(c, "update", "--memory", "800M", "--memory-swap", "1000M", name) 256 } 257 258 func (s *DockerSuite) TestUpdateNotAffectMonitorRestartPolicy(c *check.C) { 259 testRequires(c, DaemonIsLinux, cpuShare) 260 261 out, _ := dockerCmd(c, "run", "-tid", "--restart=always", "busybox", "sh") 262 id := strings.TrimSpace(string(out)) 263 dockerCmd(c, "update", "--cpu-shares", "512", id) 264 265 cpty, tty, err := pty.Open() 266 c.Assert(err, checker.IsNil) 267 defer cpty.Close() 268 269 cmd := exec.Command(dockerBinary, "attach", id) 270 cmd.Stdin = tty 271 272 c.Assert(cmd.Start(), checker.IsNil) 273 defer cmd.Process.Kill() 274 275 _, err = cpty.Write([]byte("exit\n")) 276 c.Assert(err, checker.IsNil) 277 278 c.Assert(cmd.Wait(), checker.IsNil) 279 280 // container should restart again and keep running 281 err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second) 282 c.Assert(err, checker.IsNil) 283 c.Assert(waitRun(id), checker.IsNil) 284 } 285 286 func (s *DockerSuite) TestUpdateWithNanoCPUs(c *check.C) { 287 testRequires(c, cpuCfsQuota, cpuCfsPeriod) 288 289 file1 := "/sys/fs/cgroup/cpu/cpu.cfs_quota_us" 290 file2 := "/sys/fs/cgroup/cpu/cpu.cfs_period_us" 291 292 out, _ := dockerCmd(c, "run", "-d", "--cpus", "0.5", "--name", "top", "busybox", "top") 293 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 294 295 out, _ = dockerCmd(c, "exec", "top", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2)) 296 c.Assert(strings.TrimSpace(out), checker.Equals, "50000\n100000") 297 298 out = inspectField(c, "top", "HostConfig.NanoCpus") 299 c.Assert(out, checker.Equals, "5e+08", check.Commentf("setting the Nano CPUs failed")) 300 out = inspectField(c, "top", "HostConfig.CpuQuota") 301 c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS quota should be 0")) 302 out = inspectField(c, "top", "HostConfig.CpuPeriod") 303 c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS period should be 0")) 304 305 out, _, err := dockerCmdWithError("update", "--cpu-quota", "80000", "top") 306 c.Assert(err, checker.NotNil) 307 c.Assert(out, checker.Contains, "Conflicting options: CPU Quota cannot be updated as NanoCPUs has already been set") 308 309 out, _ = dockerCmd(c, "update", "--cpus", "0.8", "top") 310 out = inspectField(c, "top", "HostConfig.NanoCpus") 311 c.Assert(out, checker.Equals, "8e+08", check.Commentf("updating the Nano CPUs failed")) 312 out = inspectField(c, "top", "HostConfig.CpuQuota") 313 c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS quota should be 0")) 314 out = inspectField(c, "top", "HostConfig.CpuPeriod") 315 c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS period should be 0")) 316 317 out, _ = dockerCmd(c, "exec", "top", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2)) 318 c.Assert(strings.TrimSpace(out), checker.Equals, "80000\n100000") 319 }