diff --git a/internal/lib/restore.go b/internal/lib/restore.go index d2ec2cade0a..7e8502ce1e4 100644 --- a/internal/lib/restore.go +++ b/internal/lib/restore.go @@ -8,6 +8,7 @@ import ( metadata "github.com/checkpoint-restore/checkpointctl/lib" "github.com/checkpoint-restore/go-criu/v6/stats" + "github.com/containers/podman/v4/pkg/annotations" "github.com/containers/podman/v4/pkg/checkpoint/crutils" "github.com/containers/storage/pkg/archive" "github.com/cri-o/cri-o/internal/log" @@ -31,8 +32,10 @@ func (c *ContainerServer) ContainerRestore(ctx context.Context, opts *ContainerC } // Get config.json - configFile := filepath.Join(ctr.Dir(), "config.json") - ctrSpec, err := generate.NewFromFile(configFile) + // This file is generated twice by earlier code. Once in BundlePath() and + // once in Dir(). This code takes the version from Dir(), modifies it and + // overwrites both versions (Dir() and BundlePath()) + ctrSpec, err := generate.NewFromFile(filepath.Join(ctr.Dir(), "config.json")) if err != nil { return "", err } @@ -54,15 +57,6 @@ func (c *ContainerServer) ContainerRestore(ctx context.Context, opts *ContainerC if err != nil { return "", err } - ic := sb.InfraContainer() - if ic == nil { - return "", fmt.Errorf("infra container of sandbox %v not found", sb.Name()) - } - infraConfigFile := filepath.Join(ic.BundlePath(), "config.json") - specgen, err := generate.NewFromFile(infraConfigFile) - if err != nil { - return "", err - } if ctr.RestoreArchive() != "" { if ctr.RestoreIsOCIImage() { @@ -209,7 +203,55 @@ func (c *ContainerServer) ContainerRestore(ctx context.Context, opts *ContainerC } } - if err := c.runtime.RestoreContainer(ctx, ctr, specgen.Config, ic.State().Pid, sb.CgroupParent()); err != nil { + // We need to adapt the to be restored container to the sandbox created for this container. + + // The container will be restored in another sandbox. Adapt to + // namespaces of the new sandbox + for i, n := range ctrSpec.Config.Linux.Namespaces { + if n.Path == "" { + // The namespace in the original container did not point to + // an existing interface. Leave it as it is. + // CRIU will restore the namespace + continue + } + for _, np := range sb.NamespacePaths() { + if string(np.Type()) == string(n.Type) { + ctrSpec.Config.Linux.Namespaces[i].Path = np.Path() + break + } + } + } + + // Update Sandbox Name + ctrSpec.AddAnnotation(annotations.SandboxName, sb.Name()) + // Update Sandbox ID + ctrSpec.AddAnnotation(annotations.SandboxID, opts.Pod) + + mData := fmt.Sprintf( + "k8s_%s_%s_%s_%s0", + ctr.Name(), + sb.KubeName(), + sb.Namespace(), + sb.Metadata().Uid, + ) + ctrSpec.AddAnnotation(annotations.Name, mData) + + ctr.SetSandbox(opts.Pod) + + saveOptions := generate.ExportOptions{} + if err := ctrSpec.SaveToFile(filepath.Join(ctr.Dir(), "config.json"), saveOptions); err != nil { + return "", err + } + if err := ctrSpec.SaveToFile(filepath.Join(ctr.BundlePath(), "config.json"), saveOptions); err != nil { + return "", err + } + + if err := c.runtime.RestoreContainer( + ctx, + ctr, + sb.CgroupParent(), + sb.MountLabel(), + ); err != nil { return "", fmt.Errorf("failed to restore container %s: %w", ctr.ID(), err) } if err := c.ContainerStateToDisk(ctx, ctr); err != nil { diff --git a/internal/lib/restore_test.go b/internal/lib/restore_test.go index fdd6fea052d..34c23d9f28f 100644 --- a/internal/lib/restore_test.go +++ b/internal/lib/restore_test.go @@ -87,7 +87,7 @@ var _ = t.Describe("ContainerRestore", func() { // Then Expect(err).NotTo(BeNil()) Expect(res).To(Equal("")) - Expect(err.Error()).To(Equal(`infra container of sandbox not found`)) + Expect(err.Error()).To(Equal(`failed to restore container containerID: a complete checkpoint for this container cannot be found, cannot restore: stat checkpoint/inventory.img: no such file or directory`)) }) }) t.Describe("ContainerRestore", func() { diff --git a/internal/oci/oci.go b/internal/oci/oci.go index 39b90e49cd9..d331cf7fe05 100644 --- a/internal/oci/oci.go +++ b/internal/oci/oci.go @@ -76,7 +76,7 @@ type RuntimeImpl interface { int32, io.ReadWriteCloser) error ReopenContainerLog(context.Context, *Container) error CheckpointContainer(context.Context, *Container, *rspec.Spec, bool) error - RestoreContainer(context.Context, *Container, *rspec.Spec, int, string) error + RestoreContainer(context.Context, *Container, string, string) error } // New creates a new Runtime with options provided @@ -428,11 +428,11 @@ func (r *Runtime) CheckpointContainer(ctx context.Context, c *Container, specgen } // RestoreContainer restores a container. -func (r *Runtime) RestoreContainer(ctx context.Context, c *Container, sbSpec *rspec.Spec, infraPid int, cgroupParent string) error { +func (r *Runtime) RestoreContainer(ctx context.Context, c *Container, cgroupParent, mountLabel string) error { impl, err := r.RuntimeImpl(c) if err != nil { return err } - return impl.RestoreContainer(ctx, c, sbSpec, infraPid, cgroupParent) + return impl.RestoreContainer(ctx, c, cgroupParent, mountLabel) } diff --git a/internal/oci/oci_test.go b/internal/oci/oci_test.go index f4451281e7d..04e5217aa78 100644 --- a/internal/oci/oci_test.go +++ b/internal/oci/oci_test.go @@ -182,7 +182,7 @@ var _ = t.Describe("Oci", func() { Skip("CRIU is missing or too old.") } // Given - beforeEach(sandboxID) + beforeEach() defer os.RemoveAll("dump.log") config.Runtimes["runc"] = &libconfig.RuntimeHandler{ RuntimePath: "/bin/true", @@ -209,7 +209,7 @@ var _ = t.Describe("Oci", func() { } // Given defer os.RemoveAll("dump.log") - beforeEach(sandboxID) + beforeEach() config.Runtimes["runc"] = &libconfig.RuntimeHandler{ RuntimePath: "/bin/false", } @@ -235,14 +235,12 @@ var _ = t.Describe("Oci", func() { Skip("CRIU is missing or too old.") } // Given - beforeEach(sandboxID) + beforeEach() config.Runtimes["runc"] = &libconfig.RuntimeHandler{ RuntimePath: "/bin/true", + MonitorPath: "/bin/true", } - specgen := &specs.Spec{ - Version: "1.0.0", - } err := os.Mkdir("checkpoint", 0o700) Expect(err).To(BeNil()) defer os.RemoveAll("checkpoint") @@ -250,42 +248,31 @@ var _ = t.Describe("Oci", func() { Expect(err).To(BeNil()) inventory.Close() - // When - err = sut.RestoreContainer(context.Background(), myContainer, specgen, 42, "no-parent-cgroup-exists") - - // Then - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(Equal("failed to detect destination sandbox of to be restored container containerID")) - }) - It("RestoreContainer should fail with destination sandbox detection", func() { - if !criu.CheckForCriu(criu.PodCriuVersion) { - Skip("CRIU is missing or too old.") - } - // Given - beforeEach("") specgen := &specs.Spec{ - Version: "1.0.0", + Version: "1.0.0", + Annotations: map[string]string{"io.kubernetes.cri-o.SandboxID": "sandboxID"}, + Linux: &specs.Linux{ + MountLabel: ".", + }, + Process: &specs.Process{ + SelinuxLabel: "", + }, } - err := os.Mkdir("checkpoint", 0o700) - Expect(err).To(BeNil()) - defer os.RemoveAll("checkpoint") - inventory, err := os.OpenFile("checkpoint/inventory.img", os.O_RDONLY|os.O_CREATE, 0o644) - Expect(err).To(BeNil()) - inventory.Close() + myContainer.SetSpec(specgen) // When - err = sut.RestoreContainer(context.Background(), myContainer, specgen, 42, "no-parent-cgroup-exists") + err = sut.RestoreContainer(context.Background(), myContainer, "no-parent-cgroup-exists", "label") // Then Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(Equal("failed to detect sandbox of to be restored container containerID")) + Expect(err.Error()).To(ContainSubstring("failed")) }) It("RestoreContainer should fail", func() { if !criu.CheckForCriu(criu.PodCriuVersion) { Skip("CRIU is missing or too old.") } // Given - beforeEach(sandboxID) + beforeEach() config.Runtimes["runc"] = &libconfig.RuntimeHandler{ RuntimePath: "/bin/true", MonitorPath: "/bin/true", @@ -325,7 +312,7 @@ var _ = t.Describe("Oci", func() { config.Conmon = "/bin/true" // When - err = sut.RestoreContainer(context.Background(), myContainer, specgen, 42, "no-parent-cgroup-exists") + err = sut.RestoreContainer(context.Background(), myContainer, "no-parent-cgroup-exists", "label") defer os.RemoveAll("restore.log") // Then @@ -337,16 +324,9 @@ var _ = t.Describe("Oci", func() { Skip("CRIU is missing or too old.") } // Given - beforeEach(sandboxID) - specgen := &specs.Spec{ - Version: "1.0.0", - Annotations: map[string]string{"io.kubernetes.cri-o.SandboxID": "sandboxID"}, - Linux: &specs.Linux{ - MountLabel: ".", - }, - } + beforeEach() // When - err := sut.RestoreContainer(context.Background(), myContainer, specgen, 42, "no-parent-cgroup-exists") + err := sut.RestoreContainer(context.Background(), myContainer, "no-parent-cgroup-exists", "label") // Then Expect(err).NotTo(BeNil()) diff --git a/internal/oci/runtime_oci.go b/internal/oci/runtime_oci.go index d3fb1b4bf0c..6ae583dd752 100644 --- a/internal/oci/runtime_oci.go +++ b/internal/oci/runtime_oci.go @@ -17,7 +17,6 @@ import ( metadata "github.com/checkpoint-restore/checkpointctl/lib" "github.com/containernetworking/plugins/pkg/ns" conmonconfig "github.com/containers/conmon/runner/config" - "github.com/containers/podman/v4/pkg/annotations" "github.com/containers/podman/v4/pkg/checkpoint/crutils" "github.com/containers/podman/v4/pkg/criu" "github.com/containers/storage/pkg/pools" @@ -30,7 +29,6 @@ import ( "github.com/fsnotify/fsnotify" json "github.com/json-iterator/go" rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/runtime-tools/generate" "github.com/sirupsen/logrus" "golang.org/x/net/context" "golang.org/x/sys/unix" @@ -1528,7 +1526,7 @@ func (r *runtimeOCI) CheckpointContainer(ctx context.Context, c *Container, spec } // RestoreContainer restores a container. -func (r *runtimeOCI) RestoreContainer(ctx context.Context, c *Container, sbSpec *rspec.Spec, infraPid int, cgroupParent string) error { +func (r *runtimeOCI) RestoreContainer(ctx context.Context, c *Container, cgroupParent, mountLabel string) error { if err := r.checkpointRestoreSupported(); err != nil { return err } @@ -1555,78 +1553,6 @@ func (r *runtimeOCI) RestoreContainer(ctx context.Context, c *Container, sbSpec return fmt.Errorf("error removing container %s winsz file: %w", c.ID(), err) } - // Figure out if this container will be restored in another sandbox - oldSbID := c.Sandbox() - if oldSbID == "" { - return fmt.Errorf("failed to detect sandbox of to be restored container %s", c.ID()) - } - newSbID := sbSpec.Annotations[annotations.SandboxID] - if newSbID == "" { - return fmt.Errorf("failed to detect destination sandbox of to be restored container %s", c.ID()) - } - - // Get config.json to adapt for restore (mostly annotations for restore in another sandbox) - configFile := filepath.Join(c.BundlePath(), "config.json") - specgen, err := generate.NewFromFile(configFile) - if err != nil { - return err - } - - if oldSbID != newSbID { - // The container will be restored in another (not the original) sandbox - // Adapt to namespaces of the new sandbox - for i, n := range specgen.Config.Linux.Namespaces { - if n.Path == "" { - // The namespace in the original container did not point to - // an existing interface. Leave it as it is. - continue - } - for _, on := range sbSpec.Linux.Namespaces { - if on.Type == n.Type { - var nsPath string - if n.Type == rspec.NetworkNamespace { - // Type for network namespaces is 'network'. - // The kernel link is 'net'. - nsPath = fmt.Sprintf("/proc/%d/ns/%s", infraPid, "net") - } else { - nsPath = fmt.Sprintf("/proc/%d/ns/%s", infraPid, n.Type) - } - specgen.Config.Linux.Namespaces[i].Path = nsPath - break - } - } - } - - // Update Sandbox Name - specgen.AddAnnotation(annotations.SandboxName, sbSpec.Annotations[annotations.Name]) - // Update Sandbox ID - specgen.AddAnnotation(annotations.SandboxID, newSbID) - - // Update Name - ctrMetadata := types.ContainerMetadata{} - err = json.Unmarshal([]byte(sbSpec.Annotations[annotations.Metadata]), &ctrMetadata) - if err != nil { - return err - } - ctrName := ctrMetadata.Name - - podMetadata := types.PodSandboxMetadata{} - err = json.Unmarshal([]byte(specgen.Config.Annotations[annotations.Metadata]), &podMetadata) - if err != nil { - return err - } - uid := podMetadata.Uid - mData := fmt.Sprintf("k8s_%s_%s_%s_%s0", ctrName, sbSpec.Annotations[annotations.KubeName], sbSpec.Annotations[annotations.Namespace], uid) - specgen.AddAnnotation(annotations.Name, mData) - - c.SetSandbox(newSbID) - - saveOptions := generate.ExportOptions{} - if err := specgen.SaveToFile(configFile, saveOptions); err != nil { - return err - } - } - c.state.InitPid = 0 c.state.InitStartTime = "" @@ -1639,7 +1565,7 @@ func (r *runtimeOCI) RestoreContainer(ctx context.Context, c *Container, sbSpec if err := crutils.CRCreateFileWithLabel( c.BundlePath(), metadata.RestoreLogFile, - specgen.Config.Linux.MountLabel, + mountLabel, ); err != nil { return err } diff --git a/internal/oci/runtime_pod.go b/internal/oci/runtime_pod.go index bb7d39505b9..d15fddfaca9 100644 --- a/internal/oci/runtime_pod.go +++ b/internal/oci/runtime_pod.go @@ -159,11 +159,10 @@ func (r *runtimePod) CheckpointContainer( func (r *runtimePod) RestoreContainer( ctx context.Context, c *Container, - sbSpec *rspec.Spec, - infraPid int, cgroupParent string, + mountLabel string, ) error { - return r.oci.RestoreContainer(ctx, c, sbSpec, infraPid, cgroupParent) + return r.oci.RestoreContainer(ctx, c, cgroupParent, mountLabel) } func (r *runtimePod) ExecContainer(ctx context.Context, c *Container, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resizeChan <-chan remotecommand.TerminalSize) error { diff --git a/internal/oci/runtime_vm.go b/internal/oci/runtime_vm.go index 07290fda68d..706ee238bf0 100644 --- a/internal/oci/runtime_vm.go +++ b/internal/oci/runtime_vm.go @@ -1050,7 +1050,7 @@ func (r *runtimeVM) CheckpointContainer(ctx context.Context, c *Container, specg } // RestoreContainer not implemented for runtimeVM -func (r *runtimeVM) RestoreContainer(ctx context.Context, c *Container, sbSpec *rspec.Spec, infraPid int, cgroupParent string) error { +func (r *runtimeVM) RestoreContainer(ctx context.Context, c *Container, cgroupParent, mountLabel string) error { log.Debugf(ctx, "RuntimeVM.RestoreContainer() start") defer log.Debugf(ctx, "RuntimeVM.RestoreContainer() end") diff --git a/internal/oci/suite_test.go b/internal/oci/suite_test.go index 0e9479d1259..ce1fd50eecc 100644 --- a/internal/oci/suite_test.go +++ b/internal/oci/suite_test.go @@ -33,12 +33,12 @@ const ( containerID = "containerID" ) -func beforeEach(sbID string) { +func beforeEach() { var err error myContainer, err = oci.NewContainer(containerID, "", "", "", make(map[string]string), make(map[string]string), make(map[string]string), "", "", "", - &types.ContainerMetadata{}, sbID, false, + &types.ContainerMetadata{}, sandboxID, false, false, false, "", "", time.Now(), "") Expect(err).To(BeNil()) } diff --git a/server/container_create.go b/server/container_create.go index 629618208bf..e8a93dd3889 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -334,11 +334,9 @@ func (s *Server) CreateContainer(ctx context.Context, req *types.CreateContainer // it to the checkpoint code. ctrID, err := s.CRImportCheckpoint( ctx, - req.Config.Image.Image, + req.Config, req.PodSandboxId, req.SandboxConfig.Metadata.Uid, - req.Config.Mounts, - req.Config.Annotations, ) if err != nil { return nil, err diff --git a/server/container_restore.go b/server/container_restore.go index 6cf45b8b5e3..8c7644c02ab 100644 --- a/server/container_restore.go +++ b/server/container_restore.go @@ -57,12 +57,15 @@ func (s *Server) checkIfCheckpointOCIImage(ctx context.Context, input string) (b // taken from Podman func (s *Server) CRImportCheckpoint( ctx context.Context, - input, sbID, sandboxUID string, - createMounts []*types.Mount, - createAnnotations map[string]string, + createConfig *types.ContainerConfig, + sbID, sandboxUID string, ) (ctrID string, retErr error) { var mountPoint string + input := createConfig.Image.Image + createMounts := createConfig.Mounts + createAnnotations := createConfig.Annotations + checkpointIsOCIImage, err := s.checkIfCheckpointOCIImage(ctx, input) if err != nil { return "", err @@ -221,6 +224,13 @@ func (s *Server) CRImportCheckpoint( Labels: originalLabels, } + if createConfig.Linux.Resources != nil { + containerConfig.Linux.Resources = createConfig.Linux.Resources + } + if createConfig.Linux.SecurityContext != nil { + containerConfig.Linux.SecurityContext = createConfig.Linux.SecurityContext + } + ignoreMounts := map[string]bool{ "/proc": true, "/dev": true, diff --git a/server/container_restore_test.go b/server/container_restore_test.go index 31110d248a4..976d99df748 100644 --- a/server/container_restore_test.go +++ b/server/container_restore_test.go @@ -15,6 +15,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" specs "github.com/opencontainers/runtime-spec/specs-go" + types "k8s.io/cri-api/pkg/apis/runtime/v1" ) var _ = t.Describe("ContainerRestore", func() { @@ -53,14 +54,19 @@ var _ = t.Describe("ContainerRestore", func() { User: "10", Size: &size, }, nil), ) + + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "does-not-exist.tar", + }, + } + // When _, err := sut.CRImportCheckpoint( context.Background(), - "does-not-exist.tar", + containerConfig, "", "", - nil, - nil, ) // Then @@ -74,14 +80,17 @@ var _ = t.Describe("ContainerRestore", func() { Expect(err).To(BeNil()) archive.Close() defer os.RemoveAll("empty.tar") + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "empty.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "empty.tar", + containerConfig, "", "", - nil, - nil, ) // Then Expect(err.Error()).To(ContainSubstring(`failed to read "spec.dump": failed to read`)) @@ -93,14 +102,17 @@ var _ = t.Describe("ContainerRestore", func() { err := os.WriteFile("no.tar", []byte("notar"), 0o644) Expect(err).To(BeNil()) defer os.RemoveAll("no.tar") + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "no.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "no.tar", + containerConfig, "", "", - nil, - nil, ) // Then Expect(err.Error()).To(ContainSubstring(`unpacking of checkpoint archive`)) @@ -124,14 +136,17 @@ var _ = t.Describe("ContainerRestore", func() { defer os.RemoveAll("archive.tar") _, err = io.Copy(outFile, input) Expect(err).To(BeNil()) + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "archive.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "archive.tar", + containerConfig, "", "", - nil, - nil, ) // Then Expect(err.Error()).To(ContainSubstring(`failed to read "spec.dump": failed to unmarshal `)) @@ -158,14 +173,17 @@ var _ = t.Describe("ContainerRestore", func() { defer os.RemoveAll("archive.tar") _, err = io.Copy(outFile, input) Expect(err).To(BeNil()) + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "archive.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "archive.tar", + containerConfig, "", "", - nil, - nil, ) // Then @@ -193,15 +211,18 @@ var _ = t.Describe("ContainerRestore", func() { defer os.RemoveAll("archive.tar") _, err = io.Copy(outFile, input) Expect(err).To(BeNil()) + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "archive.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "archive.tar", + containerConfig, "", "", - nil, - nil, ) // Then @@ -235,15 +256,18 @@ var _ = t.Describe("ContainerRestore", func() { defer os.RemoveAll("archive.tar") _, err = io.Copy(outFile, input) Expect(err).To(BeNil()) + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "archive.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "archive.tar", + containerConfig, "", "", - nil, - nil, ) // Then @@ -280,15 +304,18 @@ var _ = t.Describe("ContainerRestore", func() { defer os.RemoveAll("archive.tar") _, err = io.Copy(outFile, input) Expect(err).To(BeNil()) + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "archive.tar", + }, + } // When _, err = sut.CRImportCheckpoint( context.Background(), - "archive.tar", + containerConfig, "", "", - nil, - nil, ) // Then @@ -332,14 +359,17 @@ var _ = t.Describe("ContainerRestore", func() { storeMock.EXPECT().UnmountImage(gomock.Any(), true). Return(false, nil), ) + containerConfig := &types.ContainerConfig{ + Image: &types.ImageSpec{ + Image: "localhost/checkpoint-image:tag1", + }, + } // When _, err := sut.CRImportCheckpoint( context.Background(), - "localhost/checkpoint-image:tag1", + containerConfig, "", "", - nil, - nil, ) // Then diff --git a/test/checkpoint.bats b/test/checkpoint.bats index 38df6a5d81d..70384820443 100644 --- a/test/checkpoint.bats +++ b/test/checkpoint.bats @@ -14,7 +14,31 @@ function teardown() { cleanup_test } -@test "checkpoint and restore one container into a new pod using --export" { +@test "checkpoint and restore one container into a new pod (drop infra:true)" { + CONTAINER_DROP_INFRA_CTR=true CONTAINER_ENABLE_CRIU_SUPPORT=true start_crio + pod_id=$(crictl runp "$TESTDATA"/sandbox_config.json) + BIND_MOUNT_FILE=$(mktemp) + BIND_MOUNT_DIR=$(mktemp -d) + jq ". +{mounts:[{\"container_path\":\"/etc/issue\",\"host_path\":\"$BIND_MOUNT_FILE\"},{\"container_path\":\"/data\",\"host_path\":\"$BIND_MOUNT_DIR\"}]}" "$TESTDATA"/container_sleep.json > "$TESTDATA"/checkpoint.json + ctr_id=$(crictl create "$pod_id" "$TESTDATA"/checkpoint.json "$TESTDATA"/sandbox_config.json) + crictl start "$ctr_id" + crictl checkpoint --export="$TESTDIR"/cp.tar "$ctr_id" + crictl rm -f "$ctr_id" + crictl rmp -f "$pod_id" + rm -f "$BIND_MOUNT_FILE" + rmdir "$BIND_MOUNT_DIR" + pod_id=$(crictl runp "$TESTDATA"/sandbox_config.json) + # Replace original container with checkpoint image + jq ".image.image=\"$TESTDIR/cp.tar\"" "$TESTDATA"/container_sleep.json > "$TESTDATA"/restore.json + ctr_id=$(crictl create "$pod_id" "$TESTDATA"/restore.json "$TESTDATA"/sandbox_config.json) + rm -f "$TESTDATA"/restore.json + rm -f "$TESTDATA"/checkpoint.json + crictl start "$ctr_id" + rm -f "$BIND_MOUNT_FILE" + rmdir "$BIND_MOUNT_DIR" +} + +@test "checkpoint and restore one container into a new pod (drop infra:false)" { CONTAINER_DROP_INFRA_CTR=false CONTAINER_ENABLE_CRIU_SUPPORT=true start_crio pod_id=$(crictl runp "$TESTDATA"/sandbox_config.json) BIND_MOUNT_FILE=$(mktemp) diff --git a/test/mocks/oci/oci.go b/test/mocks/oci/oci.go index 9049cd32119..11553c99005 100644 --- a/test/mocks/oci/oci.go +++ b/test/mocks/oci/oci.go @@ -183,17 +183,17 @@ func (mr *MockRuntimeImplMockRecorder) ReopenContainerLog(arg0, arg1 interface{} } // RestoreContainer mocks base method. -func (m *MockRuntimeImpl) RestoreContainer(arg0 context.Context, arg1 *oci.Container, arg2 *specs.Spec, arg3 int, arg4 string) error { +func (m *MockRuntimeImpl) RestoreContainer(arg0 context.Context, arg1 *oci.Container, arg2, arg3 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RestoreContainer", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "RestoreContainer", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) return ret0 } // RestoreContainer indicates an expected call of RestoreContainer. -func (mr *MockRuntimeImplMockRecorder) RestoreContainer(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockRuntimeImplMockRecorder) RestoreContainer(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RestoreContainer", reflect.TypeOf((*MockRuntimeImpl)(nil).RestoreContainer), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RestoreContainer", reflect.TypeOf((*MockRuntimeImpl)(nil).RestoreContainer), arg0, arg1, arg2, arg3) } // SignalContainer mocks base method.