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