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  }