shimv2: support runtime config path via annotation

So that user can have per pod runtime config which is easiler
to manage in some cases.

Fixes: #2332
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
Peng Tao 2019-12-02 03:47:25 -08:00
parent 449a3a9a14
commit 1c11fe20ba
4 changed files with 139 additions and 5 deletions

View File

@ -59,7 +59,7 @@ func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest) (*con
return nil, fmt.Errorf("cannot create another sandbox in sandbox: %s", s.sandbox.ID()) return nil, fmt.Errorf("cannot create another sandbox in sandbox: %s", s.sandbox.ID())
} }
_, err := loadRuntimeConfig(s, r) _, err := loadRuntimeConfig(s, r, ociSpec.Annotations)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -147,10 +147,13 @@ func loadSpec(r *taskAPI.CreateTaskRequest) (*specs.Spec, string, error) {
return &ociSpec, bundlePath, nil return &ociSpec, bundlePath, nil
} }
func loadRuntimeConfig(s *service, r *taskAPI.CreateTaskRequest) (*oci.RuntimeConfig, error) { // Config override ordering(high to low):
var configPath string // 1. podsandbox annotation
// 2. shimv2 create task option
if r.Options != nil { // 3. environment
func loadRuntimeConfig(s *service, r *taskAPI.CreateTaskRequest, anno map[string]string) (*oci.RuntimeConfig, error) {
configPath := oci.GetSandboxConfigPath(anno)
if configPath == "" && r.Options != nil {
v, err := typeurl.UnmarshalAny(r.Options) v, err := typeurl.UnmarshalAny(r.Options)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -8,19 +8,24 @@ package containerdshim
import ( import (
"context" "context"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
taskAPI "github.com/containerd/containerd/runtime/v2/task" taskAPI "github.com/containerd/containerd/runtime/v2/task"
crioption "github.com/containerd/cri-containerd/pkg/api/runtimeoptions/v1"
"github.com/containerd/typeurl"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
ktu "github.com/kata-containers/runtime/pkg/katatestutils" ktu "github.com/kata-containers/runtime/pkg/katatestutils"
"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"
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
"github.com/kata-containers/runtime/virtcontainers/pkg/compatoci" "github.com/kata-containers/runtime/virtcontainers/pkg/compatoci"
"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock" "github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
) )
@ -369,3 +374,123 @@ func TestCreateContainerConfigFail(t *testing.T) {
_, err = s.Create(ctx, req) _, err = s.Create(ctx, req)
assert.Error(err) assert.Error(err)
} }
func createAllRuntimeConfigFiles(dir, hypervisor string) (config string, err error) {
if dir == "" {
return "", fmt.Errorf("BUG: need directory")
}
if hypervisor == "" {
return "", fmt.Errorf("BUG: need hypervisor")
}
hypervisorPath := path.Join(dir, "hypervisor")
kernelPath := path.Join(dir, "kernel")
kernelParams := "foo=bar xyz"
imagePath := path.Join(dir, "image")
shimPath := path.Join(dir, "shim")
proxyPath := path.Join(dir, "proxy")
netmonPath := path.Join(dir, "netmon")
logDir := path.Join(dir, "logs")
logPath := path.Join(logDir, "runtime.log")
machineType := "machineType"
disableBlockDevice := true
blockDeviceDriver := "virtio-scsi"
enableIOThreads := true
hotplugVFIOOnRootBus := true
disableNewNetNs := false
sharedFS := "virtio-9p"
configFileOptions := ktu.RuntimeConfigOptions{
Hypervisor: "qemu",
HypervisorPath: hypervisorPath,
KernelPath: kernelPath,
ImagePath: imagePath,
KernelParams: kernelParams,
MachineType: machineType,
ShimPath: shimPath,
ProxyPath: proxyPath,
NetmonPath: netmonPath,
LogPath: logPath,
DisableBlock: disableBlockDevice,
BlockDeviceDriver: blockDeviceDriver,
EnableIOThreads: enableIOThreads,
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
DisableNewNetNs: disableNewNetNs,
SharedFS: sharedFS,
}
runtimeConfigFileData := ktu.MakeRuntimeConfigFileData(configFileOptions)
configPath := path.Join(dir, "runtime.toml")
err = ioutil.WriteFile(configPath, []byte(runtimeConfigFileData), os.FileMode(0640))
if err != nil {
return "", err
}
files := []string{hypervisorPath, kernelPath, imagePath, shimPath, proxyPath}
for _, file := range files {
// create the resource (which must be >0 bytes)
err := ioutil.WriteFile(file, []byte("foo"), os.FileMode(0640))
if err != nil {
return "", err
}
}
return configPath, nil
}
func TestCreateLoadRuntimeConfig(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
config, err := createAllRuntimeConfigFiles(tmpdir, "qemu")
assert.NoError(err)
s := &service{
id: testSandboxID,
ctx: context.Background(),
}
r := &taskAPI.CreateTaskRequest{}
anno := make(map[string]string)
// set all to fake path
fakeConfig := "foobar"
anno[vcAnnotations.SandboxConfigPathKey] = fakeConfig
option := &crioption.Options{ConfigPath: fakeConfig}
r.Options, err = typeurl.MarshalAny(option)
assert.NoError(err)
err = os.Setenv("KATA_CONF_FILE", fakeConfig)
assert.NoError(err)
defer os.Setenv("KATA_CONF_FILE", "")
// fake config should fail
_, err = loadRuntimeConfig(s, r, anno)
assert.Error(err)
// 1. podsandbox annotation
anno[vcAnnotations.SandboxConfigPathKey] = config
_, err = loadRuntimeConfig(s, r, anno)
assert.NoError(err)
anno[vcAnnotations.SandboxConfigPathKey] = ""
// 2. shimv2 create task option
option.ConfigPath = config
r.Options, err = typeurl.MarshalAny(option)
assert.NoError(err)
_, err = loadRuntimeConfig(s, r, anno)
assert.NoError(err)
option.ConfigPath = ""
r.Options, err = typeurl.MarshalAny(option)
assert.NoError(err)
// 3. environment
err = os.Setenv("KATA_CONF_FILE", config)
assert.NoError(err)
_, err = loadRuntimeConfig(s, r, anno)
assert.NoError(err)
}

View File

@ -19,6 +19,8 @@ const (
// ContainerTypeKey is the annotation key to fetch container type. // ContainerTypeKey is the annotation key to fetch container type.
ContainerTypeKey = kataAnnotationsPrefix + "pkg.oci.container_type" ContainerTypeKey = kataAnnotationsPrefix + "pkg.oci.container_type"
SandboxConfigPathKey = kataAnnotationsPrefix + "config_path"
) )
// Annotations related to Hypervisor configuration // Annotations related to Hypervisor configuration

View File

@ -309,6 +309,10 @@ func ContainerType(spec specs.Spec) (vc.ContainerType, error) {
return vc.PodSandbox, nil return vc.PodSandbox, nil
} }
func GetSandboxConfigPath(annotations map[string]string) string {
return annotations[vcAnnotations.SandboxConfigPathKey]
}
// SandboxID determines the sandbox ID related to an OCI configuration. This function // SandboxID determines the sandbox ID related to an OCI configuration. This function
// is expected to be called only when the container type is "PodContainer". // is expected to be called only when the container type is "PodContainer".
func SandboxID(spec specs.Spec) (string, error) { func SandboxID(spec specs.Spec) (string, error) {