Merge pull request #20655 from hqhq/hq_fix_update_memoryswap

Fix problems when update swap memory
This commit is contained in:
Brian Goff 2016-02-25 22:28:53 -05:00
commit 6748cc10ac
7 changed files with 64 additions and 10 deletions

View file

@ -21,7 +21,7 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types
return types.ContainerCreateResponse{}, derr.ErrorCodeEmptyConfig
}
warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config)
warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false)
if err != nil {
return types.ContainerCreateResponse{Warnings: warnings}, err
}

View file

@ -1450,7 +1450,7 @@ func setDefaultMtu(config *Config) {
// verifyContainerSettings performs validation of the hostconfig and config
// structures.
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) {
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
// First perform verification of settings common across all platforms.
if config != nil {
@ -1487,7 +1487,7 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
}
// Now do platform-specific verification
return verifyPlatformContainerSettings(daemon, hostConfig, config)
return verifyPlatformContainerSettings(daemon, hostConfig, config, update)
}
// Checks if the client set configurations for more than one network while creating a container

View file

@ -221,7 +221,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
return nil
}
func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo) ([]string, error) {
func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) {
warnings := []string{}
// memory subsystem checks and adjustments
@ -242,7 +242,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
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.")
}
if resources.Memory == 0 && resources.MemorySwap > 0 {
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.")
}
if resources.MemorySwappiness != nil && *resources.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
@ -383,7 +383,7 @@ func (daemon *Daemon) usingSystemd() bool {
// verifyPlatformContainerSettings performs platform-specific validation of the
// hostconfig and config structures.
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) {
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
warnings := []string{}
sysInfo := sysinfo.New(true)
@ -392,7 +392,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
return warnings, err
}
w, err := verifyContainerResources(&hostConfig.Resources, sysInfo)
w, err := verifyContainerResources(&hostConfig.Resources, sysInfo, update)
if err != nil {
return warnings, err
}

View file

@ -85,7 +85,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
// verifyPlatformContainerSettings performs platform-specific validation of the
// hostconfig and config structures.
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) {
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
return nil, nil
}

View file

@ -58,7 +58,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
// check if hostConfig is in line with the current system settings.
// It may happen cgroups are umounted or the like.
if _, err = daemon.verifyContainerSettings(container.HostConfig, nil); err != nil {
if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false); err != nil {
return err
}
// Adapt for old containers in case we have updates in this function and

View file

@ -12,7 +12,7 @@ import (
func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) {
var warnings []string
warnings, err := daemon.verifyContainerSettings(hostConfig, nil)
warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true)
if err != nil {
return warnings, err
}
@ -45,6 +45,17 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
return err
}
restoreConfig := false
backupHostConfig := *container.HostConfig
defer func() {
if restoreConfig {
container.Lock()
container.HostConfig = &backupHostConfig
container.ToDisk()
container.Unlock()
}
}()
if container.RemovalInProgress || container.Dead {
errMsg := fmt.Errorf("Container is marked for removal and cannot be \"update\".")
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, errMsg)
@ -56,6 +67,7 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
}
if err := container.UpdateContainer(hostConfig); err != nil {
restoreConfig = true
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
}
@ -73,6 +85,7 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
// to the real world.
if container.IsRunning() && !container.IsRestarting() {
if err := daemon.execDriver.Update(container.Command); err != nil {
restoreConfig = true
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
}
}

View file

@ -139,6 +139,47 @@ func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) {
c.Assert(strings.TrimSpace(out), checker.Equals, "104857600")
}
func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) {
testRequires(c, DaemonIsLinux)
testRequires(c, memoryLimitSupport)
testRequires(c, swapMemorySupport)
name := "test-update-container"
dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top")
dockerCmd(c, "update", "--memory-swap", "600M", name)
c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600")
file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"
out, _ := dockerCmd(c, "exec", name, "cat", file)
c.Assert(strings.TrimSpace(out), checker.Equals, "629145600")
}
func (s *DockerSuite) TestUpdateInvalidSwapMemory(c *check.C) {
testRequires(c, DaemonIsLinux)
testRequires(c, memoryLimitSupport)
testRequires(c, swapMemorySupport)
name := "test-update-container"
dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top")
_, _, err := dockerCmdWithError("update", "--memory-swap", "200M", name)
// Update invalid swap memory should fail.
// This will pass docker config validation, but failed at kernel validation
c.Assert(err, check.NotNil)
// Update invalid swap memory with failure should not change HostConfig
c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "314572800")
c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "524288000")
dockerCmd(c, "update", "--memory-swap", "600M", name)
c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600")
file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"
out, _ := dockerCmd(c, "exec", name, "cat", file)
c.Assert(strings.TrimSpace(out), checker.Equals, "629145600")
}
func (s *DockerSuite) TestUpdateStats(c *check.C) {
testRequires(c, DaemonIsLinux)
testRequires(c, memoryLimitSupport)