Add validation for cpu period and quota
| ... | ... |
@@ -1441,7 +1441,7 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon |
| 1441 | 1441 |
if config.WorkingDir != "" {
|
| 1442 | 1442 |
config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics |
| 1443 | 1443 |
if !system.IsAbs(config.WorkingDir) {
|
| 1444 |
- return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
|
|
| 1444 |
+ return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir)
|
|
| 1445 | 1445 |
} |
| 1446 | 1446 |
} |
| 1447 | 1447 |
|
| ... | ... |
@@ -334,10 +334,10 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 334 | 334 |
resources.MemorySwap = -1 |
| 335 | 335 |
} |
| 336 | 336 |
if resources.Memory > 0 && resources.MemorySwap > 0 && resources.MemorySwap < resources.Memory {
|
| 337 |
- return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.")
|
|
| 337 |
+ return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage")
|
|
| 338 | 338 |
} |
| 339 | 339 |
if resources.Memory == 0 && resources.MemorySwap > 0 && !update {
|
| 340 |
- return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
|
|
| 340 |
+ return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage")
|
|
| 341 | 341 |
} |
| 342 | 342 |
if resources.MemorySwappiness != nil && *resources.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
|
| 343 | 343 |
warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") |
| ... | ... |
@@ -347,7 +347,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 347 | 347 |
if resources.MemorySwappiness != nil {
|
| 348 | 348 |
swappiness := *resources.MemorySwappiness |
| 349 | 349 |
if swappiness < -1 || swappiness > 100 {
|
| 350 |
- return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
|
|
| 350 |
+ return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100", swappiness)
|
|
| 351 | 351 |
} |
| 352 | 352 |
} |
| 353 | 353 |
if resources.MemoryReservation > 0 && !sysInfo.MemoryReservation {
|
| ... | ... |
@@ -356,7 +356,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 356 | 356 |
resources.MemoryReservation = 0 |
| 357 | 357 |
} |
| 358 | 358 |
if resources.Memory > 0 && resources.MemoryReservation > 0 && resources.Memory < resources.MemoryReservation {
|
| 359 |
- return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.")
|
|
| 359 |
+ return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage")
|
|
| 360 | 360 |
} |
| 361 | 361 |
if resources.KernelMemory > 0 && !sysInfo.KernelMemory {
|
| 362 | 362 |
warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.") |
| ... | ... |
@@ -397,11 +397,17 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 397 | 397 |
logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
|
| 398 | 398 |
resources.CPUPeriod = 0 |
| 399 | 399 |
} |
| 400 |
+ if resources.CPUPeriod > 0 && (resources.CPUPeriod < 1000 || resources.CPUQuota > 1000000) {
|
|
| 401 |
+ return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
|
|
| 402 |
+ } |
|
| 400 | 403 |
if resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
|
| 401 | 404 |
warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") |
| 402 | 405 |
logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
|
| 403 | 406 |
resources.CPUQuota = 0 |
| 404 | 407 |
} |
| 408 |
+ if resources.CPUQuota > 0 && resources.CPUQuota < 1000 {
|
|
| 409 |
+ return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
|
|
| 410 |
+ } |
|
| 405 | 411 |
|
| 406 | 412 |
// cpuset subsystem checks and adjustments |
| 407 | 413 |
if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset {
|
| ... | ... |
@@ -412,17 +418,17 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 412 | 412 |
} |
| 413 | 413 |
cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus) |
| 414 | 414 |
if err != nil {
|
| 415 |
- return warnings, fmt.Errorf("Invalid value %s for cpuset cpus.", resources.CpusetCpus)
|
|
| 415 |
+ return warnings, fmt.Errorf("Invalid value %s for cpuset cpus", resources.CpusetCpus)
|
|
| 416 | 416 |
} |
| 417 | 417 |
if !cpusAvailable {
|
| 418 |
- return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s.", resources.CpusetCpus, sysInfo.Cpus)
|
|
| 418 |
+ return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s", resources.CpusetCpus, sysInfo.Cpus)
|
|
| 419 | 419 |
} |
| 420 | 420 |
memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems) |
| 421 | 421 |
if err != nil {
|
| 422 |
- return warnings, fmt.Errorf("Invalid value %s for cpuset mems.", resources.CpusetMems)
|
|
| 422 |
+ return warnings, fmt.Errorf("Invalid value %s for cpuset mems", resources.CpusetMems)
|
|
| 423 | 423 |
} |
| 424 | 424 |
if !memsAvailable {
|
| 425 |
- return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s.", resources.CpusetMems, sysInfo.Mems)
|
|
| 425 |
+ return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s", resources.CpusetMems, sysInfo.Mems)
|
|
| 426 | 426 |
} |
| 427 | 427 |
|
| 428 | 428 |
// blkio subsystem checks and adjustments |
| ... | ... |
@@ -432,7 +438,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 432 | 432 |
resources.BlkioWeight = 0 |
| 433 | 433 |
} |
| 434 | 434 |
if resources.BlkioWeight > 0 && (resources.BlkioWeight < 10 || resources.BlkioWeight > 1000) {
|
| 435 |
- return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
|
|
| 435 |
+ return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000")
|
|
| 436 | 436 |
} |
| 437 | 437 |
if len(resources.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
|
| 438 | 438 |
warnings = append(warnings, "Your kernel does not support Block I/O weight_device.") |
| ... | ... |
@@ -512,7 +518,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. |
| 512 | 512 |
} |
| 513 | 513 |
|
| 514 | 514 |
if hostConfig.OomScoreAdj < -1000 || hostConfig.OomScoreAdj > 1000 {
|
| 515 |
- return warnings, fmt.Errorf("Invalid value %d, range for oom score adj is [-1000, 1000].", hostConfig.OomScoreAdj)
|
|
| 515 |
+ return warnings, fmt.Errorf("Invalid value %d, range for oom score adj is [-1000, 1000]", hostConfig.OomScoreAdj)
|
|
| 516 | 516 |
} |
| 517 | 517 |
if sysInfo.IPv4ForwardingDisabled {
|
| 518 | 518 |
warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.") |
| ... | ... |
@@ -1419,7 +1419,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) |
| 1419 | 1419 |
status, body, err := sockRequest("POST", "/containers/create?name="+name, c1)
|
| 1420 | 1420 |
c.Assert(err, checker.IsNil) |
| 1421 | 1421 |
c.Assert(status, checker.Equals, http.StatusInternalServerError) |
| 1422 |
- expected := "Invalid value 1-42,, for cpuset cpus.\n" |
|
| 1422 |
+ expected := "Invalid value 1-42,, for cpuset cpus\n" |
|
| 1423 | 1423 |
c.Assert(string(body), checker.Equals, expected) |
| 1424 | 1424 |
|
| 1425 | 1425 |
c2 := struct {
|
| ... | ... |
@@ -1430,7 +1430,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) |
| 1430 | 1430 |
status, body, err = sockRequest("POST", "/containers/create?name="+name, c2)
|
| 1431 | 1431 |
c.Assert(err, checker.IsNil) |
| 1432 | 1432 |
c.Assert(status, checker.Equals, http.StatusInternalServerError) |
| 1433 |
- expected = "Invalid value 42-3,1-- for cpuset mems.\n" |
|
| 1433 |
+ expected = "Invalid value 42-3,1-- for cpuset mems\n" |
|
| 1434 | 1434 |
c.Assert(string(body), checker.Equals, expected) |
| 1435 | 1435 |
} |
| 1436 | 1436 |
|
| ... | ... |
@@ -1598,7 +1598,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che |
| 1598 | 1598 |
status, b, err := sockRequest("POST", "/containers/create?name="+name, config)
|
| 1599 | 1599 |
c.Assert(err, check.IsNil) |
| 1600 | 1600 |
c.Assert(status, check.Equals, http.StatusInternalServerError) |
| 1601 |
- expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]." |
|
| 1601 |
+ expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]" |
|
| 1602 | 1602 |
if !strings.Contains(string(b), expected) {
|
| 1603 | 1603 |
c.Fatalf("Expected output to contain %q, got %q", expected, string(b))
|
| 1604 | 1604 |
} |
| ... | ... |
@@ -1611,7 +1611,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che |
| 1611 | 1611 |
status, b, err = sockRequest("POST", "/containers/create?name="+name, config)
|
| 1612 | 1612 |
c.Assert(err, check.IsNil) |
| 1613 | 1613 |
c.Assert(status, check.Equals, http.StatusInternalServerError) |
| 1614 |
- expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]." |
|
| 1614 |
+ expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]" |
|
| 1615 | 1615 |
if !strings.Contains(string(b), expected) {
|
| 1616 | 1616 |
c.Fatalf("Expected output to contain %q, got %q", expected, string(b))
|
| 1617 | 1617 |
} |