github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/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 }