From 050f03bb3617b5a718e4963f32d23f7bcc039ec2 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Tue, 5 Feb 2019 23:43:52 +0800 Subject: [PATCH] config: Add config flag "experimental" Fixes #1226 Add new flag "experimental" for supporting underworking features. Some features are under developing which are not ready for release, there're also some features which will break compatibility which is not suitable to be merged into a kata minor release(x version in x.y.z) For getting these features above merged earlier for more testing, we can mark them as "experimental" features, and move them to formal features when they are ready. Signed-off-by: Wei Zhang --- Makefile | 4 ++ cli/config/configuration-fc.toml.in | 8 +++ cli/config/configuration-qemu.toml.in | 8 +++ cli/kata-env.go | 3 + pkg/katautils/config.go | 70 ++++++++++++------- virtcontainers/experimental/experimental.go | 32 +++++++++ .../experimental/experimental_test.go | 26 +++++++ virtcontainers/pkg/oci/utils.go | 6 ++ virtcontainers/sandbox.go | 14 ++++ virtcontainers/sandbox_test.go | 16 +++++ 10 files changed, 163 insertions(+), 24 deletions(-) create mode 100644 virtcontainers/experimental/experimental.go create mode 100644 virtcontainers/experimental/experimental_test.go diff --git a/Makefile b/Makefile index 7340add51..1648e1622 100644 --- a/Makefile +++ b/Makefile @@ -157,6 +157,8 @@ DEFMEMSLOTS := 10 #Default number of bridges DEFBRIDGES := 1 DEFDISABLEGUESTSECCOMP := true +#Default experimental features enabled +DEFAULTEXPFEATURES := [] #Default entropy source DEFENTROPYSOURCE := /dev/urandom @@ -314,6 +316,7 @@ USER_VARS += DEFBRIDGES USER_VARS += DEFNETWORKMODEL_FC USER_VARS += DEFNETWORKMODEL_QEMU USER_VARS += DEFDISABLEGUESTSECCOMP +USER_VARS += DEFAULTEXPFEATURES USER_VARS += DEFDISABLEBLOCK USER_VARS += DEFBLOCKSTORAGEDRIVER_FC USER_VARS += DEFBLOCKSTORAGEDRIVER_QEMU @@ -503,6 +506,7 @@ $(GENERATED_FILES): %: %.in Makefile VERSION -e "s|@DEFNETWORKMODEL_FC@|$(DEFNETWORKMODEL_FC)|g" \ -e "s|@DEFNETWORKMODEL_QEMU@|$(DEFNETWORKMODEL_QEMU)|g" \ -e "s|@DEFDISABLEGUESTSECCOMP@|$(DEFDISABLEGUESTSECCOMP)|g" \ + -e "s|@DEFAULTEXPFEATURES@|$(DEFAULTEXPFEATURES)|g" \ -e "s|@DEFDISABLEBLOCK@|$(DEFDISABLEBLOCK)|g" \ -e "s|@DEFBLOCKSTORAGEDRIVER_FC@|$(DEFBLOCKSTORAGEDRIVER_FC)|g" \ -e "s|@DEFBLOCKSTORAGEDRIVER_QEMU@|$(DEFBLOCKSTORAGEDRIVER_QEMU)|g" \ diff --git a/cli/config/configuration-fc.toml.in b/cli/config/configuration-fc.toml.in index 6894b19c1..07dc190b6 100644 --- a/cli/config/configuration-fc.toml.in +++ b/cli/config/configuration-fc.toml.in @@ -289,3 +289,11 @@ disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@ # If you are using docker, `disable_new_netns` only works with `docker run --net=none` # (default: false) #disable_new_netns = true + +# Enabled experimental feature list, format: ["a", "b"]. +# Experimental features are features not stable enough for production, +# They may break compatibility, and are prepared for a big version bump. +# Supported experimental features: +# 1. "newstore": new persist storage driver +# (default: []) +experimental=@DEFAULTEXPFEATURES@ diff --git a/cli/config/configuration-qemu.toml.in b/cli/config/configuration-qemu.toml.in index f655136bf..52d9a974a 100644 --- a/cli/config/configuration-qemu.toml.in +++ b/cli/config/configuration-qemu.toml.in @@ -336,3 +336,11 @@ disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@ # If you are using docker, `disable_new_netns` only works with `docker run --net=none` # (default: false) #disable_new_netns = true + +# Enabled experimental feature list, format: ["a", "b"]. +# Experimental features are features not stable enough for production, +# They may break compatibility, and are prepared for a big version bump. +# Supported experimental features: +# 1. "newstore": new persist storage driver +# (default: []) +experimental=@DEFAULTEXPFEATURES@ diff --git a/cli/kata-env.go b/cli/kata-env.go index 8bf2d0576..4a66b1921 100644 --- a/cli/kata-env.go +++ b/cli/kata-env.go @@ -16,6 +16,7 @@ import ( "github.com/BurntSushi/toml" "github.com/kata-containers/runtime/pkg/katautils" vc "github.com/kata-containers/runtime/virtcontainers" + exp "github.com/kata-containers/runtime/virtcontainers/experimental" "github.com/kata-containers/runtime/virtcontainers/pkg/oci" vcUtils "github.com/kata-containers/runtime/virtcontainers/utils" specs "github.com/opencontainers/runtime-spec/specs-go" @@ -69,6 +70,7 @@ type RuntimeInfo struct { Trace bool DisableGuestSeccomp bool DisableNewNetNs bool + Experimental []exp.Feature Path string } @@ -181,6 +183,7 @@ func getRuntimeInfo(configFile string, config oci.RuntimeConfig) RuntimeInfo { Config: runtimeConfig, Path: runtimePath, DisableNewNetNs: config.DisableNewNetNs, + Experimental: config.Experimental, DisableGuestSeccomp: config.DisableGuestSeccomp, } } diff --git a/pkg/katautils/config.go b/pkg/katautils/config.go index a5145ec16..57b617f1b 100644 --- a/pkg/katautils/config.go +++ b/pkg/katautils/config.go @@ -16,6 +16,7 @@ import ( "github.com/BurntSushi/toml" vc "github.com/kata-containers/runtime/virtcontainers" "github.com/kata-containers/runtime/virtcontainers/device/config" + exp "github.com/kata-containers/runtime/virtcontainers/experimental" "github.com/kata-containers/runtime/virtcontainers/pkg/oci" "github.com/kata-containers/runtime/virtcontainers/utils" "github.com/sirupsen/logrus" @@ -122,11 +123,12 @@ type proxy struct { } type runtime struct { - Debug bool `toml:"enable_debug"` - Tracing bool `toml:"enable_tracing"` - DisableNewNetNs bool `toml:"disable_new_netns"` - DisableGuestSeccomp bool `toml:"disable_guest_seccomp"` - InterNetworkModel string `toml:"internetworking_model"` + Debug bool `toml:"enable_debug"` + Tracing bool `toml:"enable_tracing"` + DisableNewNetNs bool `toml:"disable_new_netns"` + DisableGuestSeccomp bool `toml:"disable_guest_seccomp"` + Experimental []string `toml:"experimental"` + InterNetworkModel string `toml:"internetworking_model"` } type shim struct { @@ -800,32 +802,15 @@ func initConfig() (config oci.RuntimeConfig, err error) { // All paths are resolved fully meaning if this function does not return an // error, all paths are valid at the time of the call. func LoadConfiguration(configPath string, ignoreLogging, builtIn bool) (resolvedConfigPath string, config oci.RuntimeConfig, err error) { - var resolved string config, err = initConfig() if err != nil { return "", oci.RuntimeConfig{}, err } - if configPath == "" { - resolved, err = getDefaultConfigFile() - } else { - resolved, err = ResolvePath(configPath) - } - + tomlConf, resolved, err := decodeConfig(configPath) if err != nil { - return "", config, fmt.Errorf("Cannot find usable config file (%v)", err) - } - - configData, err := ioutil.ReadFile(resolved) - if err != nil { - return "", config, err - } - - var tomlConf tomlConfig - _, err = toml.Decode(string(configData), &tomlConf) - if err != nil { - return "", config, err + return "", oci.RuntimeConfig{}, err } config.Debug = tomlConf.Runtime.Debug @@ -872,6 +857,13 @@ func LoadConfiguration(configPath string, ignoreLogging, builtIn bool) (resolved } config.DisableNewNetNs = tomlConf.Runtime.DisableNewNetNs + for _, f := range tomlConf.Runtime.Experimental { + feature := exp.Feature(f) + if !exp.Supported(feature) { + return "", config, fmt.Errorf("Unsupported experimental feature %q", f) + } + config.Experimental = append(config.Experimental, feature) + } if err := checkConfig(config); err != nil { return "", config, err @@ -880,6 +872,36 @@ func LoadConfiguration(configPath string, ignoreLogging, builtIn bool) (resolved return resolved, config, nil } +func decodeConfig(configPath string) (tomlConfig, string, error) { + var ( + resolved string + tomlConf tomlConfig + err error + ) + + if configPath == "" { + resolved, err = getDefaultConfigFile() + } else { + resolved, err = ResolvePath(configPath) + } + + if err != nil { + return tomlConf, "", fmt.Errorf("Cannot find usable config file (%v)", err) + } + + configData, err := ioutil.ReadFile(resolved) + if err != nil { + return tomlConf, resolved, err + } + + _, err = toml.Decode(string(configData), &tomlConf) + if err != nil { + return tomlConf, resolved, err + } + + return tomlConf, resolved, nil +} + // checkConfig checks the validity of the specified config. func checkConfig(config oci.RuntimeConfig) error { if err := checkNetNsConfig(config); err != nil { diff --git a/virtcontainers/experimental/experimental.go b/virtcontainers/experimental/experimental.go new file mode 100644 index 000000000..de208b71c --- /dev/null +++ b/virtcontainers/experimental/experimental.go @@ -0,0 +1,32 @@ +// Copyright (c) 2019 Huawei Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package experimental + +import ( + "fmt" +) + +// Feature to be experimental +type Feature string + +var ( + supportedFeatures = make(map[Feature]struct{}) +) + +// Register register a new experimental feature +func Register(feature Feature) error { + if _, ok := supportedFeatures[feature]; ok { + return fmt.Errorf("Feature %q had been registered before", feature) + } + supportedFeatures[feature] = struct{}{} + return nil +} + +// Supported check if the feature is supported +func Supported(feature Feature) bool { + _, ok := supportedFeatures[feature] + return ok +} diff --git a/virtcontainers/experimental/experimental_test.go b/virtcontainers/experimental/experimental_test.go new file mode 100644 index 000000000..1c24c0738 --- /dev/null +++ b/virtcontainers/experimental/experimental_test.go @@ -0,0 +1,26 @@ +// Copyright (c) 2019 Huawei Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package experimental + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestExperimental(t *testing.T) { + f := Feature("mock") + assert.False(t, Supported(f)) + + err := Register("mock") + assert.Nil(t, err) + + err = Register("mock") + assert.NotNil(t, err) + assert.Equal(t, len(supportedFeatures), 1) + + assert.True(t, Supported(f)) +} diff --git a/virtcontainers/pkg/oci/utils.go b/virtcontainers/pkg/oci/utils.go index 269edc962..cefa8f90f 100644 --- a/virtcontainers/pkg/oci/utils.go +++ b/virtcontainers/pkg/oci/utils.go @@ -23,6 +23,7 @@ import ( vc "github.com/kata-containers/runtime/virtcontainers" "github.com/kata-containers/runtime/virtcontainers/device/config" + exp "github.com/kata-containers/runtime/virtcontainers/experimental" vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations" dockershimAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations/dockershim" "github.com/kata-containers/runtime/virtcontainers/types" @@ -134,6 +135,9 @@ type RuntimeConfig struct { //Determines if create a netns for hypervisor process DisableNewNetNs bool + + //Experimental features enabled + Experimental []exp.Feature } // AddKernelParam allows the addition of new kernel parameters to an existing @@ -500,6 +504,8 @@ func SandboxConfig(ocispec CompatOCISpec, runtime RuntimeConfig, bundlePath, cid SystemdCgroup: systemdCgroup, DisableGuestSeccomp: runtime.DisableGuestSeccomp, + + Experimental: runtime.Experimental, } addAssetAnnotations(ocispec, &sandboxConfig) diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index 630f282f4..851145fb7 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -25,6 +25,7 @@ import ( "github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/drivers" deviceManager "github.com/kata-containers/runtime/virtcontainers/device/manager" + exp "github.com/kata-containers/runtime/virtcontainers/experimental" "github.com/kata-containers/runtime/virtcontainers/pkg/annotations" vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" "github.com/kata-containers/runtime/virtcontainers/store" @@ -100,6 +101,9 @@ type SandboxConfig struct { SystemdCgroup bool DisableGuestSeccomp bool + + // Experimental features enabled + Experimental []exp.Feature } func (s *Sandbox) trace(name string) (opentracing.Span, context.Context) { @@ -136,6 +140,12 @@ func (sandboxConfig *SandboxConfig) valid() bool { sandboxConfig.HypervisorType = QemuHypervisor } + // validate experimental features + for _, f := range sandboxConfig.Experimental { + if !exp.Supported(f) { + return false + } + } return true } @@ -439,6 +449,10 @@ func createSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Fac return nil, err } + if len(s.config.Experimental) != 0 { + s.Logger().WithField("features", s.config.Experimental).Infof("Enable experimental features") + } + // Fetch sandbox network to be able to access it from the sandbox structure. var networkNS NetworkNamespace if err := s.store.Load(store.Network, &networkNS); err == nil { diff --git a/virtcontainers/sandbox_test.go b/virtcontainers/sandbox_test.go index f9d78cce4..45b6f7a23 100644 --- a/virtcontainers/sandbox_test.go +++ b/virtcontainers/sandbox_test.go @@ -22,6 +22,7 @@ import ( "github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/drivers" "github.com/kata-containers/runtime/virtcontainers/device/manager" + exp "github.com/kata-containers/runtime/virtcontainers/experimental" "github.com/kata-containers/runtime/virtcontainers/pkg/annotations" "github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/types" @@ -1680,3 +1681,18 @@ func TestSandboxUpdateResources(t *testing.T) { t.Fatal(err) } } + +func TestSandboxExperimentalFeature(t *testing.T) { + testFeature := exp.Feature("mock") + sconfig := SandboxConfig{ + ID: testSandboxID, + Experimental: []exp.Feature{testFeature}, + } + + assert.False(t, exp.Supported(testFeature)) + assert.False(t, sconfig.valid()) + + exp.Register(testFeature) + assert.True(t, exp.Supported(testFeature)) + assert.True(t, sconfig.valid()) +}