From 42b42ce4ee8adc298167a3085e2f1da7cbbeffb4 Mon Sep 17 00:00:00 2001 From: Qiang Huang Date: Fri, 18 Mar 2016 11:16:53 +0800 Subject: [PATCH 1/2] Add validation for cpu period and quota Accoding to: https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt It has minimal and maximal limit. Signed-off-by: Qiang Huang Upstream-commit: b041fdc0d53c209a5e0614d2b35c6fa2209fe12d Component: engine --- components/engine/daemon/daemon_unix.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go index b6e60ff77c..e2e6f7a5c1 100644 --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/daemon/daemon_unix.go @@ -393,11 +393,17 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.") resources.CPUPeriod = 0 } + if resources.CPUPeriod > 0 && (resources.CPUPeriod < 1000 || resources.CPUQuota > 1000000) { + return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)") + } if resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota { warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.") resources.CPUQuota = 0 } + if resources.CPUQuota > 0 && resources.CPUQuota < 1000 { + return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)") + } // cpuset subsystem checks and adjustments if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset { From ec3df3b28a27dff35d4f602509b5958997563040 Mon Sep 17 00:00:00 2001 From: Qiang Huang Date: Tue, 22 Mar 2016 08:53:57 +0800 Subject: [PATCH 2/2] Remove dot in suffix to avoid double dot error message Signed-off-by: Qiang Huang Upstream-commit: aae4bcf773a88f854c720387040a0a289a2fca87 Component: engine --- components/engine/daemon/daemon.go | 2 +- components/engine/daemon/daemon_unix.go | 20 +++++++++---------- .../docker_api_containers_test.go | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go index 974bf6e9d9..a2aea0dc54 100644 --- a/components/engine/daemon/daemon.go +++ b/components/engine/daemon/daemon.go @@ -1440,7 +1440,7 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon if config.WorkingDir != "" { config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics if !system.IsAbs(config.WorkingDir) { - return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir) + return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir) } } diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go index e2e6f7a5c1..50cff9db2b 100644 --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/daemon/daemon_unix.go @@ -330,10 +330,10 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi resources.MemorySwap = -1 } if resources.Memory > 0 && resources.MemorySwap > 0 && resources.MemorySwap < resources.Memory { - return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") + return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage") } if resources.Memory == 0 && resources.MemorySwap > 0 && !update { - return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.") + return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage") } if resources.MemorySwappiness != nil && *resources.MemorySwappiness != -1 && !sysInfo.MemorySwappiness { warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") @@ -343,7 +343,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi if resources.MemorySwappiness != nil { swappiness := *resources.MemorySwappiness if swappiness < -1 || swappiness > 100 { - return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness) + return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100", swappiness) } } if resources.MemoryReservation > 0 && !sysInfo.MemoryReservation { @@ -352,7 +352,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi resources.MemoryReservation = 0 } if resources.Memory > 0 && resources.MemoryReservation > 0 && resources.Memory < resources.MemoryReservation { - return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.") + return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage") } if resources.KernelMemory > 0 && !sysInfo.KernelMemory { warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.") @@ -414,17 +414,17 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi } cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus) if err != nil { - return warnings, fmt.Errorf("Invalid value %s for cpuset cpus.", resources.CpusetCpus) + return warnings, fmt.Errorf("Invalid value %s for cpuset cpus", resources.CpusetCpus) } if !cpusAvailable { - return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s.", resources.CpusetCpus, sysInfo.Cpus) + return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s", resources.CpusetCpus, sysInfo.Cpus) } memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems) if err != nil { - return warnings, fmt.Errorf("Invalid value %s for cpuset mems.", resources.CpusetMems) + return warnings, fmt.Errorf("Invalid value %s for cpuset mems", resources.CpusetMems) } if !memsAvailable { - return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s.", resources.CpusetMems, sysInfo.Mems) + return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s", resources.CpusetMems, sysInfo.Mems) } // blkio subsystem checks and adjustments @@ -434,7 +434,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi resources.BlkioWeight = 0 } if resources.BlkioWeight > 0 && (resources.BlkioWeight < 10 || resources.BlkioWeight > 1000) { - return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") + return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000") } if len(resources.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice { warnings = append(warnings, "Your kernel does not support Block I/O weight_device.") @@ -513,7 +513,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. } if hostConfig.OomScoreAdj < -1000 || hostConfig.OomScoreAdj > 1000 { - return warnings, fmt.Errorf("Invalid value %d, range for oom score adj is [-1000, 1000].", hostConfig.OomScoreAdj) + return warnings, fmt.Errorf("Invalid value %d, range for oom score adj is [-1000, 1000]", hostConfig.OomScoreAdj) } if sysInfo.IPv4ForwardingDisabled { warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.") diff --git a/components/engine/integration-cli/docker_api_containers_test.go b/components/engine/integration-cli/docker_api_containers_test.go index eb671459f2..c6447a81b8 100644 --- a/components/engine/integration-cli/docker_api_containers_test.go +++ b/components/engine/integration-cli/docker_api_containers_test.go @@ -1419,7 +1419,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) status, body, err := sockRequest("POST", "/containers/create?name="+name, c1) c.Assert(err, checker.IsNil) c.Assert(status, checker.Equals, http.StatusInternalServerError) - expected := "Invalid value 1-42,, for cpuset cpus.\n" + expected := "Invalid value 1-42,, for cpuset cpus\n" c.Assert(string(body), checker.Equals, expected) c2 := struct { @@ -1430,7 +1430,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) status, body, err = sockRequest("POST", "/containers/create?name="+name, c2) c.Assert(err, checker.IsNil) c.Assert(status, checker.Equals, http.StatusInternalServerError) - expected = "Invalid value 42-3,1-- for cpuset mems.\n" + expected = "Invalid value 42-3,1-- for cpuset mems\n" c.Assert(string(body), checker.Equals, expected) } @@ -1598,7 +1598,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che status, b, err := sockRequest("POST", "/containers/create?name="+name, config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusInternalServerError) - expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]." + expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]" if !strings.Contains(string(b), expected) { c.Fatalf("Expected output to contain %q, got %q", expected, string(b)) } @@ -1611,7 +1611,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che status, b, err = sockRequest("POST", "/containers/create?name="+name, config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusInternalServerError) - expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]." + expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]" if !strings.Contains(string(b), expected) { c.Fatalf("Expected output to contain %q, got %q", expected, string(b)) }