Browse code

Adding more strict resource checks on Windows

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

Darren Stahl authored on 2016/11/10 08:18:54
Showing 2 changed files
... ...
@@ -8,7 +8,6 @@ import (
8 8
 	"github.com/Microsoft/hcsshim"
9 9
 	"github.com/Sirupsen/logrus"
10 10
 	"github.com/docker/docker/api/types"
11
-	pblkiodev "github.com/docker/docker/api/types/blkiodev"
12 11
 	containertypes "github.com/docker/docker/api/types/container"
13 12
 	"github.com/docker/docker/container"
14 13
 	"github.com/docker/docker/image"
... ...
@@ -83,31 +82,6 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
83 83
 		return nil
84 84
 	}
85 85
 
86
-	numCPU := int64(sysinfo.NumCPU())
87
-	if hostConfig.CPUCount < 0 {
88
-		logrus.Warnf("Changing requested CPUCount of %d to minimum allowed of %d", hostConfig.CPUCount, windowsMinCPUCount)
89
-		hostConfig.CPUCount = windowsMinCPUCount
90
-	} else if hostConfig.CPUCount > numCPU {
91
-		logrus.Warnf("Changing requested CPUCount of %d to current number of processors, %d", hostConfig.CPUCount, numCPU)
92
-		hostConfig.CPUCount = numCPU
93
-	}
94
-
95
-	if hostConfig.CPUShares < 0 {
96
-		logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, windowsMinCPUShares)
97
-		hostConfig.CPUShares = windowsMinCPUShares
98
-	} else if hostConfig.CPUShares > windowsMaxCPUShares {
99
-		logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, windowsMaxCPUShares)
100
-		hostConfig.CPUShares = windowsMaxCPUShares
101
-	}
102
-
103
-	if hostConfig.CPUPercent < 0 {
104
-		logrus.Warnf("Changing requested CPUPercent of %d to minimum allowed of %d", hostConfig.CPUPercent, windowsMinCPUPercent)
105
-		hostConfig.CPUPercent = windowsMinCPUPercent
106
-	} else if hostConfig.CPUPercent > windowsMaxCPUPercent {
107
-		logrus.Warnf("Changing requested CPUPercent of %d to maximum allowed of %d", hostConfig.CPUPercent, windowsMaxCPUPercent)
108
-		hostConfig.CPUPercent = windowsMaxCPUPercent
109
-	}
110
-
111 86
 	return nil
112 87
 }
113 88
 
... ...
@@ -138,48 +112,76 @@ func verifyContainerResources(resources *containertypes.Resources, isHyperv bool
138 138
 		}
139 139
 	}
140 140
 
141
-	if resources.NanoCPUs > 0 && resources.CPUPercent > 0 {
142
-		return warnings, fmt.Errorf("Conflicting options: Nano CPUs and CPU Percent cannot both be set")
141
+	if resources.CPUShares < 0 || resources.CPUShares > windowsMaxCPUShares {
142
+		return warnings, fmt.Errorf("range of CPUShares is from %d to %d", windowsMinCPUShares, windowsMaxCPUShares)
143
+	}
144
+	if resources.CPUPercent < 0 || resources.CPUPercent > windowsMaxCPUPercent {
145
+		return warnings, fmt.Errorf("range of CPUPercent is from %d to %d", windowsMinCPUPercent, windowsMaxCPUPercent)
146
+	}
147
+	if resources.CPUCount < 0 {
148
+		return warnings, fmt.Errorf("invalid CPUCount: CPUCount cannot be negative")
143 149
 	}
144 150
 
151
+	if resources.NanoCPUs > 0 && resources.CPUPercent > 0 {
152
+		return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Percent cannot both be set")
153
+	}
145 154
 	if resources.NanoCPUs > 0 && resources.CPUShares > 0 {
146
-		return warnings, fmt.Errorf("Conflicting options: Nano CPUs and CPU Shares cannot both be set")
155
+		return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Shares cannot both be set")
147 156
 	}
148 157
 	if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 {
149
-		return warnings, fmt.Errorf("Range of Nano CPUs is from 1 to %d", int64(sysinfo.NumCPU())*1e9)
158
+		return warnings, fmt.Errorf("range of Nano CPUs is from 1 to %d", int64(sysinfo.NumCPU())*1e9)
150 159
 	}
151 160
 
152
-	// TODO Windows: Add more validation of resource settings not supported on Windows
153
-
161
+	if len(resources.BlkioDeviceReadBps) > 0 {
162
+		return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceReadBps")
163
+	}
164
+	if len(resources.BlkioDeviceReadIOps) > 0 {
165
+		return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceReadIOps")
166
+	}
167
+	if len(resources.BlkioDeviceWriteBps) > 0 {
168
+		return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceWriteBps")
169
+	}
170
+	if len(resources.BlkioDeviceWriteIOps) > 0 {
171
+		return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceWriteIOps")
172
+	}
154 173
 	if resources.BlkioWeight > 0 {
155
-		warnings = append(warnings, "Windows does not support Block I/O weight. Block I/O weight discarded.")
156
-		logrus.Warn("Windows does not support Block I/O weight. Block I/O weight discarded.")
157
-		resources.BlkioWeight = 0
174
+		return warnings, fmt.Errorf("invalid option: Windows does not support BlkioWeight")
158 175
 	}
159 176
 	if len(resources.BlkioWeightDevice) > 0 {
160
-		warnings = append(warnings, "Windows does not support Block I/O weight-device. Weight-device discarded.")
161
-		logrus.Warn("Windows does not support Block I/O weight-device. Weight-device discarded.")
162
-		resources.BlkioWeightDevice = []*pblkiodev.WeightDevice{}
177
+		return warnings, fmt.Errorf("invalid option: Windows does not support BlkioWeightDevice")
163 178
 	}
164
-	if len(resources.BlkioDeviceReadBps) > 0 {
165
-		warnings = append(warnings, "Windows does not support Block read limit in bytes per second. Device read bps discarded.")
166
-		logrus.Warn("Windows does not support Block I/O read limit in bytes per second. Device read bps discarded.")
167
-		resources.BlkioDeviceReadBps = []*pblkiodev.ThrottleDevice{}
179
+	if resources.CgroupParent != "" {
180
+		return warnings, fmt.Errorf("invalid option: Windows does not support CgroupParent")
168 181
 	}
169
-	if len(resources.BlkioDeviceWriteBps) > 0 {
170
-		warnings = append(warnings, "Windows does not support Block write limit in bytes per second. Device write bps discarded.")
171
-		logrus.Warn("Windows does not support Block I/O write limit in bytes per second. Device write bps discarded.")
172
-		resources.BlkioDeviceWriteBps = []*pblkiodev.ThrottleDevice{}
182
+	if resources.CPUPeriod != 0 {
183
+		return warnings, fmt.Errorf("invalid option: Windows does not support CPUPeriod")
173 184
 	}
174
-	if len(resources.BlkioDeviceReadIOps) > 0 {
175
-		warnings = append(warnings, "Windows does not support Block read limit in IO per second. Device read iops discarded.")
176
-		logrus.Warn("Windows does not support Block I/O read limit in IO per second. Device read iops discarded.")
177
-		resources.BlkioDeviceReadIOps = []*pblkiodev.ThrottleDevice{}
185
+	if resources.CpusetCpus != "" {
186
+		return warnings, fmt.Errorf("invalid option: Windows does not support CpusetCpus")
178 187
 	}
179
-	if len(resources.BlkioDeviceWriteIOps) > 0 {
180
-		warnings = append(warnings, "Windows does not support Block write limit in IO per second. Device write iops discarded.")
181
-		logrus.Warn("Windows does not support Block I/O write limit in IO per second. Device write iops discarded.")
182
-		resources.BlkioDeviceWriteIOps = []*pblkiodev.ThrottleDevice{}
188
+	if resources.CpusetMems != "" {
189
+		return warnings, fmt.Errorf("invalid option: Windows does not support CpusetMems")
190
+	}
191
+	if resources.KernelMemory != 0 {
192
+		return warnings, fmt.Errorf("invalid option: Windows does not support KernelMemory")
193
+	}
194
+	if resources.MemoryReservation != 0 {
195
+		return warnings, fmt.Errorf("invalid option: Windows does not support MemoryReservation")
196
+	}
197
+	if resources.MemorySwap != 0 {
198
+		return warnings, fmt.Errorf("invalid option: Windows does not support MemorySwap")
199
+	}
200
+	if resources.MemorySwappiness != nil && *resources.MemorySwappiness != -1 {
201
+		return warnings, fmt.Errorf("invalid option: Windows does not support MemorySwappiness")
202
+	}
203
+	if resources.OomKillDisable != nil && *resources.OomKillDisable {
204
+		return warnings, fmt.Errorf("invalid option: Windows does not support OomKillDisable")
205
+	}
206
+	if resources.PidsLimit != 0 {
207
+		return warnings, fmt.Errorf("invalid option: Windows does not support PidsLimit")
208
+	}
209
+	if len(resources.Ulimits) != 0 {
210
+		return warnings, fmt.Errorf("invalid option: Windows does not support Ulimits")
183 211
 	}
184 212
 	return warnings, nil
185 213
 }
... ...
@@ -14,6 +14,7 @@ import (
14 14
 
15 15
 	"github.com/Microsoft/hcsshim"
16 16
 	"github.com/Sirupsen/logrus"
17
+	"github.com/docker/docker/pkg/sysinfo"
17 18
 	"github.com/opencontainers/runtime-spec/specs-go"
18 19
 )
19 20
 
... ...
@@ -111,7 +112,16 @@ func (clnt *client) Create(containerID string, checkpoint string, checkpointDir
111 111
 	if spec.Windows.Resources != nil {
112 112
 		if spec.Windows.Resources.CPU != nil {
113 113
 			if spec.Windows.Resources.CPU.Count != nil {
114
-				configuration.ProcessorCount = uint32(*spec.Windows.Resources.CPU.Count)
114
+				// This check is being done here rather than in adaptContainerSettings
115
+				// because we don't want to update the HostConfig in case this container
116
+				// is moved to a host with more CPUs than this one.
117
+				cpuCount := *spec.Windows.Resources.CPU.Count
118
+				hostCPUCount := uint64(sysinfo.NumCPU())
119
+				if cpuCount > hostCPUCount {
120
+					logrus.Warnf("Changing requested CPUCount of %d to current number of processors, %d", cpuCount, hostCPUCount)
121
+					cpuCount = hostCPUCount
122
+				}
123
+				configuration.ProcessorCount = uint32(cpuCount)
115 124
 			}
116 125
 			if spec.Windows.Resources.CPU.Shares != nil {
117 126
 				configuration.ProcessorWeight = uint64(*spec.Windows.Resources.CPU.Shares)