1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/integration-cli/docker_cli_daemon_experimental_test.go
Michael Crosby d705dab1b1 Add --live-restore flag
This flags enables full support of daemonless containers in docker.  It
ensures that docker does not stop containers on shutdown or restore and
properly reconnects to the container when restarted.

This is not the default because of backwards compat but should be the
desired outcome for people running containers in prod.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2016-06-13 19:16:26 -07:00

195 lines
6.2 KiB
Go

// +build daemon,!windows,experimental
package main
import (
"io/ioutil"
"os"
"os/exec"
"strings"
"time"
"github.com/go-check/check"
)
// TestDaemonRestartWithKilledRunningContainer requires live restore of running containers
func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *check.C) {
// TODO(mlaventure): Not sure what would the exit code be on windows
testRequires(t, DaemonIsLinux)
if err := s.d.StartWithBusybox(); err != nil {
t.Fatal(err)
}
cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top")
defer s.d.Stop()
if err != nil {
t.Fatal(cid, err)
}
cid = strings.TrimSpace(cid)
// Kill the daemon
if err := s.d.Kill(); err != nil {
t.Fatal(err)
}
// kill the container
runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", cid)
if out, ec, err := runCommandWithOutput(runCmd); err != nil {
t.Fatalf("Failed to run ctr, ExitCode: %d, err: '%v' output: '%s' cid: '%s'\n", ec, err, out, cid)
}
// Give time to containerd to process the command if we don't
// the exit event might be received after we do the inspect
time.Sleep(3 * time.Second)
// restart the daemon
if err := s.d.Start(); err != nil {
t.Fatal(err)
}
// Check that we've got the correct exit code
out, err := s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", cid)
t.Assert(err, check.IsNil)
out = strings.TrimSpace(out)
if out != "143" {
t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "143", out, cid)
}
}
// os.Kill should kill daemon ungracefully, leaving behind live containers.
// The live containers should be known to the restarted daemon. Stopping
// them now, should remove the mounts.
func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) {
testRequires(c, DaemonIsLinux)
c.Assert(s.d.StartWithBusybox("--live-restore"), check.IsNil)
out, err := s.d.Cmd("run", "-d", "busybox", "top")
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
id := strings.TrimSpace(out)
c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil)
mountOut, err := ioutil.ReadFile("/proc/self/mountinfo")
c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut))
// container mounts should exist even after daemon has crashed.
comment := check.Commentf("%s should stay mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut)
c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment)
// restart daemon.
if err := s.d.Restart("--live-restore"); err != nil {
c.Fatal(err)
}
// container should be running.
out, err = s.d.Cmd("inspect", "--format='{{.State.Running}}'", id)
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
out = strings.TrimSpace(out)
if out != "true" {
c.Fatalf("Container %s expected to stay alive after daemon restart", id)
}
// 'docker stop' should work.
out, err = s.d.Cmd("stop", id)
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
// Now, container mounts should be gone.
mountOut, err = ioutil.ReadFile("/proc/self/mountinfo")
c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut))
comment = check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut)
c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment)
}
// TestDaemonRestartWithPausedRunningContainer requires live restore of running containers
func (s *DockerDaemonSuite) TestDaemonRestartWithPausedRunningContainer(t *check.C) {
if err := s.d.StartWithBusybox("--live-restore"); err != nil {
t.Fatal(err)
}
cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top")
defer s.d.Stop()
if err != nil {
t.Fatal(cid, err)
}
cid = strings.TrimSpace(cid)
// Kill the daemon
if err := s.d.Kill(); err != nil {
t.Fatal(err)
}
// kill the container
runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "pause", cid)
if out, ec, err := runCommandWithOutput(runCmd); err != nil {
t.Fatalf("Failed to run ctr, ExitCode: %d, err: '%v' output: '%s' cid: '%s'\n", ec, err, out, cid)
}
// Give time to containerd to process the command if we don't
// the pause event might be received after we do the inspect
time.Sleep(3 * time.Second)
// restart the daemon
if err := s.d.Start("--live-restore"); err != nil {
t.Fatal(err)
}
// Check that we've got the correct status
out, err := s.d.Cmd("inspect", "-f", "{{.State.Status}}", cid)
t.Assert(err, check.IsNil)
out = strings.TrimSpace(out)
if out != "paused" {
t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "paused", out, cid)
}
}
// TestDaemonRestartWithUnpausedRunningContainer requires live restore of running containers.
func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *check.C) {
// TODO(mlaventure): Not sure what would the exit code be on windows
testRequires(t, DaemonIsLinux)
if err := s.d.StartWithBusybox("--live-restore"); err != nil {
t.Fatal(err)
}
cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top")
defer s.d.Stop()
if err != nil {
t.Fatal(cid, err)
}
cid = strings.TrimSpace(cid)
// pause the container
if _, err := s.d.Cmd("pause", cid); err != nil {
t.Fatal(cid, err)
}
// Kill the daemon
if err := s.d.Kill(); err != nil {
t.Fatal(err)
}
// resume the container
runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "resume", cid)
if out, ec, err := runCommandWithOutput(runCmd); err != nil {
t.Fatalf("Failed to run ctr, ExitCode: %d, err: '%v' output: '%s' cid: '%s'\n", ec, err, out, cid)
}
// Give time to containerd to process the command if we don't
// the resume event might be received after we do the inspect
time.Sleep(3 * time.Second)
// restart the daemon
if err := s.d.Start("--live-restore"); err != nil {
t.Fatal(err)
}
// Check that we've got the correct status
out, err := s.d.Cmd("inspect", "-f", "{{.State.Status}}", cid)
t.Assert(err, check.IsNil)
out = strings.TrimSpace(out)
if out != "running" {
t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "running", out, cid)
}
}