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:
parent
ce0673fd7d
commit
147208061c
@ -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,
|
||||
|
97
container.go
97
container.go
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user