mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-03 02:26:37 +00:00
cli: add vm factory management subcommand
Add enable_template option to the config file. When it is set, enable the vm template factory. cache factory cannot be used by kata cli directly because it requires a running daemon to maintain the cache VMs. `kata-runtime factory init` would initialize the vm factory and `kata-runtime factory destroy` would destroy the vm factory. When configured, a vm factory is loaded before creating new sandboxes. Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
parent
a7d888febc
commit
0309e59cf8
@ -62,6 +62,11 @@ type tomlConfig struct {
|
||||
Shim map[string]shim
|
||||
Agent map[string]agent
|
||||
Runtime runtime
|
||||
Factory factory
|
||||
}
|
||||
|
||||
type factory struct {
|
||||
Template bool `toml:"enable_template"`
|
||||
}
|
||||
|
||||
type hypervisor struct {
|
||||
@ -353,6 +358,10 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newFactoryConfig(f factory) (oci.FactoryConfig, error) {
|
||||
return oci.FactoryConfig{Template: f.Template}, nil
|
||||
}
|
||||
|
||||
func newShimConfig(s shim) (vc.ShimConfig, error) {
|
||||
path, err := s.path()
|
||||
if err != nil {
|
||||
@ -423,6 +432,12 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run
|
||||
config.ShimConfig = shConfig
|
||||
}
|
||||
|
||||
fConfig, err := newFactoryConfig(tomlConf.Factory)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", configPath, err)
|
||||
}
|
||||
config.FactoryConfig = fConfig
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -134,6 +134,18 @@ enable_iothreads = @DEFENABLEIOTHREADS@
|
||||
# used for 9p packet payload.
|
||||
#msize_9p = @DEFMSIZE9P@
|
||||
|
||||
[factory]
|
||||
# VM templating support. Once enabled, new VMs are created from template
|
||||
# using vm cloning. They will share the same initial kernel, initramfs and
|
||||
# agent memory by mapping it readonly. It helps speeding up new container
|
||||
# creation and saves a lot of memory if there are many kata containers running
|
||||
# on the same host.
|
||||
#
|
||||
# When disabled, new VMs are created from scratch.
|
||||
#
|
||||
# Default false
|
||||
#enable_template = true
|
||||
|
||||
[proxy.@PROJECT_TYPE@]
|
||||
path = "@PROXYPATH@"
|
||||
|
||||
|
@ -1146,3 +1146,19 @@ func TestUpdateRuntimeConfigurationVMConfig(t *testing.T) {
|
||||
|
||||
assert.Equal(expectedVMConfig, config.VMConfig)
|
||||
}
|
||||
|
||||
func TestUpdateRuntimeConfigurationFactoryConfig(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
config := oci.RuntimeConfig{}
|
||||
expectedFactoryConfig := oci.FactoryConfig{
|
||||
Template: true,
|
||||
}
|
||||
|
||||
tomlConf := tomlConfig{Factory: factory{Template: true}}
|
||||
|
||||
err := updateRuntimeConfig("", tomlConf, &config)
|
||||
assert.NoError(err)
|
||||
|
||||
assert.Equal(expectedFactoryConfig, config.FactoryConfig)
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"strings"
|
||||
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
vf "github.com/kata-containers/runtime/virtcontainers/factory"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@ -106,6 +107,25 @@ func create(containerID, bundlePath, console, pidFilePath string, detach bool,
|
||||
return err
|
||||
}
|
||||
|
||||
if runtimeConfig.FactoryConfig.Template {
|
||||
factoryConfig := vf.Config{
|
||||
Template: true,
|
||||
VMConfig: vc.VMConfig{
|
||||
HypervisorType: runtimeConfig.HypervisorType,
|
||||
HypervisorConfig: runtimeConfig.HypervisorConfig,
|
||||
AgentType: runtimeConfig.AgentType,
|
||||
AgentConfig: runtimeConfig.AgentConfig,
|
||||
},
|
||||
}
|
||||
kataLog.WithField("factory", factoryConfig).Info("load vm factory")
|
||||
f, err := vf.NewFactory(factoryConfig, true)
|
||||
if err != nil {
|
||||
kataLog.WithError(err).Info("load vm factory failed")
|
||||
} else {
|
||||
vci.SetFactory(f)
|
||||
}
|
||||
}
|
||||
|
||||
disableOutput := noNeedForOutput(detach, ociSpec.Process.Terminal)
|
||||
|
||||
var process vc.Process
|
||||
|
98
cli/factory.go
Normal file
98
cli/factory.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
vf "github.com/kata-containers/runtime/virtcontainers/factory"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var factorySubCmds = []cli.Command{
|
||||
initFactoryCommand,
|
||||
destroyFactoryCommand,
|
||||
}
|
||||
|
||||
var factoryCLICommand = cli.Command{
|
||||
Name: "factory",
|
||||
Usage: "manage vm factory",
|
||||
Subcommands: factorySubCmds,
|
||||
Action: func(context *cli.Context) {
|
||||
cli.ShowSubcommandHelp(context)
|
||||
},
|
||||
}
|
||||
|
||||
var initFactoryCommand = cli.Command{
|
||||
Name: "init",
|
||||
Usage: "initialize a VM factory based on kata-runtime configuration",
|
||||
Action: func(context *cli.Context) error {
|
||||
runtimeConfig, ok := context.App.Metadata["runtimeConfig"].(oci.RuntimeConfig)
|
||||
if !ok {
|
||||
return errors.New("invalid runtime config")
|
||||
}
|
||||
|
||||
if runtimeConfig.FactoryConfig.Template {
|
||||
factoryConfig := vf.Config{
|
||||
Template: true,
|
||||
VMConfig: vc.VMConfig{
|
||||
HypervisorType: runtimeConfig.HypervisorType,
|
||||
HypervisorConfig: runtimeConfig.HypervisorConfig,
|
||||
AgentType: runtimeConfig.AgentType,
|
||||
AgentConfig: runtimeConfig.AgentConfig,
|
||||
},
|
||||
}
|
||||
kataLog.WithField("factory", factoryConfig).Info("create vm factory")
|
||||
_, err := vf.NewFactory(factoryConfig, false)
|
||||
if err != nil {
|
||||
kataLog.WithError(err).Error("create vm factory failed")
|
||||
return err
|
||||
}
|
||||
fmt.Println("vm factory initialized")
|
||||
} else {
|
||||
kataLog.Error("vm factory is not enabled")
|
||||
fmt.Println("vm factory is not enabled")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var destroyFactoryCommand = cli.Command{
|
||||
Name: "destroy",
|
||||
Usage: "destroy the VM factory",
|
||||
Action: func(context *cli.Context) error {
|
||||
runtimeConfig, ok := context.App.Metadata["runtimeConfig"].(oci.RuntimeConfig)
|
||||
if !ok {
|
||||
return errors.New("invalid runtime config")
|
||||
}
|
||||
|
||||
if runtimeConfig.FactoryConfig.Template {
|
||||
factoryConfig := vf.Config{
|
||||
Template: true,
|
||||
VMConfig: vc.VMConfig{
|
||||
HypervisorType: runtimeConfig.HypervisorType,
|
||||
HypervisorConfig: runtimeConfig.HypervisorConfig,
|
||||
AgentType: runtimeConfig.AgentType,
|
||||
AgentConfig: runtimeConfig.AgentConfig,
|
||||
},
|
||||
}
|
||||
kataLog.WithField("factory", factoryConfig).Info("load vm factory")
|
||||
f, err := vf.NewFactory(factoryConfig, true)
|
||||
if err != nil {
|
||||
kataLog.WithError(err).Error("load vm factory failed")
|
||||
// ignore error
|
||||
} else {
|
||||
f.CloseFactory()
|
||||
}
|
||||
}
|
||||
fmt.Println("vm factory destroyed")
|
||||
return nil
|
||||
},
|
||||
}
|
117
cli/factory_test.go
Normal file
117
cli/factory_test.go
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
)
|
||||
|
||||
func TestFactoryCLIFunctionNoRuntimeConfig(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
app := cli.NewApp()
|
||||
ctx := cli.NewContext(app, nil, nil)
|
||||
app.Name = "foo"
|
||||
ctx.App.Metadata = map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}
|
||||
|
||||
fn, ok := initFactoryCommand.Action.(func(context *cli.Context) error)
|
||||
assert.True(ok)
|
||||
err := fn(ctx)
|
||||
// no runtime config in the Metadata
|
||||
assert.Error(err)
|
||||
|
||||
fn, ok = destroyFactoryCommand.Action.(func(context *cli.Context) error)
|
||||
assert.True(ok)
|
||||
err = fn(ctx)
|
||||
// no runtime config in the Metadata
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestFactoryCLIFunctionInit(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
set := flag.NewFlagSet("", 0)
|
||||
|
||||
set.String("console-socket", "", "")
|
||||
|
||||
app := cli.NewApp()
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
app.Name = "foo"
|
||||
|
||||
// No template
|
||||
ctx.App.Metadata = map[string]interface{}{
|
||||
"runtimeConfig": runtimeConfig,
|
||||
}
|
||||
fn, ok := initFactoryCommand.Action.(func(context *cli.Context) error)
|
||||
assert.True(ok)
|
||||
err = fn(ctx)
|
||||
assert.Nil(err)
|
||||
|
||||
// With template
|
||||
runtimeConfig.FactoryConfig.Template = true
|
||||
runtimeConfig.HypervisorType = vc.MockHypervisor
|
||||
runtimeConfig.AgentType = vc.NoopAgentType
|
||||
ctx.App.Metadata["runtimeConfig"] = runtimeConfig
|
||||
fn, ok = initFactoryCommand.Action.(func(context *cli.Context) error)
|
||||
assert.True(ok)
|
||||
err = fn(ctx)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestFactoryCLIFunctionDestroy(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
set := flag.NewFlagSet("", 0)
|
||||
|
||||
set.String("console-socket", "", "")
|
||||
|
||||
app := cli.NewApp()
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
app.Name = "foo"
|
||||
|
||||
// No template
|
||||
ctx.App.Metadata = map[string]interface{}{
|
||||
"runtimeConfig": runtimeConfig,
|
||||
}
|
||||
fn, ok := destroyFactoryCommand.Action.(func(context *cli.Context) error)
|
||||
assert.True(ok)
|
||||
err = fn(ctx)
|
||||
assert.Nil(err)
|
||||
|
||||
// With template
|
||||
runtimeConfig.FactoryConfig.Template = true
|
||||
runtimeConfig.HypervisorType = vc.MockHypervisor
|
||||
runtimeConfig.AgentType = vc.NoopAgentType
|
||||
ctx.App.Metadata["runtimeConfig"] = runtimeConfig
|
||||
fn, ok = destroyFactoryCommand.Action.(func(context *cli.Context) error)
|
||||
assert.True(ok)
|
||||
err = fn(ctx)
|
||||
assert.Nil(err)
|
||||
}
|
@ -123,6 +123,7 @@ var runtimeCommands = []cli.Command{
|
||||
// Kata Containers specific extensions
|
||||
kataCheckCLICommand,
|
||||
kataEnvCLICommand,
|
||||
factoryCLICommand,
|
||||
}
|
||||
|
||||
// runtimeBeforeSubcommands is the function to run before command-line
|
||||
|
@ -91,6 +91,12 @@ type CompatOCISpec struct {
|
||||
Process *CompatOCIProcess `json:"process,omitempty"`
|
||||
}
|
||||
|
||||
// FactoryConfig is a structure to set the VM factory configuration.
|
||||
type FactoryConfig struct {
|
||||
// Template enables VM templating support in VM factory.
|
||||
Template bool
|
||||
}
|
||||
|
||||
// RuntimeConfig aggregates all runtime specific settings
|
||||
type RuntimeConfig struct {
|
||||
VMConfig vc.Resources
|
||||
@ -98,6 +104,8 @@ type RuntimeConfig struct {
|
||||
HypervisorType vc.HypervisorType
|
||||
HypervisorConfig vc.HypervisorConfig
|
||||
|
||||
FactoryConfig FactoryConfig
|
||||
|
||||
AgentType vc.AgentType
|
||||
AgentConfig interface{}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user