github.com/containerd/Containerd@v1.4.13/cmd/ctr/commands/tasks/checkpoint.go (about)

     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 tasks
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/containerd/containerd"
    23  	"github.com/containerd/containerd/cmd/ctr/commands"
    24  	"github.com/containerd/containerd/plugin"
    25  	"github.com/containerd/containerd/runtime/linux/runctypes"
    26  	"github.com/containerd/containerd/runtime/v2/runc/options"
    27  	"github.com/pkg/errors"
    28  	"github.com/urfave/cli"
    29  )
    30  
    31  var checkpointCommand = cli.Command{
    32  	Name:      "checkpoint",
    33  	Usage:     "checkpoint a container",
    34  	ArgsUsage: "[flags] CONTAINER",
    35  	Flags: []cli.Flag{
    36  		cli.BoolFlag{
    37  			Name:  "exit",
    38  			Usage: "stop the container after the checkpoint",
    39  		},
    40  		cli.StringFlag{
    41  			Name:  "image-path",
    42  			Usage: "path to criu image files",
    43  		},
    44  		cli.StringFlag{
    45  			Name:  "work-path",
    46  			Usage: "path to criu work files and logs",
    47  		},
    48  	},
    49  	Action: func(context *cli.Context) error {
    50  		id := context.Args().First()
    51  		if id == "" {
    52  			return errors.New("container id must be provided")
    53  		}
    54  		client, ctx, cancel, err := commands.NewClient(context, containerd.WithDefaultRuntime(context.String("runtime")))
    55  		if err != nil {
    56  			return err
    57  		}
    58  		defer cancel()
    59  		container, err := client.LoadContainer(ctx, id)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		task, err := container.Task(ctx, nil)
    64  		if err != nil {
    65  			return err
    66  		}
    67  		info, err := container.Info(ctx)
    68  		if err != nil {
    69  			return err
    70  		}
    71  		opts := []containerd.CheckpointTaskOpts{withCheckpointOpts(info.Runtime.Name, context)}
    72  		checkpoint, err := task.Checkpoint(ctx, opts...)
    73  		if err != nil {
    74  			return err
    75  		}
    76  		if context.String("image-path") == "" {
    77  			fmt.Println(checkpoint.Name())
    78  		}
    79  		return nil
    80  	},
    81  }
    82  
    83  // withCheckpointOpts only suitable for runc runtime now
    84  func withCheckpointOpts(rt string, context *cli.Context) containerd.CheckpointTaskOpts {
    85  	return func(r *containerd.CheckpointTaskInfo) error {
    86  		imagePath := context.String("image-path")
    87  		workPath := context.String("work-path")
    88  
    89  		switch rt {
    90  		case plugin.RuntimeRuncV1, plugin.RuntimeRuncV2:
    91  			if r.Options == nil {
    92  				r.Options = &options.CheckpointOptions{}
    93  			}
    94  			opts, _ := r.Options.(*options.CheckpointOptions)
    95  
    96  			if context.Bool("exit") {
    97  				opts.Exit = true
    98  			}
    99  			if imagePath != "" {
   100  				opts.ImagePath = imagePath
   101  			}
   102  			if workPath != "" {
   103  				opts.WorkPath = workPath
   104  			}
   105  		case plugin.RuntimeLinuxV1:
   106  			if r.Options == nil {
   107  				r.Options = &runctypes.CheckpointOptions{}
   108  			}
   109  			opts, _ := r.Options.(*runctypes.CheckpointOptions)
   110  
   111  			if context.Bool("exit") {
   112  				opts.Exit = true
   113  			}
   114  			if imagePath != "" {
   115  				opts.ImagePath = imagePath
   116  			}
   117  			if workPath != "" {
   118  				opts.WorkPath = workPath
   119  			}
   120  		}
   121  		return nil
   122  	}
   123  }