Browse code

Add CPU count and maximum resource controls for Windows

Signed-off-by: Darren Stahl <darst@microsoft.com>

Darren Stahl authored on 2016/03/05 10:24:09
Showing 6 changed files
... ...
@@ -408,6 +408,11 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
408 408
 	if resources.CPUQuota > 0 && resources.CPUQuota < 1000 {
409 409
 		return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
410 410
 	}
411
+	if resources.CPUPercent > 0 {
412
+		warnings = append(warnings, "%s does not support CPU percent. Percent discarded.", runtime.GOOS)
413
+		logrus.Warnf("%s does not support CPU percent. Percent discarded.", runtime.GOOS)
414
+		resources.CPUPercent = 0
415
+	}
411 416
 
412 417
 	// cpuset subsystem checks and adjustments
413 418
 	if (resources.CpusetCpus != "" || resources.CpusetMems != "") && !sysInfo.Cpuset {
... ...
@@ -16,6 +16,7 @@ import (
16 16
 	"github.com/docker/docker/dockerversion"
17 17
 	"github.com/docker/docker/image"
18 18
 	"github.com/docker/docker/layer"
19
+	"github.com/docker/docker/pkg/sysinfo"
19 20
 	"github.com/docker/docker/reference"
20 21
 	"github.com/docker/docker/runconfig"
21 22
 	// register the windows graph driver
... ...
@@ -95,10 +96,34 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
95 95
 	return nil
96 96
 }
97 97
 
98
+func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo) ([]string, error) {
99
+	warnings := []string{}
100
+
101
+	// cpu subsystem checks and adjustments
102
+	if resources.CPUPercent < 0 || resources.CPUPercent > 100 {
103
+		return warnings, fmt.Errorf("Range of CPU percent is from 1 to 100")
104
+	}
105
+
106
+	if resources.CPUPercent > 0 && resources.CPUShares > 0 {
107
+		return warnings, fmt.Errorf("Conflicting options: CPU Shares and CPU Percent cannot both be set")
108
+	}
109
+
110
+	return warnings, nil
111
+}
112
+
98 113
 // verifyPlatformContainerSettings performs platform-specific validation of the
99 114
 // hostconfig and config structures.
100 115
 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
101
-	return nil, nil
116
+
117
+	warnings := []string{}
118
+
119
+	w, err := verifyContainerResources(&hostConfig.Resources, nil)
120
+	warnings = append(warnings, w...)
121
+	if err != nil {
122
+		return warnings, err
123
+	}
124
+
125
+	return warnings, nil
102 126
 }
103 127
 
104 128
 // verifyDaemonSettings performs validation of daemon config struct
... ...
@@ -158,9 +158,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
158 158
 	cpuShares := uint64(c.HostConfig.CPUShares)
159 159
 	s.Windows.Resources = &windowsoci.Resources{
160 160
 		CPU: &windowsoci.CPU{
161
-			//TODO Count: ...,
162
-			//TODO Percent: ...,
163
-			Shares: &cpuShares,
161
+			Percent: &c.HostConfig.CPUPercent,
162
+			Shares:  &cpuShares,
164 163
 		},
165 164
 		Memory: &windowsoci.Memory{
166 165
 		//TODO Limit: ...,
... ...
@@ -293,6 +293,7 @@ Create a container
293 293
              "MemorySwap": 0,
294 294
              "MemoryReservation": 0,
295 295
              "KernelMemory": 0,
296
+             "CpuPercent": 80,
296 297
              "CpuShares": 512,
297 298
              "CpuPeriod": 100000,
298 299
              "CpuQuota": 50000,
... ...
@@ -353,6 +354,7 @@ Json Parameters:
353 353
       You must use this with `memory` and make the swap value larger than `memory`.
354 354
 -   **MemoryReservation** - Memory soft limit in bytes.
355 355
 -   **KernelMemory** - Kernel memory limit in bytes.
356
+-   **CpuPercent** - An integer value containing the usable percentage of the available CPUs. (Windows daemon only)
356 357
 -   **CpuShares** - An integer value containing the container's CPU Shares
357 358
       (ie. the relative weight vs other containers).
358 359
 -   **CpuPeriod** - The length of a CPU period in microseconds.
... ...
@@ -538,6 +540,7 @@ Return low-level information on the container `id`
538 538
 			"ContainerIDFile": "",
539 539
 			"CpusetCpus": "",
540 540
 			"CpusetMems": "",
541
+			"CpuPercent": 80,
541 542
 			"CpuShares": 0,
542 543
 			"CpuPeriod": 100000,
543 544
 			"Devices": [],
... ...
@@ -23,6 +23,7 @@ parent = "smn_cli"
23 23
       --cap-drop=[]                 Drop Linux capabilities
24 24
       --cgroup-parent=""            Optional parent cgroup for the container
25 25
       --cidfile=""                  Write the container ID to the file
26
+      --cpu-percent=0               Limit percentage of CPU available for execution by the container. Windows daemon only.
26 27
       --cpu-period=0                Limit CPU CFS (Completely Fair Scheduler) period
27 28
       --cpu-quota=0                 Limit CPU CFS (Completely Fair Scheduler) quota
28 29
       --cpuset-cpus=""              CPUs in which to allow execution (0-3, 0,1)
... ...
@@ -76,6 +76,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
76 76
 		flUser              = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
77 77
 		flWorkingDir        = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
78 78
 		flCPUShares         = cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
79
+		flCPUPercent        = cmd.Int64([]string{"-cpu-percent"}, 0, "CPU percent (Windows only)")
79 80
 		flCPUPeriod         = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period")
80 81
 		flCPUQuota          = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
81 82
 		flCpusetCpus        = cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
... ...
@@ -345,6 +346,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
345 345
 		MemorySwappiness:     flSwappiness,
346 346
 		KernelMemory:         KernelMemory,
347 347
 		OomKillDisable:       flOomKillDisable,
348
+		CPUPercent:           *flCPUPercent,
348 349
 		CPUShares:            *flCPUShares,
349 350
 		CPUPeriod:            *flCPUPeriod,
350 351
 		CpusetCpus:           *flCpusetCpus,