Merge pull request #10468 from noironetworks/10457-Pause-and-unpause-accept-multi-containers

Allow docker pause and unpause to accept multiple containers
This commit is contained in:
Jessie Frazelle 2015-02-19 15:16:05 -08:00
commit 934535db9c
7 changed files with 131 additions and 59 deletions

View file

@ -786,8 +786,8 @@ func (cli *DockerCli) CmdStart(args ...string) error {
}
func (cli *DockerCli) CmdUnpause(args ...string) error {
cmd := cli.Subcmd("unpause", "CONTAINER", "Unpause all processes within a container", true)
cmd.Require(flag.Exact, 1)
cmd := cli.Subcmd("unpause", "CONTAINER [CONTAINER...]", "Unpause all processes within a container", true)
cmd.Require(flag.Min, 1)
utils.ParseFlags(cmd, args, false)
var encounteredError error
@ -803,8 +803,8 @@ func (cli *DockerCli) CmdUnpause(args ...string) error {
}
func (cli *DockerCli) CmdPause(args ...string) error {
cmd := cli.Subcmd("pause", "CONTAINER", "Pause all processes within a container", true)
cmd.Require(flag.Exact, 1)
cmd := cli.Subcmd("pause", "CONTAINER [CONTAINER...]", "Pause all processes within a container", true)
cmd.Require(flag.Min, 1)
utils.ParseFlags(cmd, args, false)
var encounteredError error

View file

@ -6,7 +6,7 @@ docker-pause - Pause all processes within a container
# SYNOPSIS
**docker pause**
CONTAINER
CONTAINER [CONTAINER...]
# DESCRIPTION

View file

@ -6,7 +6,7 @@ docker-unpause - Unpause all processes within a container
# SYNOPSIS
**docker unpause**
CONTAINER
CONTAINER [CONTAINER...]
# DESCRIPTION

View file

@ -1360,7 +1360,7 @@ nano-second part of the timestamp will be padded with zero when necessary.
## pause
Usage: docker pause CONTAINER
Usage: docker pause CONTAINER [CONTAINER...]
Pause all processes within a container
@ -1397,22 +1397,6 @@ just a specific mapping:
$ sudo docker port test 7890
0.0.0.0:4321
## pause
Usage: docker pause CONTAINER
Pause all processes within a container
The `docker pause` command uses the cgroups freezer to suspend all processes in
a container. Traditionally when suspending a process the `SIGSTOP` signal is
used, which is observable by the process being suspended. With the cgroups freezer
the process is unaware, and unable to capture, that it is being suspended,
and subsequently resumed.
See the
[cgroups freezer documentation](https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt)
for further details.
## rename
Usage: docker rename OLD_NAME NEW_NAME
@ -2074,7 +2058,7 @@ them to [*Share Images via Repositories*](
## unpause
Usage: docker unpause CONTAINER
Usage: docker unpause CONTAINER [CONTAINER...]
Unpause all processes within a container

View file

@ -30,41 +30,6 @@ func TestEventsUntag(t *testing.T) {
logDone("events - untags are logged")
}
func TestEventsPause(t *testing.T) {
name := "testeventpause"
out, _, _ := dockerCmd(t, "images", "-q")
image := strings.Split(out, "\n")[0]
dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
dockerCmd(t, "pause", name)
dockerCmd(t, "unpause", name)
defer deleteAllContainers()
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
}
pauseEvent := strings.Fields(events[len(events)-3])
unpauseEvent := strings.Fields(events[len(events)-2])
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
}
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
waitCmd := exec.Command(dockerBinary, "wait", name)
if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
}
logDone("events - pause/unpause is logged")
}
func TestEventsContainerFailStartDie(t *testing.T) {
defer deleteAllContainers()

View file

@ -0,0 +1,113 @@
package main
import (
"fmt"
"os/exec"
"strings"
"testing"
"time"
)
func TestPause(t *testing.T) {
defer deleteAllContainers()
defer unpauseAllContainers()
name := "testeventpause"
out, _, _ := dockerCmd(t, "images", "-q")
image := strings.Split(out, "\n")[0]
dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
dockerCmd(t, "pause", name)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != 1 {
t.Fatalf("there should be one paused container and not", len(pausedContainers))
}
dockerCmd(t, "unpause", name)
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
}
pauseEvent := strings.Fields(events[len(events)-3])
unpauseEvent := strings.Fields(events[len(events)-2])
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
}
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
waitCmd := exec.Command(dockerBinary, "wait", name)
if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
}
logDone("pause - pause/unpause is logged")
}
func TestPauseMultipleContainers(t *testing.T) {
defer deleteAllContainers()
defer unpauseAllContainers()
containers := []string{
"testpausewithmorecontainers1",
"testpausewithmorecontainers2",
}
out, _, _ := dockerCmd(t, "images", "-q")
image := strings.Split(out, "\n")[0]
for _, name := range containers {
dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
}
dockerCmd(t, append([]string{"pause"}, containers...)...)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != len(containers) {
t.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
}
dockerCmd(t, append([]string{"unpause"}, containers...)...)
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= len(containers)*3-2 {
t.Fatalf("Missing expected event")
}
pauseEvents := make([][]string, len(containers))
unpauseEvents := make([][]string, len(containers))
for i := range containers {
pauseEvents[i] = strings.Fields(events[len(events)-len(containers)*2-1+i])
unpauseEvents[i] = strings.Fields(events[len(events)-len(containers)-1+i])
}
for _, pauseEvent := range pauseEvents {
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
}
}
for _, unpauseEvent := range unpauseEvents {
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
}
for _, name := range containers {
waitCmd := exec.Command(dockerBinary, "wait", name)
if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
}
}
logDone("pause - multi pause/unpause is logged")
}

View file

@ -386,6 +386,16 @@ func getPausedContainers() (string, error) {
return out, err
}
func getSliceOfPausedContainers() ([]string, error) {
out, err := getPausedContainers()
if err == nil {
slice := strings.Split(strings.TrimSpace(out), "\n")
return slice, err
} else {
return []string{out}, err
}
}
func unpauseContainer(container string) error {
unpauseCmd := exec.Command(dockerBinary, "unpause", container)
exitCode, err := runCommand(unpauseCmd)