Browse code

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 <yong.tang.github@outlook.com>

Yong Tang authored on 2016/11/16 08:48:46
Showing 3 changed files
... ...
@@ -112,10 +112,11 @@ func getCPUResources(config containertypes.Resources) *specs.CPU {
112 112
 	}
113 113
 
114 114
 	if config.NanoCPUs > 0 {
115
-		// Use the default setting of 100ms, as is specified in:
115
+		// We set the highest value possible (1s), as is specified in:
116 116
 		// https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
117
-		//    	cpu.cfs_period_us=100ms
118
-		period := uint64(100 * time.Millisecond / time.Microsecond)
117
+		//    	cpu.cfs_period_us=1s
118
+		// The purpose is to get the highest precision
119
+		period := uint64(1 * time.Second / time.Microsecond)
119 120
 		quota := uint64(config.NanoCPUs) * period / 1e9
120 121
 		cpu.Period = &period
121 122
 		cpu.Quota = &quota
... ...
@@ -361,8 +362,15 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
361 361
 	if resources.NanoCPUs > 0 && (!sysInfo.CPUCfsPeriod || !sysInfo.CPUCfsQuota) {
362 362
 		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")
363 363
 	}
364
+	// The highest precision we could get on Linux is 0.001, by setting
365
+	//   cpu.cfs_period_us=1000ms
366
+	//   cpu.cfs_quota=1ms
367
+	// See the following link for details:
368
+	// https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
369
+	// Here we don't set the lower limit and it is up to the underlying platform (e.g., Linux) to return an error.
370
+	// The error message is 0.01 so that this is consistent with Windows
364 371
 	if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 {
365
-		return warnings, fmt.Errorf("Range of Nano CPUs is from 1 to %d", int64(sysinfo.NumCPU())*1e9)
372
+		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())
366 373
 	}
367 374
 
368 375
 	if resources.CPUShares > 0 && !sysInfo.CPUShares {
... ...
@@ -129,8 +129,10 @@ func verifyContainerResources(resources *containertypes.Resources, isHyperv bool
129 129
 	if resources.NanoCPUs > 0 && resources.CPUShares > 0 {
130 130
 		return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Shares cannot both be set")
131 131
 	}
132
+	// The precision we could get is 0.01, because on Windows we have to convert to CPUPercent.
133
+	// We don't set the lower limit here and it is up to the underlying platform (e.g., Windows) to return an error.
132 134
 	if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 {
133
-		return warnings, fmt.Errorf("range of Nano CPUs is from 1 to %d", int64(sysinfo.NumCPU())*1e9)
135
+		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())
134 136
 	}
135 137
 
136 138
 	if len(resources.BlkioDeviceReadBps) > 0 {
... ...
@@ -1577,7 +1577,7 @@ func (s *DockerSuite) TestRunWithNanoCPUs(c *check.C) {
1577 1577
 	file1 := "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"
1578 1578
 	file2 := "/sys/fs/cgroup/cpu/cpu.cfs_period_us"
1579 1579
 	out, _ := dockerCmd(c, "run", "--cpus", "0.5", "--name", "test", "busybox", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2))
1580
-	c.Assert(strings.TrimSpace(out), checker.Equals, "50000\n100000")
1580
+	c.Assert(strings.TrimSpace(out), checker.Equals, "500000\n1000000")
1581 1581
 
1582 1582
 	out = inspectField(c, "test", "HostConfig.NanoCpus")
1583 1583
 	c.Assert(out, checker.Equals, "5e+08", check.Commentf("setting the Nano CPUs failed"))