containerd-shim-kata-v2: add the create service support

Add the "Create" api support for creating a pod
or container.

Signed-off-by: fupan <lifupan@gmail.com>
This commit is contained in:
fupan 2018-11-19 10:15:04 +08:00
parent d6c4ca5fe5
commit 72fd6e0c7d
4 changed files with 202 additions and 3 deletions

View File

@ -10,6 +10,9 @@ import (
"time" "time"
"github.com/containerd/containerd/api/types/task" "github.com/containerd/containerd/api/types/task"
"github.com/containerd/containerd/errdefs"
taskAPI "github.com/containerd/containerd/runtime/v2/task"
vc "github.com/kata-containers/runtime/virtcontainers" vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/pkg/oci" "github.com/kata-containers/runtime/virtcontainers/pkg/oci"
) )
@ -33,3 +36,32 @@ type container struct {
status task.Status status task.Status
terminal bool terminal bool
} }
func newContainer(s *service, r *taskAPI.CreateTaskRequest, containerType vc.ContainerType, spec *oci.CompatOCISpec) (*container, error) {
if r == nil {
return nil, errdefs.ToGRPCf(errdefs.ErrInvalidArgument, " CreateTaskRequest points to nil")
}
// in order to avoid deferencing a nil pointer in test
if spec == nil {
spec = &oci.CompatOCISpec{}
}
c := &container{
s: s,
spec: spec,
id: r.ID,
bundle: r.Bundle,
stdin: r.Stdin,
stdout: r.Stdout,
stderr: r.Stderr,
terminal: r.Terminal,
cType: containerType,
execs: make(map[string]*exec),
status: task.StatusCreated,
exitIOch: make(chan struct{}),
exitCh: make(chan uint32, 1),
time: time.Now(),
}
return c, nil
}

View File

@ -0,0 +1,102 @@
// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
// Copyright (c) 2018 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
package containerdshim
import (
"context"
"fmt"
vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
taskAPI "github.com/containerd/containerd/runtime/v2/task"
"github.com/kata-containers/runtime/pkg/katautils"
"github.com/opencontainers/runtime-spec/specs-go"
)
func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest, netns string,
runtimeConfig *oci.RuntimeConfig) (*container, error) {
detach := !r.Terminal
// Checks the MUST and MUST NOT from OCI runtime specification
bundlePath, err := validBundle(r.ID, r.Bundle)
if err != nil {
return nil, err
}
ociSpec, err := oci.ParseConfigJSON(bundlePath)
if err != nil {
return nil, err
}
containerType, err := ociSpec.ContainerType()
if err != nil {
return nil, err
}
// Todo:
// Since there is a bug in kata for sharedPidNs, here to
// remove the pidns to disable the sharePidNs temporarily,
// once kata fixed this issue, we can remove this line.
// For the bug, please see:
// https://github.com/kata-containers/runtime/issues/930
removeNamespace(&ociSpec, specs.PIDNamespace)
//set the network namespace path
//this set will be applied to sandbox's
//network config and has nothing to
//do with containers in the sandbox since
//networkNamespace has been ignored by
//kata-agent in sandbox.
for _, n := range ociSpec.Linux.Namespaces {
if n.Type != specs.NetworkNamespace {
continue
}
if n.Path == "" {
n.Path = netns
}
}
katautils.HandleFactory(ctx, vci, runtimeConfig)
disableOutput := noNeedForOutput(detach, ociSpec.Process.Terminal)
switch containerType {
case vc.PodSandbox:
if s.sandbox != nil {
return nil, fmt.Errorf("cannot create another sandbox in sandbox: %s", s.sandbox.ID())
}
sandbox, _, err := katautils.CreateSandbox(ctx, vci, ociSpec, *runtimeConfig, r.ID, bundlePath, "", disableOutput, false, true)
if err != nil {
return nil, err
}
s.sandbox = sandbox
case vc.PodContainer:
if s.sandbox == nil {
return nil, fmt.Errorf("BUG: Cannot start the container, since the sandbox hasn't been created")
}
_, err = katautils.CreateContainer(ctx, vci, s.sandbox, ociSpec, r.ID, bundlePath, "", disableOutput, true)
if err != nil {
return nil, err
}
}
container, err := newContainer(s, r, containerType, &ociSpec)
if err != nil {
return nil, err
}
return container, nil
}

View File

@ -8,6 +8,7 @@ import (
"context" "context"
"os" "os"
sysexec "os/exec" sysexec "os/exec"
"path/filepath"
"sync" "sync"
"syscall" "syscall"
"time" "time"
@ -15,6 +16,7 @@ import (
eventstypes "github.com/containerd/containerd/api/events" eventstypes "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events" "github.com/containerd/containerd/events"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
cdruntime "github.com/containerd/containerd/runtime" cdruntime "github.com/containerd/containerd/runtime"
cdshim "github.com/containerd/containerd/runtime/v2/shim" cdshim "github.com/containerd/containerd/runtime/v2/shim"
@ -23,7 +25,9 @@ import (
vc "github.com/kata-containers/runtime/virtcontainers" vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/pkg/oci" "github.com/kata-containers/runtime/virtcontainers/pkg/oci"
"github.com/containerd/containerd/api/types/task"
ptypes "github.com/gogo/protobuf/types" ptypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -235,7 +239,46 @@ func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error)
// Create a new sandbox or container with the underlying OCI runtime // Create a new sandbox or container with the underlying OCI runtime
func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *taskAPI.CreateTaskResponse, err error) { func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *taskAPI.CreateTaskResponse, err error) {
return nil, errdefs.ErrNotImplemented s.Lock()
defer s.Unlock()
//the network namespace created by cni plugin
netns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return nil, errors.Wrap(err, "create namespace")
}
rootfs := filepath.Join(r.Bundle, "rootfs")
defer func() {
if err != nil {
if err2 := mount.UnmountAll(rootfs, 0); err2 != nil {
logrus.WithError(err2).Warn("failed to cleanup rootfs mount")
}
}
}()
for _, rm := range r.Rootfs {
m := &mount.Mount{
Type: rm.Type,
Source: rm.Source,
Options: rm.Options,
}
if err := m.Mount(rootfs); err != nil {
return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
}
}
container, err := create(ctx, s, r, netns, s.config)
if err != nil {
return nil, err
}
container.status = task.StatusCreated
s.containers[r.ID] = container
return &taskAPI.CreateTaskResponse{
Pid: s.pid,
}, nil
} }
// Start a process // Start a process

View File

@ -15,9 +15,10 @@ import (
"github.com/kata-containers/runtime/pkg/katautils" "github.com/kata-containers/runtime/pkg/katautils"
vc "github.com/kata-containers/runtime/virtcontainers" vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/pkg/oci" "github.com/kata-containers/runtime/virtcontainers/pkg/oci"
"github.com/opencontainers/runtime-spec/specs-go"
) )
func validCreateParams(containerID, bundlePath string) (string, error) { func validBundle(containerID, bundlePath string) (string, error) {
// container ID MUST be provided. // container ID MUST be provided.
if containerID == "" { if containerID == "" {
return "", fmt.Errorf("Missing container ID") return "", fmt.Errorf("Missing container ID")
@ -49,7 +50,7 @@ func getAddress(ctx context.Context, bundlePath, id string) (string, error) {
var err error var err error
// Checks the MUST and MUST NOT from OCI runtime specification // Checks the MUST and MUST NOT from OCI runtime specification
if bundlePath, err = validCreateParams(id, bundlePath); err != nil { if bundlePath, err = validBundle(id, bundlePath); err != nil {
return "", err return "", err
} }
@ -77,3 +78,24 @@ func getAddress(ctx context.Context, bundlePath, id string) (string, error) {
return "", nil return "", nil
} }
func noNeedForOutput(detach bool, tty bool) bool {
if !detach {
return false
}
if !tty {
return false
}
return true
}
func removeNamespace(s *oci.CompatOCISpec, nsType specs.LinuxNamespaceType) {
for i, n := range s.Linux.Namespaces {
if n.Type == nsType {
s.Linux.Namespaces = append(s.Linux.Namespaces[:i], s.Linux.Namespaces[i+1:]...)
return
}
}
}