Skip to content

Commit fee41f4

Browse files
committed
checkpoint: support checkpoint create command
Signed-off-by: ChengyuZhu6 <[email protected]>
1 parent 05ab86f commit fee41f4

File tree

5 files changed

+220
-0
lines changed

5 files changed

+220
-0
lines changed

cmd/nerdctl/checkpoint/checkpoint.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package checkpoint
18+
19+
import (
20+
"github.com/spf13/cobra"
21+
22+
"github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers"
23+
)
24+
25+
func Command() *cobra.Command {
26+
cmd := &cobra.Command{
27+
Annotations: map[string]string{helpers.Category: helpers.Management},
28+
Use: "checkpoint",
29+
Short: "Manage checkpoints.",
30+
RunE: helpers.UnknownSubcommandAction,
31+
SilenceUsage: true,
32+
SilenceErrors: true,
33+
}
34+
35+
cmd.AddCommand(
36+
CreateCommand(),
37+
)
38+
39+
return cmd
40+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package checkpoint
18+
19+
import (
20+
"github.com/spf13/cobra"
21+
22+
"github.com/containerd/nerdctl/v2/cmd/nerdctl/completion"
23+
"github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers"
24+
"github.com/containerd/nerdctl/v2/pkg/api/types"
25+
"github.com/containerd/nerdctl/v2/pkg/clientutil"
26+
"github.com/containerd/nerdctl/v2/pkg/cmd/checkpoint"
27+
)
28+
29+
func CreateCommand() *cobra.Command {
30+
var cmd = &cobra.Command{
31+
Use: "create [OPTIONS] CONTAINER CHECKPOINT",
32+
Short: "Create a checkpoint from a running container",
33+
Args: cobra.ExactArgs(2),
34+
RunE: createAction,
35+
ValidArgsFunction: createShellComplete,
36+
SilenceUsage: true,
37+
SilenceErrors: true,
38+
}
39+
cmd.Flags().Bool("leave-running", false, "Leave the container running after checkpointing")
40+
return cmd
41+
}
42+
43+
func processCreateFlags(cmd *cobra.Command) (types.CheckpointCreateOptions, error) {
44+
globalOptions, err := helpers.ProcessRootCmdFlags(cmd)
45+
if err != nil {
46+
return types.CheckpointCreateOptions{}, err
47+
}
48+
49+
leaveRunning, err := cmd.Flags().GetBool("leave-running")
50+
51+
if err != nil {
52+
return types.CheckpointCreateOptions{}, err
53+
}
54+
55+
return types.CheckpointCreateOptions{
56+
Stdout: cmd.OutOrStdout(),
57+
GOptions: globalOptions,
58+
LeaveRunning: leaveRunning,
59+
}, nil
60+
}
61+
62+
func createAction(cmd *cobra.Command, args []string) error {
63+
createOptions, err := processCreateFlags(cmd)
64+
if err != nil {
65+
return err
66+
}
67+
client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), createOptions.GOptions.Namespace, createOptions.GOptions.Address)
68+
if err != nil {
69+
return err
70+
}
71+
defer cancel()
72+
73+
err = checkpoint.Create(ctx, client, args[0], args[1], createOptions)
74+
if err != nil {
75+
return err
76+
}
77+
78+
return nil
79+
}
80+
81+
func createShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
82+
return completion.ImageNames(cmd)
83+
}

cmd/nerdctl/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/containerd/log"
3232

3333
"github.com/containerd/nerdctl/v2/cmd/nerdctl/builder"
34+
"github.com/containerd/nerdctl/v2/cmd/nerdctl/checkpoint"
3435
"github.com/containerd/nerdctl/v2/cmd/nerdctl/completion"
3536
"github.com/containerd/nerdctl/v2/cmd/nerdctl/compose"
3637
"github.com/containerd/nerdctl/v2/cmd/nerdctl/container"
@@ -350,6 +351,9 @@ Config file ($NERDCTL_TOML): %s
350351

351352
// Manifest
352353
manifest.Command(),
354+
355+
// Checkpoint
356+
checkpoint.Command(),
353357
)
354358
addApparmorCommand(rootCmd)
355359
container.AddCpCommand(rootCmd)

pkg/api/types/checkpoint_types.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package types
18+
19+
import "io"
20+
21+
// CheckpointCreateOptions specifies options for `nerdctl checkpoint create`.
22+
type CheckpointCreateOptions struct {
23+
Stdout io.Writer
24+
GOptions GlobalCommandOptions
25+
// Leave the container running after checkpointing
26+
LeaveRunning bool
27+
}

pkg/cmd/checkpoint/create.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package checkpoint
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
containerd "github.com/containerd/containerd/v2/client"
24+
25+
"github.com/containerd/nerdctl/v2/pkg/api/types"
26+
"github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker"
27+
)
28+
29+
func Create(ctx context.Context, client *containerd.Client, containerID string, checkpointDir string, options types.CheckpointCreateOptions) error {
30+
var container containerd.Container
31+
32+
walker := &containerwalker.ContainerWalker{
33+
Client: client,
34+
OnFound: func(ctx context.Context, found containerwalker.Found) error {
35+
if found.MatchCount > 1 {
36+
return fmt.Errorf("multiple containers found with provided prefix: %s", found.Req)
37+
}
38+
container = found.Container
39+
return nil
40+
},
41+
}
42+
43+
n, err := walker.Walk(ctx, containerID)
44+
if err != nil {
45+
return err
46+
} else if n == 0 {
47+
return fmt.Errorf("no such container: %s", containerID)
48+
}
49+
50+
opts := []containerd.CheckpointOpts{
51+
containerd.WithCheckpointRuntime,
52+
containerd.WithCheckpointRW,
53+
containerd.WithCheckpointTask,
54+
}
55+
if !options.LeaveRunning {
56+
opts = append(opts, containerd.WithCheckpointTaskExit)
57+
}
58+
59+
checkpoint, err := container.Checkpoint(ctx, checkpointDir, opts...)
60+
if err != nil {
61+
return err
62+
}
63+
64+
fmt.Fprintf(options.Stdout, "Checkpoint created: %s\n", checkpoint.Name())
65+
return nil
66+
}

0 commit comments

Comments
 (0)