github.com/lalkh/containerd@v1.4.3/container_restore_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 "context" 21 22 "github.com/containerd/containerd/containers" 23 "github.com/containerd/containerd/content" 24 "github.com/containerd/containerd/images" 25 "github.com/gogo/protobuf/proto" 26 ptypes "github.com/gogo/protobuf/types" 27 "github.com/opencontainers/image-spec/identity" 28 imagespec "github.com/opencontainers/image-spec/specs-go/v1" 29 "github.com/pkg/errors" 30 ) 31 32 var ( 33 // ErrImageNameNotFoundInIndex is returned when the image name is not found in the index 34 ErrImageNameNotFoundInIndex = errors.New("image name not found in index") 35 // ErrRuntimeNameNotFoundInIndex is returned when the runtime is not found in the index 36 ErrRuntimeNameNotFoundInIndex = errors.New("runtime not found in index") 37 // ErrSnapshotterNameNotFoundInIndex is returned when the snapshotter is not found in the index 38 ErrSnapshotterNameNotFoundInIndex = errors.New("snapshotter not found in index") 39 ) 40 41 // RestoreOpts are options to manage the restore operation 42 type RestoreOpts func(context.Context, string, *Client, Image, *imagespec.Index) NewContainerOpts 43 44 // WithRestoreImage restores the image for the container 45 func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts { 46 return func(ctx context.Context, client *Client, c *containers.Container) error { 47 name, ok := index.Annotations[checkpointImageNameLabel] 48 if !ok || name == "" { 49 return ErrRuntimeNameNotFoundInIndex 50 } 51 snapshotter, ok := index.Annotations[checkpointSnapshotterNameLabel] 52 if !ok || name == "" { 53 return ErrSnapshotterNameNotFoundInIndex 54 } 55 i, err := client.GetImage(ctx, name) 56 if err != nil { 57 return err 58 } 59 60 diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform) 61 if err != nil { 62 return err 63 } 64 parent := identity.ChainID(diffIDs).String() 65 if _, err := client.SnapshotService(snapshotter).Prepare(ctx, id, parent); err != nil { 66 return err 67 } 68 c.Image = i.Name() 69 c.SnapshotKey = id 70 c.Snapshotter = snapshotter 71 return nil 72 } 73 } 74 75 // WithRestoreRuntime restores the runtime for the container 76 func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts { 77 return func(ctx context.Context, client *Client, c *containers.Container) error { 78 name, ok := index.Annotations[checkpointRuntimeNameLabel] 79 if !ok { 80 return ErrRuntimeNameNotFoundInIndex 81 } 82 83 // restore options if present 84 m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointRuntimeOptions) 85 if err != nil { 86 if err != ErrMediaTypeNotFound { 87 return err 88 } 89 } 90 var options ptypes.Any 91 if m != nil { 92 store := client.ContentStore() 93 data, err := content.ReadBlob(ctx, store, *m) 94 if err != nil { 95 return errors.Wrap(err, "unable to read checkpoint runtime") 96 } 97 if err := proto.Unmarshal(data, &options); err != nil { 98 return err 99 } 100 } 101 102 c.Runtime = containers.RuntimeInfo{ 103 Name: name, 104 Options: &options, 105 } 106 return nil 107 } 108 } 109 110 // WithRestoreSpec restores the spec from the checkpoint for the container 111 func WithRestoreSpec(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts { 112 return func(ctx context.Context, client *Client, c *containers.Container) error { 113 m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointConfig) 114 if err != nil { 115 return err 116 } 117 store := client.ContentStore() 118 data, err := content.ReadBlob(ctx, store, *m) 119 if err != nil { 120 return errors.Wrap(err, "unable to read checkpoint config") 121 } 122 var any ptypes.Any 123 if err := proto.Unmarshal(data, &any); err != nil { 124 return err 125 } 126 c.Spec = &any 127 return nil 128 } 129 } 130 131 // WithRestoreRW restores the rw layer from the checkpoint for the container 132 func WithRestoreRW(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts { 133 return func(ctx context.Context, client *Client, c *containers.Container) error { 134 // apply rw layer 135 rw, err := GetIndexByMediaType(index, imagespec.MediaTypeImageLayerGzip) 136 if err != nil { 137 return err 138 } 139 mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, c.SnapshotKey) 140 if err != nil { 141 return err 142 } 143 144 if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil { 145 return err 146 } 147 return nil 148 } 149 }