From 24edf94c3be7bbecc9eb19231afbe368cee82a4b Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Tue, 15 Nov 2016 15:48:46 -0800 Subject: [PATCH] Fix error messages for `--cpus` from daemon This fix fixes error messages for `--cpus` from daemon. When `docker run` takes `--cpus`, it will translate into NanoCPUs and pass the value to daemon. The `NanoCPU` is not visible to the user. The error message generated from daemon used 'NanoCPU' which may cause some confusion to the user. This fix fixes this issue by returning the error in CPUs instead. This fix fixes 28456. Signed-off-by: Yong Tang Upstream-commit: d22ac2f3a0de8e2ff6da8f1787e3ac3ac7438f17 Component: engine --- components/engine/daemon/daemon_unix.go | 16 ++++++++++++---- components/engine/daemon/daemon_windows.go | 4 +++- .../integration-cli/docker_cli_run_unix_test.go | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go index b8b994de57..37c4bc09c4 100644 --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/daemon/daemon_unix.go @@ -112,10 +112,11 @@ func getCPUResources(config containertypes.Resources) *specs.CPU { } if config.NanoCPUs > 0 { - // Use the default setting of 100ms, as is specified in: + // We set the highest value possible (1s), as is specified in: // https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt - // cpu.cfs_period_us=100ms - period := uint64(100 * time.Millisecond / time.Microsecond) + // cpu.cfs_period_us=1s + // The purpose is to get the highest precision + period := uint64(1 * time.Second / time.Microsecond) quota := uint64(config.NanoCPUs) * period / 1e9 cpu.Period = &period cpu.Quota = "a @@ -361,8 +362,15 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi if resources.NanoCPUs > 0 && (!sysInfo.CPUCfsPeriod || !sysInfo.CPUCfsQuota) { return warnings, fmt.Errorf("NanoCPUs can not be set, as your kernel does not support CPU cfs period/quota or the cgroup is not mounted") } + // The highest precision we could get on Linux is 0.001, by setting + // cpu.cfs_period_us=1000ms + // cpu.cfs_quota=1ms + // See the following link for details: + // https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt + // Here we don't set the lower limit and it is up to the underlying platform (e.g., Linux) to return an error. + // The error message is 0.01 so that this is consistent with Windows if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 { - return warnings, fmt.Errorf("Range of Nano CPUs is from 1 to %d", int64(sysinfo.NumCPU())*1e9) + return warnings, fmt.Errorf("Range of CPUs is from 0.01 to %d.00, as there are only %d CPUs available", sysinfo.NumCPU(), sysinfo.NumCPU()) } if resources.CPUShares > 0 && !sysInfo.CPUShares { diff --git a/components/engine/daemon/daemon_windows.go b/components/engine/daemon/daemon_windows.go index 2620fc4b9d..257a6f3894 100644 --- a/components/engine/daemon/daemon_windows.go +++ b/components/engine/daemon/daemon_windows.go @@ -129,8 +129,10 @@ func verifyContainerResources(resources *containertypes.Resources, isHyperv bool if resources.NanoCPUs > 0 && resources.CPUShares > 0 { return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Shares cannot both be set") } + // The precision we could get is 0.01, because on Windows we have to convert to CPUPercent. + // We don't set the lower limit here and it is up to the underlying platform (e.g., Windows) to return an error. if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 { - return warnings, fmt.Errorf("range of Nano CPUs is from 1 to %d", int64(sysinfo.NumCPU())*1e9) + return warnings, fmt.Errorf("range of CPUs is from 0.01 to %d.00, as there are only %d CPUs available", sysinfo.NumCPU(), sysinfo.NumCPU()) } if len(resources.BlkioDeviceReadBps) > 0 { diff --git a/components/engine/integration-cli/docker_cli_run_unix_test.go b/components/engine/integration-cli/docker_cli_run_unix_test.go index 4c2f829e3c..49544f4225 100644 --- a/components/engine/integration-cli/docker_cli_run_unix_test.go +++ b/components/engine/integration-cli/docker_cli_run_unix_test.go @@ -1577,7 +1577,7 @@ func (s *DockerSuite) TestRunWithNanoCPUs(c *check.C) { file1 := "/sys/fs/cgroup/cpu/cpu.cfs_quota_us" file2 := "/sys/fs/cgroup/cpu/cpu.cfs_period_us" out, _ := dockerCmd(c, "run", "--cpus", "0.5", "--name", "test", "busybox", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2)) - c.Assert(strings.TrimSpace(out), checker.Equals, "50000\n100000") + c.Assert(strings.TrimSpace(out), checker.Equals, "500000\n1000000") out = inspectField(c, "test", "HostConfig.NanoCpus") c.Assert(out, checker.Equals, "5e+08", check.Commentf("setting the Nano CPUs failed"))