Browse code

Add hostConfig check before starting a container

It may happen that host system settings are changed while the daemon is running.
This will cause errors at libcontainer level when starting a container with a
particular hostConfig (e.g. hostConfig with memory swappiness but the memory
cgroup was umounted).
This patch adds an hostConfig check on container start to prevent the daemon
from even calling libcontainer with the wrong configuration as we're already
doing on container's creation).

Signed-off-by: Antonio Murdaca <runcom@linux.com>
(cherry picked from commit 0d2628cdf19783106ae8723f51fae0a7c7f361c6)

Antonio Murdaca authored on 2015/08/06 20:55:56
Showing 3 changed files
... ...
@@ -155,6 +155,8 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
155 155
 	if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
156 156
 		return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
157 157
 	}
158
+
159
+	// memory subsystem checks and adjustments
158 160
 	if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
159 161
 		return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
160 162
 	}
... ...
@@ -162,6 +164,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
162 162
 		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
163 163
 		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
164 164
 		hostConfig.Memory = 0
165
+		hostConfig.MemorySwap = -1
165 166
 	}
166 167
 	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit {
167 168
 		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
... ...
@@ -174,7 +177,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
174 174
 	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
175 175
 		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
176 176
 	}
177
-	if hostConfig.MemorySwappiness != nil && !sysInfo.MemorySwappiness {
177
+	if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
178 178
 		warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
179 179
 		logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
180 180
 		hostConfig.MemorySwappiness = nil
... ...
@@ -214,10 +217,12 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
214 214
 	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
215 215
 		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
216 216
 	}
217
+
217 218
 	if hostConfig.OomKillDisable && !sysInfo.OomKillDisable {
218 219
 		hostConfig.OomKillDisable = false
219 220
 		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
220 221
 	}
222
+
221 223
 	if sysInfo.IPv4ForwardingDisabled {
222 224
 		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
223 225
 		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
... ...
@@ -21,10 +21,6 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf
21 21
 		return fmt.Errorf("Container already started")
22 22
 	}
23 23
 
24
-	if _, err = daemon.verifyContainerSettings(hostConfig, nil); err != nil {
25
-		return err
26
-	}
27
-
28 24
 	// Windows does not have the backwards compatibilty issue here.
29 25
 	if runtime.GOOS != "windows" {
30 26
 		// This is kept for backward compatibility - hostconfig should be passed when
... ...
@@ -40,6 +36,12 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf
40 40
 		}
41 41
 	}
42 42
 
43
+	// check if hostConfig is in line with the current system settings.
44
+	// It may happen cgroups are umounted or the like.
45
+	if _, err = daemon.verifyContainerSettings(container.hostConfig, nil); err != nil {
46
+		return err
47
+	}
48
+
43 49
 	if err := container.Start(); err != nil {
44 50
 		return fmt.Errorf("Cannot start container %s: %s", name, err)
45 51
 	}
... ...
@@ -188,16 +188,16 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
188 188
 		flMemory = parsedMemory
189 189
 	}
190 190
 
191
-	var MemorySwap int64
191
+	var memorySwap int64
192 192
 	if *flMemorySwap != "" {
193 193
 		if *flMemorySwap == "-1" {
194
-			MemorySwap = -1
194
+			memorySwap = -1
195 195
 		} else {
196 196
 			parsedMemorySwap, err := units.RAMInBytes(*flMemorySwap)
197 197
 			if err != nil {
198 198
 				return nil, nil, cmd, err
199 199
 			}
200
-			MemorySwap = parsedMemorySwap
200
+			memorySwap = parsedMemorySwap
201 201
 		}
202 202
 	}
203 203
 
... ...
@@ -354,7 +354,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
354 354
 		ContainerIDFile:  *flContainerIDFile,
355 355
 		LxcConf:          lxcConf,
356 356
 		Memory:           flMemory,
357
-		MemorySwap:       MemorySwap,
357
+		MemorySwap:       memorySwap,
358 358
 		CPUShares:        *flCPUShares,
359 359
 		CPUPeriod:        *flCPUPeriod,
360 360
 		CpusetCpus:       *flCpusetCpus,