add image name and runtime name media types; remove task operation on checkpoint

Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
Evan Hazlett 2018-09-17 13:48:46 -04:00
parent ce0673fd7d
commit 147208061c
4 changed files with 123 additions and 63 deletions

View File

@ -332,6 +332,17 @@ var checkpointCommand = cli.Command{
if err != nil {
return err
}
task, err := container.Task(ctx, nil)
if err != nil {
if !errdefs.IsNotFound(err) {
return err
}
}
if err := task.Pause(ctx); err != nil {
return err
}
defer task.Resume(ctx)
if _, err := container.Checkpoint(ctx, ref, opts...); err != nil {
return err
}
@ -378,6 +389,7 @@ var restoreCommand = cli.Command{
}
opts := []containerd.RestoreOpts{
containerd.WithRestoreImage,
containerd.WithRestoreSpec,
containerd.WithRestoreSnapshot,
containerd.WithRestoreRuntime,

View File

@ -295,11 +295,15 @@ func (c *container) Checkpoint(ctx context.Context, ref string, opts ...Checkpoi
FileLocks: true,
EmptyNamespaces: nil,
}
info, err := c.Info(ctx)
if err != nil {
return nil, err
}
img, err := c.Image(ctx)
if err != nil {
return nil, err
}
index.Annotations["image.name"] = img.Name()
ctx, done, err := c.client.WithLease(ctx)
if err != nil {
@ -307,54 +311,53 @@ func (c *container) Checkpoint(ctx context.Context, ref string, opts ...Checkpoi
}
defer done(ctx)
// pause task to checkpoint
if err := func(ctx context.Context) error {
task, err := c.Task(ctx, nil)
if err != nil {
if errdefs.IsNotFound(err) {
return nil
}
return err
}
if err := task.Pause(ctx); err != nil {
return err
}
defer task.Resume(ctx)
info, err := c.Info(ctx)
if err != nil {
return err
}
// add runtime info to index
index.Annotations["runtime.name"] = info.Runtime.Name
if info.Runtime.Options != nil {
data, err := info.Runtime.Options.Marshal()
if err != nil {
return err
}
r := bytes.NewReader(data)
desc, err := writeContent(ctx, c.client.ContentStore(), images.MediaTypeContainerd1CheckpointRuntimeOptions, info.ID+"-runtime-options", r)
if err != nil {
return err
}
desc.Platform = &ocispec.Platform{
OS: runtime.GOOS,
Architecture: runtime.GOARCH,
}
index.Manifests = append(index.Manifests, desc)
}
// process remaining opts
for _, o := range opts {
if err := o(ctx, c.client, &info, index, copts); err != nil {
return err
}
}
return nil
}(ctx); err != nil {
// add image name to manifest
ir := bytes.NewReader([]byte(img.Name()))
idesc, err := writeContent(ctx, c.client.ContentStore(), images.MediaTypeContainerd1CheckpointImageName, info.ID+"-image-name", ir)
if err != nil {
return nil, err
}
idesc.Platform = &ocispec.Platform{
OS: runtime.GOOS,
Architecture: runtime.GOARCH,
}
index.Manifests = append(index.Manifests, idesc)
// add runtime info to index
rr := bytes.NewReader([]byte(info.Runtime.Name))
rdesc, err := writeContent(ctx, c.client.ContentStore(), images.MediaTypeContainerd1CheckpointRuntimeName, info.ID+"-runtime-name", rr)
if err != nil {
return nil, err
}
rdesc.Platform = &ocispec.Platform{
OS: runtime.GOOS,
Architecture: runtime.GOARCH,
}
index.Manifests = append(index.Manifests, rdesc)
if info.Runtime.Options != nil {
data, err := info.Runtime.Options.Marshal()
if err != nil {
return nil, err
}
r := bytes.NewReader(data)
desc, err := writeContent(ctx, c.client.ContentStore(), images.MediaTypeContainerd1CheckpointRuntimeOptions, info.ID+"-runtime-options", r)
if err != nil {
return nil, err
}
desc.Platform = &ocispec.Platform{
OS: runtime.GOOS,
Architecture: runtime.GOARCH,
}
index.Manifests = append(index.Manifests, desc)
}
// process remaining opts
for _, o := range opts {
if err := o(ctx, c.client, &info, index, copts); err != nil {
return nil, err
}
}
desc, err := writeIndex(ctx, index, c.client, c.ID()+"index")
if err != nil {

View File

@ -31,22 +31,54 @@ import (
"github.com/pkg/errors"
)
var (
// ErrCheckpointIndexImageNameNotFound is returned when the checkpoint image name is not present in the index
ErrCheckpointIndexImageNameNotFound = errors.New("image name not present in index")
// ErrCheckpointIndexRuntimeNameNotFound is returned when the checkpoint runtime name is not present in the index
ErrCheckpointIndexRuntimeNameNotFound = errors.New("runtime name not present in index")
)
// RestoreOpts are options to manage the restore operation
type RestoreOpts func(context.Context, string, *Client, Image, *imagespec.Index) ([]NewContainerOpts, error)
// WithRestoreImage restores the image for the container
func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) ([]NewContainerOpts, error) {
store := client.ContentStore()
m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointImageName)
if err != nil {
if err != ErrMediaTypeNotFound {
return nil, err
}
}
imageName := ""
if m != nil {
data, err := content.ReadBlob(ctx, store, *m)
if err != nil {
return nil, err
}
imageName = string(data)
}
i, err := client.GetImage(ctx, imageName)
if err != nil {
return nil, err
}
return []NewContainerOpts{
WithImage(i),
}, nil
}
// WithRestoreRuntime restores the runtime for the container
func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) ([]NewContainerOpts, error) {
runtimeName, ok := index.Annotations["runtime.name"]
if !ok {
return nil, ErrCheckpointIndexRuntimeNameNotFound
store := client.ContentStore()
n, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointRuntimeName)
if err != nil {
if err != ErrMediaTypeNotFound {
return nil, err
}
}
runtimeName := ""
if n != nil {
data, err := content.ReadBlob(ctx, store, *n)
if err != nil {
return nil, err
}
runtimeName = string(data)
}
// restore options if present
m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointRuntimeOptions)
if err != nil {
@ -54,9 +86,9 @@ func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoi
return nil, err
}
}
var options *ptypes.Any
if m != nil {
store := client.ContentStore()
data, err := content.ReadBlob(ctx, store, *m)
if err != nil {
return nil, errors.Wrap(err, "unable to read checkpoint runtime")
@ -98,15 +130,26 @@ func WithRestoreSpec(ctx context.Context, id string, client *Client, checkpoint
// WithRestoreSnapshot restores the snapshot from the checkpoint for the container
func WithRestoreSnapshot(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) ([]NewContainerOpts, error) {
// get image from annotation
imageName, ok := index.Annotations["image.name"]
if !ok {
return nil, ErrCheckpointIndexImageNameNotFound
imageName := ""
store := client.ContentStore()
m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointImageName)
if err != nil {
if err != ErrMediaTypeNotFound {
return nil, err
}
}
i, err := client.Pull(ctx, imageName, WithPullUnpack)
if m != nil {
data, err := content.ReadBlob(ctx, store, *m)
if err != nil {
return nil, err
}
imageName = string(data)
}
i, err := client.GetImage(ctx, imageName)
if err != nil {
return nil, err
}
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
if err != nil {
return nil, err

View File

@ -34,6 +34,8 @@ const (
MediaTypeContainerd1Resource = "application/vnd.containerd.container.resource.tar"
MediaTypeContainerd1RW = "application/vnd.containerd.container.rw.tar"
MediaTypeContainerd1CheckpointConfig = "application/vnd.containerd.container.checkpoint.config.v1+proto"
MediaTypeContainerd1CheckpointImageName = "application/vnd.containerd.container.checkpoint.image.name"
MediaTypeContainerd1CheckpointRuntimeName = "application/vnd.containerd.container.checkpoint.runtime.name"
MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
// Legacy Docker schema1 manifest
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"