github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/integration/container/checkpoint_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "context" 5 "fmt" 6 "os/exec" 7 "regexp" 8 "sort" 9 "testing" 10 "time" 11 12 "github.com/docker/docker/api/types" 13 mounttypes "github.com/docker/docker/api/types/mount" 14 "github.com/docker/docker/client" 15 "github.com/docker/docker/integration/internal/container" 16 "github.com/docker/docker/internal/test/request" 17 "gotest.tools/assert" 18 is "gotest.tools/assert/cmp" 19 "gotest.tools/poll" 20 "gotest.tools/skip" 21 ) 22 23 func containerExec(t *testing.T, client client.APIClient, cID string, cmd []string) { 24 t.Logf("Exec: %s", cmd) 25 ctx := context.Background() 26 r, err := container.Exec(ctx, client, cID, cmd) 27 assert.NilError(t, err) 28 t.Log(r.Combined()) 29 assert.Equal(t, r.ExitCode, 0) 30 } 31 32 func TestCheckpoint(t *testing.T) { 33 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 34 skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild) 35 36 defer setupTest(t)() 37 38 cmd := exec.Command("criu", "check") 39 stdoutStderr, err := cmd.CombinedOutput() 40 t.Logf("%s", stdoutStderr) 41 assert.NilError(t, err) 42 43 ctx := context.Background() 44 client := request.NewAPIClient(t) 45 46 mnt := mounttypes.Mount{ 47 Type: mounttypes.TypeTmpfs, 48 Target: "/tmp", 49 } 50 51 t.Log("Start a container") 52 cID := container.Run(t, ctx, client, container.WithMount(mnt)) 53 poll.WaitOn(t, 54 container.IsInState(ctx, client, cID, "running"), 55 poll.WithDelay(100*time.Millisecond), 56 ) 57 58 cptOpt := types.CheckpointCreateOptions{ 59 Exit: false, 60 CheckpointID: "test", 61 } 62 63 { 64 // FIXME: ipv6 iptables modules are not uploaded in the test environment 65 cmd := exec.Command("bash", "-c", "set -x; "+ 66 "mount --bind $(type -P true) $(type -P ip6tables-restore) && "+ 67 "mount --bind $(type -P true) $(type -P ip6tables-save)") 68 stdoutStderr, err = cmd.CombinedOutput() 69 t.Logf("%s", stdoutStderr) 70 assert.NilError(t, err) 71 72 defer func() { 73 cmd := exec.Command("bash", "-c", "set -x; "+ 74 "umount -c -i -l $(type -P ip6tables-restore); "+ 75 "umount -c -i -l $(type -P ip6tables-save)") 76 stdoutStderr, err = cmd.CombinedOutput() 77 t.Logf("%s", stdoutStderr) 78 assert.NilError(t, err) 79 }() 80 } 81 t.Log("Do a checkpoint and leave the container running") 82 err = client.CheckpointCreate(ctx, cID, cptOpt) 83 if err != nil { 84 // An error can contain a path to a dump file 85 t.Logf("%s", err) 86 re := regexp.MustCompile("path= (.*): ") 87 m := re.FindStringSubmatch(fmt.Sprintf("%s", err)) 88 if len(m) >= 2 { 89 dumpLog := m[1] 90 t.Logf("%s", dumpLog) 91 cmd := exec.Command("cat", dumpLog) 92 stdoutStderr, err = cmd.CombinedOutput() 93 t.Logf("%s", stdoutStderr) 94 } 95 } 96 assert.NilError(t, err) 97 98 inspect, err := client.ContainerInspect(ctx, cID) 99 assert.NilError(t, err) 100 assert.Check(t, is.Equal(true, inspect.State.Running)) 101 102 checkpoints, err := client.CheckpointList(ctx, cID, types.CheckpointListOptions{}) 103 assert.NilError(t, err) 104 assert.Equal(t, len(checkpoints), 1) 105 assert.Equal(t, checkpoints[0].Name, "test") 106 107 // Create a test file on a tmpfs mount. 108 containerExec(t, client, cID, []string{"touch", "/tmp/test-file"}) 109 110 // Do a second checkpoint 111 cptOpt = types.CheckpointCreateOptions{ 112 Exit: true, 113 CheckpointID: "test2", 114 } 115 t.Log("Do a checkpoint and stop the container") 116 err = client.CheckpointCreate(ctx, cID, cptOpt) 117 assert.NilError(t, err) 118 119 poll.WaitOn(t, 120 container.IsInState(ctx, client, cID, "exited"), 121 poll.WithDelay(100*time.Millisecond), 122 ) 123 124 inspect, err = client.ContainerInspect(ctx, cID) 125 assert.NilError(t, err) 126 assert.Check(t, is.Equal(false, inspect.State.Running)) 127 128 // Check that both checkpoints are listed. 129 checkpoints, err = client.CheckpointList(ctx, cID, types.CheckpointListOptions{}) 130 assert.NilError(t, err) 131 assert.Equal(t, len(checkpoints), 2) 132 cptNames := make([]string, 2) 133 for i, c := range checkpoints { 134 cptNames[i] = c.Name 135 } 136 sort.Strings(cptNames) 137 assert.Equal(t, cptNames[0], "test") 138 assert.Equal(t, cptNames[1], "test2") 139 140 // Restore the container from a second checkpoint. 141 startOpt := types.ContainerStartOptions{ 142 CheckpointID: "test2", 143 } 144 t.Log("Restore the container") 145 err = client.ContainerStart(ctx, cID, startOpt) 146 assert.NilError(t, err) 147 148 inspect, err = client.ContainerInspect(ctx, cID) 149 assert.NilError(t, err) 150 assert.Check(t, is.Equal(true, inspect.State.Running)) 151 152 // Check that the test file has been restored. 153 containerExec(t, client, cID, []string{"test", "-f", "/tmp/test-file"}) 154 155 for _, id := range []string{"test", "test2"} { 156 cptDelOpt := types.CheckpointDeleteOptions{ 157 CheckpointID: id, 158 } 159 160 err = client.CheckpointDelete(ctx, cID, cptDelOpt) 161 assert.NilError(t, err) 162 } 163 }