github.com/lalkh/containerd@v1.4.3/container_checkpoint_opts.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 containerd
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"fmt"
    23  	"runtime"
    24  
    25  	tasks "github.com/containerd/containerd/api/services/tasks/v1"
    26  	"github.com/containerd/containerd/containers"
    27  	"github.com/containerd/containerd/diff"
    28  	"github.com/containerd/containerd/images"
    29  	"github.com/containerd/containerd/platforms"
    30  	"github.com/containerd/containerd/rootfs"
    31  	"github.com/containerd/containerd/runtime/v2/runc/options"
    32  	"github.com/containerd/typeurl"
    33  	imagespec "github.com/opencontainers/image-spec/specs-go/v1"
    34  	"github.com/pkg/errors"
    35  )
    36  
    37  var (
    38  	// ErrCheckpointRWUnsupported is returned if the container runtime does not support checkpoint
    39  	ErrCheckpointRWUnsupported = errors.New("rw checkpoint is only supported on v2 runtimes")
    40  	// ErrMediaTypeNotFound returns an error when a media type in the manifest is unknown
    41  	ErrMediaTypeNotFound = errors.New("media type not found")
    42  )
    43  
    44  // CheckpointOpts are options to manage the checkpoint operation
    45  type CheckpointOpts func(context.Context, *Client, *containers.Container, *imagespec.Index, *options.CheckpointOptions) error
    46  
    47  // WithCheckpointImage includes the container image in the checkpoint
    48  func WithCheckpointImage(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
    49  	ir, err := client.ImageService().Get(ctx, c.Image)
    50  	if err != nil {
    51  		return err
    52  	}
    53  	index.Manifests = append(index.Manifests, ir.Target)
    54  	return nil
    55  }
    56  
    57  // WithCheckpointTask includes the running task
    58  func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
    59  	any, err := typeurl.MarshalAny(copts)
    60  	if err != nil {
    61  		return nil
    62  	}
    63  	task, err := client.TaskService().Checkpoint(ctx, &tasks.CheckpointTaskRequest{
    64  		ContainerID: c.ID,
    65  		Options:     any,
    66  	})
    67  	if err != nil {
    68  		return err
    69  	}
    70  	for _, d := range task.Descriptors {
    71  		platformSpec := platforms.DefaultSpec()
    72  		index.Manifests = append(index.Manifests, imagespec.Descriptor{
    73  			MediaType:   d.MediaType,
    74  			Size:        d.Size_,
    75  			Digest:      d.Digest,
    76  			Platform:    &platformSpec,
    77  			Annotations: d.Annotations,
    78  		})
    79  	}
    80  	// save copts
    81  	data, err := any.Marshal()
    82  	if err != nil {
    83  		return err
    84  	}
    85  	r := bytes.NewReader(data)
    86  	desc, err := writeContent(ctx, client.ContentStore(), images.MediaTypeContainerd1CheckpointOptions, c.ID+"-checkpoint-options", r)
    87  	if err != nil {
    88  		return err
    89  	}
    90  	desc.Platform = &imagespec.Platform{
    91  		OS:           runtime.GOOS,
    92  		Architecture: runtime.GOARCH,
    93  	}
    94  	index.Manifests = append(index.Manifests, desc)
    95  	return nil
    96  }
    97  
    98  // WithCheckpointRuntime includes the container runtime info
    99  func WithCheckpointRuntime(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
   100  	if c.Runtime.Options != nil {
   101  		data, err := c.Runtime.Options.Marshal()
   102  		if err != nil {
   103  			return err
   104  		}
   105  		r := bytes.NewReader(data)
   106  		desc, err := writeContent(ctx, client.ContentStore(), images.MediaTypeContainerd1CheckpointRuntimeOptions, c.ID+"-runtime-options", r)
   107  		if err != nil {
   108  			return err
   109  		}
   110  		desc.Platform = &imagespec.Platform{
   111  			OS:           runtime.GOOS,
   112  			Architecture: runtime.GOARCH,
   113  		}
   114  		index.Manifests = append(index.Manifests, desc)
   115  	}
   116  	return nil
   117  }
   118  
   119  // WithCheckpointRW includes the rw in the checkpoint
   120  func WithCheckpointRW(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
   121  	diffOpts := []diff.Opt{
   122  		diff.WithReference(fmt.Sprintf("checkpoint-rw-%s", c.SnapshotKey)),
   123  	}
   124  	rw, err := rootfs.CreateDiff(ctx,
   125  		c.SnapshotKey,
   126  		client.SnapshotService(c.Snapshotter),
   127  		client.DiffService(),
   128  		diffOpts...,
   129  	)
   130  	if err != nil {
   131  		return err
   132  
   133  	}
   134  	rw.Platform = &imagespec.Platform{
   135  		OS:           runtime.GOOS,
   136  		Architecture: runtime.GOARCH,
   137  	}
   138  	index.Manifests = append(index.Manifests, rw)
   139  	return nil
   140  }
   141  
   142  // WithCheckpointTaskExit causes the task to exit after checkpoint
   143  func WithCheckpointTaskExit(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
   144  	copts.Exit = true
   145  	return nil
   146  }
   147  
   148  // GetIndexByMediaType returns the index in a manifest for the specified media type
   149  func GetIndexByMediaType(index *imagespec.Index, mt string) (*imagespec.Descriptor, error) {
   150  	for _, d := range index.Manifests {
   151  		if d.MediaType == mt {
   152  			return &d, nil
   153  		}
   154  	}
   155  	return nil, ErrMediaTypeNotFound
   156  }