mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #20655 from hqhq/hq_fix_update_memoryswap
Fix problems when update swap memory
This commit is contained in:
commit
6748cc10ac
7 changed files with 64 additions and 10 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue