Update RestartPolicy of container

Add `--restart` flag for `update` command, so we can change restart
policy for a container no matter it's running or stopped.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
This commit is contained in:
Zhang Wei 2016-01-04 23:58:20 +08:00
parent 6668326aa8
commit ff3ea4c90f
17 changed files with 154 additions and 33 deletions

View File

@ -6,6 +6,7 @@ import (
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/runconfig/opts"
"github.com/docker/engine-api/types/container"
"github.com/docker/go-units"
)
@ -25,6 +26,7 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
flMemoryReservation := cmd.String([]string{"-memory-reservation"}, "", "Memory soft limit")
flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap")
flKernelMemory := cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
flRestartPolicy := cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits")
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, true)
@ -69,6 +71,14 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
}
}
var restartPolicy container.RestartPolicy
if *flRestartPolicy != "" {
restartPolicy, err = opts.ParseRestartPolicy(*flRestartPolicy)
if err != nil {
return err
}
}
resources := container.Resources{
BlkioWeight: *flBlkioWeight,
CpusetCpus: *flCpusetCpus,
@ -84,6 +94,7 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
updateConfig := container.UpdateConfig{
Resources: resources,
RestartPolicy: restartPolicy,
}
names := cmd.Args()

View File

@ -323,6 +323,7 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
hostConfig := &container.HostConfig{
Resources: updateConfig.Resources,
RestartPolicy: updateConfig.RestartPolicy,
}
name := vars["name"]

View File

@ -64,7 +64,7 @@ var dockerCommands = []Command{
{"tag", "Tag an image into a repository"},
{"top", "Display the running processes of a container"},
{"unpause", "Unpause all processes within a container"},
{"update", "Update resources of one or more containers"},
{"update", "Update configuration of one or more containers"},
{"version", "Show the Docker version information"},
{"volume", "Manage Docker volumes"},
{"wait", "Block until a container stops, then print its exit code"},

View File

@ -594,3 +594,20 @@ func (container *Container) InitDNSHostConfig() {
container.HostConfig.DNSOptions = make([]string, 0)
}
}
// UpdateMonitor updates monitor configure for running container
func (container *Container) UpdateMonitor(restartPolicy containertypes.RestartPolicy) {
monitor := container.monitor
// No need to update monitor if container hasn't got one
// monitor will be generated correctly according to container
if monitor == nil {
return
}
monitor.mux.Lock()
// to check whether restart policy has changed.
if restartPolicy.Name != "" && !monitor.restartPolicy.IsSame(&restartPolicy) {
monitor.restartPolicy = restartPolicy
}
monitor.mux.Unlock()
}

View File

@ -564,10 +564,11 @@ func updateCommand(c *execdriver.Command, resources containertypes.Resources) {
c.Resources.KernelMemory = resources.KernelMemory
}
// UpdateContainer updates resources of a container.
// UpdateContainer updates configuration of a container.
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
container.Lock()
// update resources of container
resources := hostConfig.Resources
cResources := &container.HostConfig.Resources
if resources.BlkioWeight != 0 {
@ -600,6 +601,11 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
if resources.KernelMemory != 0 {
cResources.KernelMemory = resources.KernelMemory
}
// update HostConfig of container
if hostConfig.RestartPolicy.Name != "" {
container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
}
container.Unlock()
// If container is not running, update hostConfig struct is enough,

View File

@ -3,6 +3,7 @@
package container
import (
"fmt"
"os"
"path/filepath"
@ -45,8 +46,22 @@ func (container *Container) TmpfsMounts() []execdriver.Mount {
return nil
}
// UpdateContainer updates resources of a container
// UpdateContainer updates configuration of a container
func (container *Container) UpdateContainer(hostConfig *container.HostConfig) error {
container.Lock()
defer container.Unlock()
resources := hostConfig.Resources
if resources.BlkioWeight != 0 || resources.CPUShares != 0 ||
resources.CPUPeriod != 0 || resources.CPUQuota != 0 ||
resources.CpusetCpus != "" || resources.CpusetMems != "" ||
resources.Memory != 0 || resources.MemorySwap != 0 ||
resources.MemoryReservation != 0 || resources.KernelMemory != 0 {
return fmt.Errorf("Resource updating isn't supported on Windows")
}
// update HostConfig of container
if hostConfig.RestartPolicy.Name != "" {
container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
}
return nil
}

View File

@ -79,11 +79,11 @@ type containerMonitor struct {
// StartMonitor initializes a containerMonitor for this container with the provided supervisor and restart policy
// and starts the container's process.
func (container *Container) StartMonitor(s supervisor, policy container.RestartPolicy) error {
func (container *Container) StartMonitor(s supervisor) error {
container.monitor = &containerMonitor{
supervisor: s,
container: container,
restartPolicy: policy,
restartPolicy: container.HostConfig.RestartPolicy,
timeIncrement: defaultTimeIncrement,
stopChan: make(chan struct{}),
startSignal: make(chan struct{}),

View File

@ -119,11 +119,11 @@ func wait(waitChan <-chan struct{}, timeout time.Duration) error {
}
}
// waitRunning waits until state is running. If state is already
// WaitRunning waits until state is running. If state is already
// running it returns immediately. If you want wait forever you must
// supply negative timeout. Returns pid, that was passed to
// SetRunning.
func (s *State) waitRunning(timeout time.Duration) (int, error) {
func (s *State) WaitRunning(timeout time.Duration) (int, error) {
s.Lock()
if s.Running {
pid := s.Pid

View File

@ -14,7 +14,7 @@ func TestStateRunStop(t *testing.T) {
started := make(chan struct{})
var pid int64
go func() {
runPid, _ := s.waitRunning(-1 * time.Second)
runPid, _ := s.WaitRunning(-1 * time.Second)
atomic.StoreInt64(&pid, int64(runPid))
close(started)
}()
@ -41,8 +41,8 @@ func TestStateRunStop(t *testing.T) {
if runPid != i+100 {
t.Fatalf("Pid %v, expected %v", runPid, i+100)
}
if pid, err := s.waitRunning(-1 * time.Second); err != nil || pid != i+100 {
t.Fatalf("waitRunning returned pid: %v, err: %v, expected pid: %v, err: %v", pid, err, i+100, nil)
if pid, err := s.WaitRunning(-1 * time.Second); err != nil || pid != i+100 {
t.Fatalf("WaitRunning returned pid: %v, err: %v, expected pid: %v, err: %v", pid, err, i+100, nil)
}
stopped := make(chan struct{})
@ -82,7 +82,7 @@ func TestStateTimeoutWait(t *testing.T) {
s := NewState()
started := make(chan struct{})
go func() {
s.waitRunning(100 * time.Millisecond)
s.WaitRunning(100 * time.Millisecond)
close(started)
}()
select {
@ -98,7 +98,7 @@ func TestStateTimeoutWait(t *testing.T) {
stopped := make(chan struct{})
go func() {
s.waitRunning(100 * time.Millisecond)
s.WaitRunning(100 * time.Millisecond)
close(stopped)
}()
select {

View File

@ -3,12 +3,12 @@
package windows
import (
"fmt"
"github.com/docker/docker/daemon/execdriver"
)
// Update updates resource configs for a container.
func (d *Driver) Update(c *execdriver.Command) error {
return fmt.Errorf("Windows: Update not implemented")
// Updating resource isn't supported on Windows
// but we should return nil for enabling updating container
return nil
}

View File

@ -154,7 +154,7 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
}
func (daemon *Daemon) waitForStart(container *container.Container) error {
return container.StartMonitor(daemon, container.HostConfig.RestartPolicy)
return container.StartMonitor(daemon)
}
// Cleanup releases any network resources allocated to the container along with any rules

View File

@ -2,12 +2,13 @@ package daemon
import (
"fmt"
"time"
derr "github.com/docker/docker/errors"
"github.com/docker/engine-api/types/container"
)
// ContainerUpdate updates resources of the container
// ContainerUpdate updates configuration of the container
func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) {
var warnings []string
@ -58,11 +59,19 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
}
// if Restart Policy changed, we need to update container monitor
container.UpdateMonitor(hostConfig.RestartPolicy)
// if container is restarting, wait 5 seconds until it's running
if container.IsRestarting() {
container.WaitRunning(5 * time.Second)
}
// If container is not running, update hostConfig struct is enough,
// resources will be updated when the container is started again.
// If container is running (including paused), we need to update configs
// to the real world.
if container.IsRunning() {
if container.IsRunning() && !container.IsRestarting() {
if err := daemon.execDriver.Update(container.Command); err != nil {
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
}

View File

@ -117,7 +117,7 @@ This section lists each version from latest to oldest. Each listing includes a
* `GET /containers/json` returns the state of the container, one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`.
* `GET /networks/(name)` now returns an `Internal` field showing whether the network is internal or not.
* `POST /containers/(name)/update` now supports updating container's restart policy.
### v1.22 API changes

View File

@ -1031,7 +1031,7 @@ Status Codes:
`POST /containers/(id)/update`
Update resource configs of one or more containers.
Update configuration of one or more containers.
**Example request**:
@ -1049,6 +1049,10 @@ Update resource configs of one or more containers.
"MemorySwap": 514288000,
"MemoryReservation": 209715200,
"KernelMemory": 52428800,
"RestartPolicy": {
"MaximumRetryCount": 4,
"Name": "on-failure"
},
}
**Example response**:

View File

@ -12,7 +12,7 @@ parent = "smn_cli"
Usage: docker update [OPTIONS] CONTAINER [CONTAINER...]
Updates container resource limits
Update configuration of one or more containers
--help=false Print usage
--blkio-weight=0 Block IO (relative weight), between 10 and 1000
@ -25,11 +25,12 @@ parent = "smn_cli"
--memory-reservation="" Memory soft limit
--memory-swap="" A positive integer equal to memory plus swap. Specify -1 to enable unlimited swap
--kernel-memory="" Kernel memory limit: container must be stopped
--restart Restart policy to apply when a container exits
The `docker update` command dynamically updates container resources. Use this
command to prevent containers from consuming too many resources from their
Docker host. With a single command, you can place limits on a single
container or on many. To specify more than one container, provide
The `docker update` command dynamically updates container configuration.
You can use this command to prevent containers from consuming too many resources
from their Docker host. With a single command, you can place limits on
a single container or on many. To specify more than one container, provide
space-separated list of container names or IDs.
With the exception of the `--kernel-memory` value, you can specify these
@ -38,6 +39,10 @@ options on a running or a stopped container. You can only update
stopped container, the next time you restart it, the container uses those
values.
Another configuration you can change with this command is restart policy,
new restart policy will take effect instantly after you run `docker update`
on a container.
## EXAMPLES
The following sections illustrate ways to use this command.
@ -59,3 +64,10 @@ To update multiple resource configurations for multiple containers:
```bash
$ docker update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
```
### Update a container's restart policy
To update restart policy for one or more containers:
```bash
$ docker update --restart=on-failure:3 abebf7571666 hopeful_morse
```

View File

@ -0,0 +1,31 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestUpdateRestartPolicy(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "sh", "-c", "sleep 1 && false")
timeout := 60 * time.Second
if daemonPlatform == "windows" {
timeout = 100 * time.Second
}
id := strings.TrimSpace(string(out))
// update restart policy to on-failure:5
dockerCmd(c, "update", "--restart=on-failure:5", id)
err := waitExited(id, timeout)
c.Assert(err, checker.IsNil)
count := inspectField(c, id, "RestartCount")
c.Assert(count, checker.Equals, "5")
maximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount")
c.Assert(maximumRetryCount, checker.Equals, "5")
}

View File

@ -2,7 +2,7 @@
% Docker Community
% JUNE 2014
# NAME
docker-update - Update resource configs of one or more containers
docker-update - Update configuration of one or more containers
# SYNOPSIS
**docker update**
@ -17,15 +17,16 @@ docker-update - Update resource configs of one or more containers
[**-m**|**--memory**[=*MEMORY*]]
[**--memory-reservation**[=*MEMORY-RESERVATION*]]
[**--memory-swap**[=*MEMORY-SWAP*]]
[**--restart**[=*""*]]
CONTAINER [CONTAINER...]
# DESCRIPTION
The `docker update` command dynamically updates container resources. Use this
command to prevent containers from consuming too many resources from their
Docker host. With a single command, you can place limits on a single
container or on many. To specify more than one container, provide
space-separated list of container names or IDs.
The `docker update` command dynamically updates container configuration.
you can Use this command to prevent containers from consuming too many
resources from their Docker host. With a single command, you can place
limits on a single container or on many. To specify more than one container,
provide space-separated list of container names or IDs.
With the exception of the `--kernel-memory` value, you can specify these
options on a running or a stopped container. You can only update
@ -33,6 +34,10 @@ options on a running or a stopped container. You can only update
stopped container, the next time you restart it, the container uses those
values.
Another configuration you can change with this command is restart policy,
new restart policy will take effect instantly after you run `docker update`
on a container.
# OPTIONS
**--blkio-weight**=0
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
@ -70,6 +75,9 @@ be updated to a stopped container, and affect after it's started.
**--memory-swap**=""
Total memory limit (memory + swap)
**--restart**=""
Restart policy to apply when a container exits (no, on-failure[:max-retry], always, unless-stopped).
# EXAMPLES
The following sections illustrate ways to use this command.
@ -91,3 +99,10 @@ To update multiple resource configurations for multiple containers:
```bash
$ docker update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
```
### Update a container's restart policy
To update restart policy for one or more containers:
```bash
$ docker update --restart=on-failure:3 abebf7571666 hopeful_morse
```