Files
kata-containers/pkg/katautils/config.go
Hui Zhu 42a89d0dcd katautils: Move SetKernelParams from CreateSandbox to updateRuntimeConfig
Function SetKernelParams is just to update the runtimeConfig according to itself.
It just around the configuration.
So this patch moves it to updateRuntimeConfig.

Fixes: #1106

Signed-off-by: Hui Zhu <teawater@hyper.sh>
2019-01-11 08:25:42 +08:00

1037 lines
26 KiB
Go

// Copyright (c) 2018 Intel Corporation
// Copyright (c) 2018 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
package katautils
import (
"errors"
"fmt"
"io/ioutil"
goruntime "runtime"
"strings"
"github.com/BurntSushi/toml"
vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
"github.com/kata-containers/runtime/virtcontainers/utils"
"github.com/sirupsen/logrus"
)
const (
defaultHypervisor = vc.QemuHypervisor
defaultAgent = vc.KataContainersAgent
)
var (
defaultProxy = vc.KataProxyType
defaultShim = vc.KataShimType
// if true, enable opentracing support.
tracing = false
)
// The TOML configuration file contains a number of sections (or
// tables). The names of these tables are in dotted ("nested table")
// form:
//
// [<component>.<type>]
//
// The components are hypervisor, proxy, shim and agent. For example,
//
// [proxy.kata]
//
// The currently supported types are listed below:
const (
// supported hypervisor component types
firecrackerHypervisorTableType = "firecracker"
qemuHypervisorTableType = "qemu"
// supported proxy component types
ccProxyTableType = "cc"
kataProxyTableType = "kata"
// supported shim component types
ccShimTableType = "cc"
kataShimTableType = "kata"
// supported agent component types
hyperstartAgentTableType = "hyperstart"
kataAgentTableType = "kata"
// the maximum amount of PCI bridges that can be cold plugged in a VM
maxPCIBridges uint32 = 5
)
type tomlConfig struct {
Hypervisor map[string]hypervisor
Proxy map[string]proxy
Shim map[string]shim
Agent map[string]agent
Runtime runtime
Factory factory
Netmon netmon
}
type factory struct {
Template bool `toml:"enable_template"`
}
type hypervisor struct {
Path string `toml:"path"`
Kernel string `toml:"kernel"`
Initrd string `toml:"initrd"`
Image string `toml:"image"`
Firmware string `toml:"firmware"`
MachineAccelerators string `toml:"machine_accelerators"`
KernelParams string `toml:"kernel_params"`
MachineType string `toml:"machine_type"`
BlockDeviceDriver string `toml:"block_device_driver"`
EntropySource string `toml:"entropy_source"`
BlockDeviceCacheSet bool `toml:"block_device_cache_set"`
BlockDeviceCacheDirect bool `toml:"block_device_cache_direct"`
BlockDeviceCacheNoflush bool `toml:"block_device_cache_noflush"`
NumVCPUs int32 `toml:"default_vcpus"`
DefaultMaxVCPUs uint32 `toml:"default_maxvcpus"`
MemorySize uint32 `toml:"default_memory"`
MemSlots uint32 `toml:"memory_slots"`
MemOffset uint32 `toml:"memory_offset"`
DefaultBridges uint32 `toml:"default_bridges"`
Msize9p uint32 `toml:"msize_9p"`
DisableBlockDeviceUse bool `toml:"disable_block_device_use"`
MemPrealloc bool `toml:"enable_mem_prealloc"`
HugePages bool `toml:"enable_hugepages"`
Swap bool `toml:"enable_swap"`
Debug bool `toml:"enable_debug"`
DisableNestingChecks bool `toml:"disable_nesting_checks"`
EnableIOThreads bool `toml:"enable_iothreads"`
UseVSock bool `toml:"use_vsock"`
HotplugVFIOOnRootBus bool `toml:"hotplug_vfio_on_root_bus"`
DisableVhostNet bool `toml:"disable_vhost_net"`
GuestHookPath string `toml:"guest_hook_path"`
}
type proxy struct {
Path string `toml:"path"`
Debug bool `toml:"enable_debug"`
}
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"`
}
type shim struct {
Path string `toml:"path"`
Debug bool `toml:"enable_debug"`
Tracing bool `toml:"enable_tracing"`
}
type agent struct {
}
type netmon struct {
Path string `toml:"path"`
Debug bool `toml:"enable_debug"`
Enable bool `toml:"enable_netmon"`
}
func (h hypervisor) path() (string, error) {
p := h.Path
if h.Path == "" {
p = defaultHypervisorPath
}
return ResolvePath(p)
}
func (h hypervisor) kernel() (string, error) {
p := h.Kernel
if p == "" {
p = defaultKernelPath
}
return ResolvePath(p)
}
func (h hypervisor) initrd() (string, error) {
p := h.Initrd
if p == "" {
return "", nil
}
return ResolvePath(p)
}
func (h hypervisor) image() (string, error) {
p := h.Image
if p == "" {
return "", nil
}
return ResolvePath(p)
}
func (h hypervisor) firmware() (string, error) {
p := h.Firmware
if p == "" {
if defaultFirmwarePath == "" {
return "", nil
}
p = defaultFirmwarePath
}
return ResolvePath(p)
}
func (h hypervisor) machineAccelerators() string {
var machineAccelerators string
accelerators := strings.Split(h.MachineAccelerators, ",")
acceleratorsLen := len(accelerators)
for i := 0; i < acceleratorsLen; i++ {
if accelerators[i] != "" {
machineAccelerators += strings.Trim(accelerators[i], "\r\t\n ") + ","
}
}
machineAccelerators = strings.Trim(machineAccelerators, ",")
return machineAccelerators
}
func (h hypervisor) kernelParams() string {
if h.KernelParams == "" {
return defaultKernelParams
}
return h.KernelParams
}
func (h hypervisor) machineType() string {
if h.MachineType == "" {
return defaultMachineType
}
return h.MachineType
}
func (h hypervisor) GetEntropySource() string {
if h.EntropySource == "" {
return defaultEntropySource
}
return h.EntropySource
}
func (h hypervisor) defaultVCPUs() uint32 {
numCPUs := goruntime.NumCPU()
if h.NumVCPUs < 0 || h.NumVCPUs > int32(numCPUs) {
return uint32(numCPUs)
}
if h.NumVCPUs == 0 { // or unspecified
return defaultVCPUCount
}
return uint32(h.NumVCPUs)
}
func (h hypervisor) defaultMaxVCPUs() uint32 {
numcpus := uint32(goruntime.NumCPU())
maxvcpus := vc.MaxQemuVCPUs()
reqVCPUs := h.DefaultMaxVCPUs
//don't exceed the number of physical CPUs. If a default is not provided, use the
// numbers of physical CPUs
if reqVCPUs >= numcpus || reqVCPUs == 0 {
reqVCPUs = numcpus
}
// Don't exceed the maximum number of vCPUs supported by hypervisor
if reqVCPUs > maxvcpus {
return maxvcpus
}
return reqVCPUs
}
func (h hypervisor) defaultMemSz() uint32 {
if h.MemorySize < 8 {
return defaultMemSize // MiB
}
return h.MemorySize
}
func (h hypervisor) defaultMemSlots() uint32 {
slots := h.MemSlots
if slots == 0 {
slots = defaultMemSlots
}
return slots
}
func (h hypervisor) defaultMemOffset() uint32 {
offset := h.MemOffset
if offset == 0 {
offset = defaultMemOffset
}
return offset
}
func (h hypervisor) defaultBridges() uint32 {
if h.DefaultBridges == 0 {
return defaultBridgesCount
}
if h.DefaultBridges > maxPCIBridges {
return maxPCIBridges
}
return h.DefaultBridges
}
func (h hypervisor) blockDeviceDriver() (string, error) {
supportedBlockDrivers := []string{config.VirtioSCSI, config.VirtioBlock, config.VirtioMmio, config.Nvdimm}
if h.BlockDeviceDriver == "" {
return defaultBlockDeviceDriver, nil
}
for _, b := range supportedBlockDrivers {
if b == h.BlockDeviceDriver {
return h.BlockDeviceDriver, nil
}
}
return "", fmt.Errorf("Invalid hypervisor block storage driver %v specified (supported drivers: %v)", h.BlockDeviceDriver, supportedBlockDrivers)
}
func (h hypervisor) msize9p() uint32 {
if h.Msize9p == 0 {
return defaultMsize9p
}
return h.Msize9p
}
func (h hypervisor) useVSock() bool {
return h.UseVSock
}
func (h hypervisor) guestHookPath() string {
if h.GuestHookPath == "" {
return defaultGuestHookPath
}
return h.GuestHookPath
}
func (h hypervisor) getInitrdAndImage() (initrd string, image string, err error) {
if initrd, err = h.initrd(); err != nil {
return
}
if image, err = h.image(); err != nil {
return
}
if image != "" && initrd != "" {
return "", "", errors.New("having both an image and an initrd defined in the configuration file is not supported")
}
if image == "" && initrd == "" {
return "", "", errors.New("either image or initrd must be defined in the configuration file")
}
return
}
func (p proxy) path() string {
if p.Path == "" {
return defaultProxyPath
}
return p.Path
}
func (p proxy) debug() bool {
return p.Debug
}
func (s shim) path() (string, error) {
p := s.Path
if p == "" {
p = defaultShimPath
}
return ResolvePath(p)
}
func (s shim) debug() bool {
return s.Debug
}
func (s shim) trace() bool {
return s.Tracing
}
func (n netmon) enable() bool {
return n.Enable
}
func (n netmon) path() string {
if n.Path == "" {
return defaultNetmonPath
}
return n.Path
}
func (n netmon) debug() bool {
return n.Debug
}
func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
hypervisor, err := h.path()
if err != nil {
return vc.HypervisorConfig{}, err
}
kernel, err := h.kernel()
if err != nil {
return vc.HypervisorConfig{}, err
}
initrd, image, err := h.getInitrdAndImage()
if err != nil {
return vc.HypervisorConfig{}, err
}
firmware, err := h.firmware()
if err != nil {
return vc.HypervisorConfig{}, err
}
kernelParams := h.kernelParams()
blockDriver, err := h.blockDeviceDriver()
if err != nil {
return vc.HypervisorConfig{}, err
}
if !utils.SupportsVsocks() {
return vc.HypervisorConfig{}, errors.New("No vsock support, firecracker cannot be used")
}
return vc.HypervisorConfig{
HypervisorPath: hypervisor,
KernelPath: kernel,
InitrdPath: initrd,
ImagePath: image,
FirmwarePath: firmware,
KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)),
NumVCPUs: h.defaultVCPUs(),
DefaultMaxVCPUs: h.defaultMaxVCPUs(),
MemorySize: h.defaultMemSz(),
MemSlots: h.defaultMemSlots(),
EntropySource: h.GetEntropySource(),
DefaultBridges: h.defaultBridges(),
DisableBlockDeviceUse: h.DisableBlockDeviceUse,
HugePages: h.HugePages,
Mlock: !h.Swap,
Debug: h.Debug,
DisableNestingChecks: h.DisableNestingChecks,
BlockDeviceDriver: blockDriver,
EnableIOThreads: h.EnableIOThreads,
UseVSock: true,
GuestHookPath: h.guestHookPath(),
}, nil
}
func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
hypervisor, err := h.path()
if err != nil {
return vc.HypervisorConfig{}, err
}
kernel, err := h.kernel()
if err != nil {
return vc.HypervisorConfig{}, err
}
initrd, image, err := h.getInitrdAndImage()
if err != nil {
return vc.HypervisorConfig{}, err
}
if image != "" && initrd != "" {
return vc.HypervisorConfig{},
errors.New("having both an image and an initrd defined in the configuration file is not supported")
}
if image == "" && initrd == "" {
return vc.HypervisorConfig{},
errors.New("either image or initrd must be defined in the configuration file")
}
firmware, err := h.firmware()
if err != nil {
return vc.HypervisorConfig{}, err
}
machineAccelerators := h.machineAccelerators()
kernelParams := h.kernelParams()
machineType := h.machineType()
blockDriver, err := h.blockDeviceDriver()
if err != nil {
return vc.HypervisorConfig{}, err
}
useVSock := false
if h.useVSock() {
if utils.SupportsVsocks() {
kataUtilsLogger.Info("vsock supported")
useVSock = true
} else {
kataUtilsLogger.Warn("No vsock support, falling back to legacy serial port")
}
}
return vc.HypervisorConfig{
HypervisorPath: hypervisor,
KernelPath: kernel,
InitrdPath: initrd,
ImagePath: image,
FirmwarePath: firmware,
MachineAccelerators: machineAccelerators,
KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)),
HypervisorMachineType: machineType,
NumVCPUs: h.defaultVCPUs(),
DefaultMaxVCPUs: h.defaultMaxVCPUs(),
MemorySize: h.defaultMemSz(),
MemSlots: h.defaultMemSlots(),
MemOffset: h.defaultMemOffset(),
EntropySource: h.GetEntropySource(),
DefaultBridges: h.defaultBridges(),
DisableBlockDeviceUse: h.DisableBlockDeviceUse,
MemPrealloc: h.MemPrealloc,
HugePages: h.HugePages,
Mlock: !h.Swap,
Debug: h.Debug,
DisableNestingChecks: h.DisableNestingChecks,
BlockDeviceDriver: blockDriver,
BlockDeviceCacheSet: h.BlockDeviceCacheSet,
BlockDeviceCacheDirect: h.BlockDeviceCacheDirect,
BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush,
EnableIOThreads: h.EnableIOThreads,
Msize9p: h.msize9p(),
UseVSock: useVSock,
HotplugVFIOOnRootBus: h.HotplugVFIOOnRootBus,
DisableVhostNet: h.DisableVhostNet,
GuestHookPath: h.guestHookPath(),
}, 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 {
return vc.ShimConfig{}, err
}
return vc.ShimConfig{
Path: path,
Debug: s.debug(),
Trace: s.trace(),
}, nil
}
func updateRuntimeConfigHypervisor(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
for k, hypervisor := range tomlConf.Hypervisor {
var err error
var hConfig vc.HypervisorConfig
switch k {
case firecrackerHypervisorTableType:
config.HypervisorType = vc.FirecrackerHypervisor
hConfig, err = newFirecrackerHypervisorConfig(hypervisor)
case qemuHypervisorTableType:
config.HypervisorType = vc.QemuHypervisor
hConfig, err = newQemuHypervisorConfig(hypervisor)
}
if err != nil {
return fmt.Errorf("%v: %v", configPath, err)
}
config.HypervisorConfig = hConfig
}
return nil
}
func updateRuntimeConfigProxy(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
for k, proxy := range tomlConf.Proxy {
switch k {
case ccProxyTableType:
config.ProxyType = vc.CCProxyType
case kataProxyTableType:
config.ProxyType = vc.KataProxyType
}
config.ProxyConfig = vc.ProxyConfig{
Path: proxy.path(),
Debug: proxy.debug(),
}
}
return nil
}
func updateRuntimeConfigAgent(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
for k := range tomlConf.Agent {
switch k {
case hyperstartAgentTableType:
config.AgentType = hyperstartAgentTableType
config.AgentConfig = vc.HyperConfig{}
case kataAgentTableType:
config.AgentType = kataAgentTableType
config.AgentConfig = vc.KataAgentConfig{
UseVSock: config.HypervisorConfig.UseVSock,
}
}
}
return nil
}
func updateRuntimeConfigShim(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
for k, shim := range tomlConf.Shim {
switch k {
case ccShimTableType:
config.ShimType = vc.CCShimType
case kataShimTableType:
config.ShimType = vc.KataShimType
}
shConfig, err := newShimConfig(shim)
if err != nil {
return fmt.Errorf("%v: %v", configPath, err)
}
config.ShimConfig = shConfig
}
return nil
}
// SetKernelParams adds the user-specified kernel parameters (from the
// configuration file) to the defaults so that the former take priority.
func SetKernelParams(runtimeConfig *oci.RuntimeConfig) error {
defaultKernelParams := GetKernelParamsFunc(needSystemd(runtimeConfig.HypervisorConfig))
if runtimeConfig.HypervisorConfig.Debug {
strParams := vc.SerializeParams(defaultKernelParams, "=")
formatted := strings.Join(strParams, " ")
kataUtilsLogger.WithField("default-kernel-parameters", formatted).Debug()
}
// retrieve the parameters specified in the config file
userKernelParams := runtimeConfig.HypervisorConfig.KernelParams
// reset
runtimeConfig.HypervisorConfig.KernelParams = []vc.Param{}
// first, add default values
for _, p := range defaultKernelParams {
if err := (runtimeConfig).AddKernelParam(p); err != nil {
return err
}
}
// now re-add the user-specified values so that they take priority.
for _, p := range userKernelParams {
if err := (runtimeConfig).AddKernelParam(p); err != nil {
return err
}
}
return nil
}
func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
if err := updateRuntimeConfigHypervisor(configPath, tomlConf, config); err != nil {
return err
}
if err := updateRuntimeConfigProxy(configPath, tomlConf, config); err != nil {
return err
}
if err := updateRuntimeConfigAgent(configPath, tomlConf, config); err != nil {
return err
}
if err := updateRuntimeConfigShim(configPath, tomlConf, config); err != nil {
return err
}
fConfig, err := newFactoryConfig(tomlConf.Factory)
if err != nil {
return fmt.Errorf("%v: %v", configPath, err)
}
config.FactoryConfig = fConfig
config.NetmonConfig = vc.NetmonConfig{
Path: tomlConf.Netmon.path(),
Debug: tomlConf.Netmon.debug(),
Enable: tomlConf.Netmon.enable(),
}
err = SetKernelParams(config)
if err != nil {
return err
}
return nil
}
func initConfig() (config oci.RuntimeConfig, err error) {
var defaultAgentConfig interface{}
defaultHypervisorConfig := vc.HypervisorConfig{
HypervisorPath: defaultHypervisorPath,
KernelPath: defaultKernelPath,
ImagePath: defaultImagePath,
InitrdPath: defaultInitrdPath,
FirmwarePath: defaultFirmwarePath,
MachineAccelerators: defaultMachineAccelerators,
HypervisorMachineType: defaultMachineType,
NumVCPUs: defaultVCPUCount,
DefaultMaxVCPUs: defaultMaxVCPUCount,
MemorySize: defaultMemSize,
MemOffset: defaultMemOffset,
DefaultBridges: defaultBridgesCount,
MemPrealloc: defaultEnableMemPrealloc,
HugePages: defaultEnableHugePages,
Mlock: !defaultEnableSwap,
Debug: defaultEnableDebug,
DisableNestingChecks: defaultDisableNestingChecks,
BlockDeviceDriver: defaultBlockDeviceDriver,
BlockDeviceCacheSet: defaultBlockDeviceCacheSet,
BlockDeviceCacheDirect: defaultBlockDeviceCacheDirect,
BlockDeviceCacheNoflush: defaultBlockDeviceCacheNoflush,
EnableIOThreads: defaultEnableIOThreads,
Msize9p: defaultMsize9p,
HotplugVFIOOnRootBus: defaultHotplugVFIOOnRootBus,
GuestHookPath: defaultGuestHookPath,
}
err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel)
if err != nil {
return oci.RuntimeConfig{}, err
}
defaultAgentConfig = vc.HyperConfig{}
config = oci.RuntimeConfig{
HypervisorType: defaultHypervisor,
HypervisorConfig: defaultHypervisorConfig,
AgentType: defaultAgent,
AgentConfig: defaultAgentConfig,
ProxyType: defaultProxy,
ShimType: defaultShim,
}
return config, nil
}
// LoadConfiguration loads the configuration file and converts it into a
// runtime configuration.
//
// If ignoreLogging is true, the system logger will not be initialised nor
// will this function make any log calls.
//
// 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)
}
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
}
config.Debug = tomlConf.Runtime.Debug
if !tomlConf.Runtime.Debug {
// If debug is not required, switch back to the original
// default log priority, otherwise continue in debug mode.
kataUtilsLogger.Logger.Level = originalLoggerLevel
}
config.Trace = tomlConf.Runtime.Tracing
tracing = config.Trace
if tomlConf.Runtime.InterNetworkModel != "" {
err = config.InterNetworkModel.SetModel(tomlConf.Runtime.InterNetworkModel)
if err != nil {
return "", config, err
}
}
if !ignoreLogging {
err := handleSystemLog("", "")
if err != nil {
return "", config, err
}
kataUtilsLogger.WithFields(
logrus.Fields{
"format": "TOML",
"file": resolved,
}).Info("loaded configuration")
}
if err := updateConfig(resolved, tomlConf, &config, builtIn); err != nil {
return "", config, err
}
config.DisableGuestSeccomp = tomlConf.Runtime.DisableGuestSeccomp
// use no proxy if HypervisorConfig.UseVSock is true
if config.HypervisorConfig.UseVSock {
kataUtilsLogger.Info("VSOCK supported, configure to not use proxy")
config.ProxyType = vc.NoProxyType
config.ProxyConfig = vc.ProxyConfig{}
}
config.DisableNewNetNs = tomlConf.Runtime.DisableNewNetNs
if err := checkConfig(config); err != nil {
return "", config, err
}
return resolved, config, nil
}
// checkConfig checks the validity of the specified config.
func checkConfig(config oci.RuntimeConfig) error {
if err := checkNetNsConfig(config); err != nil {
return err
}
if err := checkHypervisorConfig(config.HypervisorConfig); err != nil {
return err
}
if err := checkFactoryConfig(config); err != nil {
return err
}
return nil
}
func updateConfig(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error {
if err := updateRuntimeConfig(configPath, tomlConf, config); err != nil {
return err
}
if builtIn {
config.ProxyType = vc.KataBuiltInProxyType
config.ShimType = vc.KataBuiltInShimType
config.AgentType = vc.KataContainersAgent
config.AgentConfig = vc.KataAgentConfig{
LongLiveConn: true,
UseVSock: config.HypervisorConfig.UseVSock,
}
}
return nil
}
// checkNetNsConfig performs sanity checks on disable_new_netns config.
// Because it is an expert option and conflicts with some other common configs.
func checkNetNsConfig(config oci.RuntimeConfig) error {
if config.DisableNewNetNs {
if config.NetmonConfig.Enable {
return fmt.Errorf("config disable_new_netns conflicts with enable_netmon")
}
if config.InterNetworkModel != vc.NetXConnectNoneModel {
return fmt.Errorf("config disable_new_netns only works with 'none' internetworking_model")
}
} else if config.ShimConfig.(vc.ShimConfig).Trace {
// Normally, the shim runs in a separate network namespace.
// But when tracing, the shim process needs to be able to talk
// to the Jaeger agent running in the host network namespace.
return errors.New("Shim tracing requires disable_new_netns for Jaeger agent communication")
}
return nil
}
// checkFactoryConfig ensures the VM factory configuration is valid.
func checkFactoryConfig(config oci.RuntimeConfig) error {
if config.FactoryConfig.Template {
if config.HypervisorConfig.InitrdPath == "" {
return errors.New("Factory option enable_template requires an initrd image")
}
if config.HypervisorConfig.UseVSock {
return errors.New("config vsock conflicts with factory, please disable one of them")
}
}
return nil
}
// checkHypervisorConfig performs basic "sanity checks" on the hypervisor
// config.
func checkHypervisorConfig(config vc.HypervisorConfig) error {
type image struct {
path string
initrd bool
}
images := []image{
{
path: config.ImagePath,
initrd: false,
},
{
path: config.InitrdPath,
initrd: true,
},
}
memSizeMB := int64(config.MemorySize)
if memSizeMB == 0 {
return errors.New("VM memory cannot be zero")
}
mb := int64(1024 * 1024)
for _, image := range images {
if image.path == "" {
continue
}
imageSizeBytes, err := fileSize(image.path)
if err != nil {
return err
}
if imageSizeBytes == 0 {
return fmt.Errorf("image %q is empty", image.path)
}
if imageSizeBytes > mb {
imageSizeMB := imageSizeBytes / mb
msg := fmt.Sprintf("VM memory (%dMB) smaller than image %q size (%dMB)",
memSizeMB, image.path, imageSizeMB)
if imageSizeMB >= memSizeMB {
if image.initrd {
// Initrd's need to be fully read into memory
return errors.New(msg)
}
// Images do not need to be fully read
// into memory, but it would be highly
// unusual to have an image larger
// than the amount of memory assigned
// to the VM.
kataUtilsLogger.Warn(msg)
}
}
}
return nil
}
// GetDefaultConfigFilePaths returns a list of paths that will be
// considered as configuration files in priority order.
func GetDefaultConfigFilePaths() []string {
return []string{
// normally below "/etc"
defaultSysConfRuntimeConfiguration,
// normally below "/usr/share"
defaultRuntimeConfiguration,
}
}
// getDefaultConfigFile looks in multiple default locations for a
// configuration file and returns the resolved path for the first file
// found, or an error if no config files can be found.
func getDefaultConfigFile() (string, error) {
var errs []string
for _, file := range GetDefaultConfigFilePaths() {
resolved, err := ResolvePath(file)
if err == nil {
return resolved, nil
}
s := fmt.Sprintf("config file %q unresolvable: %v", file, err)
errs = append(errs, s)
}
return "", errors.New(strings.Join(errs, ", "))
}
// SetConfigOptions will override some of the defaults settings.
func SetConfigOptions(n, runtimeConfig, sysRuntimeConfig string) {
if n != "" {
name = n
}
if runtimeConfig != "" {
defaultRuntimeConfiguration = runtimeConfig
}
if sysRuntimeConfig != "" {
defaultSysConfRuntimeConfiguration = sysRuntimeConfig
}
}