Support custom runtime path when launching tasks

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
This commit is contained in:
Maksym Pavlenko
2021-11-09 13:31:46 -08:00
parent d4f4c1380a
commit 6870f3b1b8
10 changed files with 146 additions and 59 deletions

View File

@@ -20,6 +20,9 @@ import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"sync"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/errdefs"
@@ -31,6 +34,7 @@ import (
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/runtime"
shim_binary "github.com/containerd/containerd/runtime/v2/shim"
"github.com/containerd/containerd/runtime/v2/task"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -199,6 +203,8 @@ type ShimManager struct {
shims *runtime.TaskList
events *exchange.Exchange
containers containers.Store
// runtimePaths is a cache of `runtime names` -> `resolved fs path`
runtimePaths sync.Map
}
// ID of the shim manager
@@ -253,8 +259,13 @@ func (m *ShimManager) startShim(ctx context.Context, bundle *Bundle, id string,
topts = opts.RuntimeOptions
}
runtimePath, err := m.resolveRuntimePath(opts.Runtime)
if err != nil {
return nil, fmt.Errorf("failed to resolve runtime path: %w", err)
}
b := shimBinary(bundle, shimBinaryConfig{
runtime: opts.Runtime,
runtime: runtimePath,
address: m.containerdAddress,
ttrpcAddress: m.containerdTTRPCAddress,
schedCore: m.schedCore,
@@ -276,6 +287,79 @@ func (m *ShimManager) startShim(ctx context.Context, bundle *Bundle, id string,
return shim, nil
}
func (m *ShimManager) resolveRuntimePath(runtime string) (string, error) {
if runtime == "" {
return "", fmt.Errorf("no runtime name")
}
// Custom path to runtime binary
if filepath.IsAbs(runtime) {
// Make sure it exists before returning ok
if _, err := os.Stat(runtime); err != nil {
return "", fmt.Errorf("invalid custom binary path: %w", err)
}
return runtime, nil
}
// Preserve existing logic and resolve runtime path from runtime name.
name := shim_binary.BinaryName(runtime)
if name == "" {
return "", fmt.Errorf("invalid runtime name %s, correct runtime name should be either format like `io.containerd.runc.v1` or a full path to the binary", runtime)
}
if path, ok := m.runtimePaths.Load(name); ok {
return path.(string), nil
}
var (
cmdPath string
lerr error
)
binaryPath := shim_binary.BinaryPath(runtime)
if _, serr := os.Stat(binaryPath); serr == nil {
cmdPath = binaryPath
}
if cmdPath == "" {
if cmdPath, lerr = exec.LookPath(name); lerr != nil {
if eerr, ok := lerr.(*exec.Error); ok {
if eerr.Err == exec.ErrNotFound {
self, err := os.Executable()
if err != nil {
return "", err
}
// Match the calling binaries (containerd) path and see
// if they are side by side. If so, execute the shim
// found there.
testPath := filepath.Join(filepath.Dir(self), name)
if _, serr := os.Stat(testPath); serr == nil {
cmdPath = testPath
}
if cmdPath == "" {
return "", errors.Wrapf(os.ErrNotExist, "runtime %q binary not installed %q", runtime, name)
}
}
}
}
}
cmdPath, err := filepath.Abs(cmdPath)
if err != nil {
return "", err
}
if path, ok := m.runtimePaths.LoadOrStore(name, cmdPath); ok {
// We didn't store cmdPath we loaded an already cached value. Use it.
cmdPath = path.(string)
}
return cmdPath, nil
}
// cleanupShim attempts to properly delete and cleanup shim after error
func (m *ShimManager) cleanupShim(shim *shim) {
dctx, cancel := timeout.WithContext(context.Background(), cleanupTimeout)