mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-04 11:06:21 +00:00
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:
parent
d6c4ca5fe5
commit
72fd6e0c7d
@ -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
|
||||||
|
}
|
||||||
|
102
containerd-shim-v2/create.go
Normal file
102
containerd-shim-v2/create.go
Normal 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
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user