cr: support checkpoint/restore without image

support checkpoint without committing a checkpoint dir into a
checkpoint image and restore without untar image into checkpoint
directory. support for both v1 and v2 runtime

Signed-off-by: Ace-Tang <aceapril@126.com>
This commit is contained in:
Ace-Tang
2018-11-23 17:17:58 +08:00
parent fd16bf6d46
commit 6593399e9f
7 changed files with 188 additions and 32 deletions

View File

@@ -41,7 +41,9 @@ import (
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/runtime"
"github.com/containerd/containerd/runtime/linux/runctypes"
"github.com/containerd/containerd/runtime/v2"
"github.com/containerd/containerd/runtime/v2/runc/options"
"github.com/containerd/containerd/services"
"github.com/containerd/typeurl"
ptypes "github.com/gogo/protobuf/types"
@@ -123,11 +125,16 @@ type local struct {
}
func (l *local) Create(ctx context.Context, r *api.CreateTaskRequest, _ ...grpc.CallOption) (*api.CreateTaskResponse, error) {
var (
checkpointPath string
err error
)
if r.Checkpoint != nil {
container, err := l.getContainer(ctx, r.ContainerID)
if err != nil {
return nil, errdefs.ToGRPC(err)
}
checkpointPath, err := getRestorePath(container.Runtime.Name, r.Options)
if err != nil {
return nil, err
}
// jump get checkpointPath from checkpoint image
if checkpointPath != "" && r.Checkpoint != nil {
checkpointPath, err = ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "ctrd-checkpoint")
if err != nil {
return nil, err
@@ -149,10 +156,6 @@ func (l *local) Create(ctx context.Context, r *api.CreateTaskRequest, _ ...grpc.
return nil, err
}
}
container, err := l.getContainer(ctx, r.ContainerID)
if err != nil {
return nil, errdefs.ToGRPC(err)
}
opts := runtime.CreateOpts{
Spec: container.Spec,
IO: runtime.IO{
@@ -478,14 +481,27 @@ func (l *local) Checkpoint(ctx context.Context, r *api.CheckpointTaskRequest, _
if err != nil {
return nil, err
}
image, err := ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "ctd-checkpoint")
image, err := getCheckpointPath(container.Runtime.Name, r.Options)
if err != nil {
return nil, errdefs.ToGRPC(err)
return nil, err
}
checkpointImageExists := false
if image == "" {
checkpointImageExists = true
image, err = ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "ctd-checkpoint")
if err != nil {
return nil, errdefs.ToGRPC(err)
}
defer os.RemoveAll(image)
}
defer os.RemoveAll(image)
if err := t.Checkpoint(ctx, image, r.Options); err != nil {
return nil, errdefs.ToGRPC(err)
}
// do not commit checkpoint image if checkpoint ImagePath is passed,
// return if checkpointImageExists is false
if !checkpointImageExists {
return &api.CheckpointTaskResponse{}, nil
}
// write checkpoint to the content store
tar := archive.Diff(ctx, "", image)
cp, err := l.writeContent(ctx, images.MediaTypeContainerd1Checkpoint, image, tar)
@@ -663,3 +679,71 @@ func (l *local) allRuntimes() (o []runtime.PlatformRuntime) {
o = append(o, l.v2Runtime)
return o
}
// getCheckpointPath only suitable for runc runtime now
func getCheckpointPath(runtime string, option *ptypes.Any) (string, error) {
if option == nil {
return "", nil
}
var checkpointPath string
switch runtime {
case "io.containerd.runc.v1":
v, err := typeurl.UnmarshalAny(option)
if err != nil {
return "", err
}
opts, ok := v.(*options.CheckpointOptions)
if !ok {
return "", fmt.Errorf("invalid task checkpoint option for %s", runtime)
}
checkpointPath = opts.ImagePath
case "io.containerd.runtime.v1.linux":
v, err := typeurl.UnmarshalAny(option)
if err != nil {
return "", err
}
opts, ok := v.(*runctypes.CheckpointOptions)
if !ok {
return "", fmt.Errorf("invalid task checkpoint option for %s", runtime)
}
checkpointPath = opts.ImagePath
}
return checkpointPath, nil
}
// getRestorePath only suitable for runc runtime now
func getRestorePath(runtime string, option *ptypes.Any) (string, error) {
if option == nil {
return "", nil
}
var restorePath string
switch runtime {
case "io.containerd.runc.v1":
v, err := typeurl.UnmarshalAny(option)
if err != nil {
return "", err
}
opts, ok := v.(*options.Options)
if !ok {
return "", fmt.Errorf("invalid task create option for %s", runtime)
}
restorePath = opts.CriuImagePath
case "io.containerd.runtime.v1.linux":
v, err := typeurl.UnmarshalAny(option)
if err != nil {
return "", err
}
opts, ok := v.(*runctypes.CreateOptions)
if !ok {
return "", fmt.Errorf("invalid task create option for %s", runtime)
}
restorePath = opts.CriuImagePath
}
return restorePath, nil
}