Merge pull request #21315 from hqhq/hq_check_quota

Add validation for cpu period and quota
This commit is contained in:
Sebastiaan van Stijn 2016-03-24 14:10:48 -07:00
commit f2847f8ab3
3 changed files with 21 additions and 15 deletions

View File

@ -1441,7 +1441,7 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
if config.WorkingDir != "" { if config.WorkingDir != "" {
config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
if !system.IsAbs(config.WorkingDir) { 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)
} }
} }

View File

@ -334,10 +334,10 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
resources.MemorySwap = -1 resources.MemorySwap = -1
} }
if resources.Memory > 0 && resources.MemorySwap > 0 && resources.MemorySwap < resources.Memory { 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 { 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 { if resources.MemorySwappiness != nil && *resources.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") 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
if resources.MemorySwappiness != nil { if resources.MemorySwappiness != nil {
swappiness := *resources.MemorySwappiness swappiness := *resources.MemorySwappiness
if swappiness < -1 || swappiness > 100 { 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 { if resources.MemoryReservation > 0 && !sysInfo.MemoryReservation {
@ -356,7 +356,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
resources.MemoryReservation = 0 resources.MemoryReservation = 0
} }
if resources.Memory > 0 && resources.MemoryReservation > 0 && resources.Memory < resources.MemoryReservation { 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 { if resources.KernelMemory > 0 && !sysInfo.KernelMemory {
warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.") 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
logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.") logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
resources.CPUPeriod = 0 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 { if resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") 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.") logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
resources.CPUQuota = 0 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 // cpuset subsystem checks and adjustments
if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset { if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset {
@ -412,17 +418,17 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
} }
cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus) cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus)
if err != nil { 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 { 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) memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems)
if err != nil { 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 { 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 // blkio subsystem checks and adjustments
@ -432,7 +438,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
resources.BlkioWeight = 0 resources.BlkioWeight = 0
} }
if resources.BlkioWeight > 0 && (resources.BlkioWeight < 10 || resources.BlkioWeight > 1000) { 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 { if len(resources.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
warnings = append(warnings, "Your kernel does not support Block I/O weight_device.") warnings = append(warnings, "Your kernel does not support Block I/O weight_device.")
@ -512,7 +518,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
} }
if hostConfig.OomScoreAdj < -1000 || hostConfig.OomScoreAdj > 1000 { 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 { if sysInfo.IPv4ForwardingDisabled {
warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.") warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")

View File

@ -1419,7 +1419,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C)
status, body, err := sockRequest("POST", "/containers/create?name="+name, c1) status, body, err := sockRequest("POST", "/containers/create?name="+name, c1)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusInternalServerError) 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) c.Assert(string(body), checker.Equals, expected)
c2 := struct { c2 := struct {
@ -1430,7 +1430,7 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C)
status, body, err = sockRequest("POST", "/containers/create?name="+name, c2) status, body, err = sockRequest("POST", "/containers/create?name="+name, c2)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusInternalServerError) 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) 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) status, b, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusInternalServerError) 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) { if !strings.Contains(string(b), expected) {
c.Fatalf("Expected output to contain %q, got %q", expected, string(b)) 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) status, b, err = sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusInternalServerError) 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) { if !strings.Contains(string(b), expected) {
c.Fatalf("Expected output to contain %q, got %q", expected, string(b)) c.Fatalf("Expected output to contain %q, got %q", expected, string(b))
} }