github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/pkg/katautils/config.go (about)

     1  // Copyright (c) 2018 Intel Corporation
     2  // Copyright (c) 2018 HyperHQ Inc.
     3  //
     4  // SPDX-License-Identifier: Apache-2.0
     5  //
     6  
     7  package katautils
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"io/ioutil"
    13  	goruntime "runtime"
    14  	"strings"
    15  
    16  	"github.com/BurntSushi/toml"
    17  	govmmQemu "github.com/kata-containers/govmm/qemu"
    18  	vc "github.com/kata-containers/runtime/virtcontainers"
    19  	"github.com/kata-containers/runtime/virtcontainers/device/config"
    20  	exp "github.com/kata-containers/runtime/virtcontainers/experimental"
    21  	"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
    22  	"github.com/kata-containers/runtime/virtcontainers/utils"
    23  	"github.com/sirupsen/logrus"
    24  )
    25  
    26  const (
    27  	defaultHypervisor = vc.QemuHypervisor
    28  	defaultAgent      = vc.KataContainersAgent
    29  )
    30  
    31  var (
    32  	defaultProxy = vc.KataProxyType
    33  	defaultShim  = vc.KataShimType
    34  
    35  	// if true, enable opentracing support.
    36  	tracing = false
    37  )
    38  
    39  // The TOML configuration file contains a number of sections (or
    40  // tables). The names of these tables are in dotted ("nested table")
    41  // form:
    42  //
    43  //   [<component>.<type>]
    44  //
    45  // The components are hypervisor, proxy, shim and agent. For example,
    46  //
    47  //   [proxy.kata]
    48  //
    49  // The currently supported types are listed below:
    50  const (
    51  	// supported hypervisor component types
    52  	firecrackerHypervisorTableType = "firecracker"
    53  	clhHypervisorTableType         = "clh"
    54  	qemuHypervisorTableType        = "qemu"
    55  	acrnHypervisorTableType        = "acrn"
    56  
    57  	// supported proxy component types
    58  	kataProxyTableType = "kata"
    59  
    60  	// supported shim component types
    61  	kataShimTableType = "kata"
    62  
    63  	// supported agent component types
    64  	kataAgentTableType = "kata"
    65  
    66  	// the maximum amount of PCI bridges that can be cold plugged in a VM
    67  	maxPCIBridges uint32 = 5
    68  )
    69  
    70  type tomlConfig struct {
    71  	Hypervisor map[string]hypervisor
    72  	Proxy      map[string]proxy
    73  	Shim       map[string]shim
    74  	Agent      map[string]agent
    75  	Runtime    runtime
    76  	Factory    factory
    77  	Netmon     netmon
    78  }
    79  
    80  type factory struct {
    81  	Template        bool   `toml:"enable_template"`
    82  	TemplatePath    string `toml:"template_path"`
    83  	VMCacheNumber   uint   `toml:"vm_cache_number"`
    84  	VMCacheEndpoint string `toml:"vm_cache_endpoint"`
    85  }
    86  
    87  type hypervisor struct {
    88  	Path                    string   `toml:"path"`
    89  	HypervisorPathList      []string `toml:"valid_hypervisor_paths"`
    90  	JailerPath              string   `toml:"jailer_path"`
    91  	JailerPathList          []string `toml:"valid_jailer_paths"`
    92  	Kernel                  string   `toml:"kernel"`
    93  	CtlPath                 string   `toml:"ctlpath"`
    94  	CtlPathList             []string `toml:"valid_ctlpaths"`
    95  	Initrd                  string   `toml:"initrd"`
    96  	Image                   string   `toml:"image"`
    97  	Firmware                string   `toml:"firmware"`
    98  	MachineAccelerators     string   `toml:"machine_accelerators"`
    99  	CPUFeatures             string   `toml:"cpu_features"`
   100  	KernelParams            string   `toml:"kernel_params"`
   101  	MachineType             string   `toml:"machine_type"`
   102  	BlockDeviceDriver       string   `toml:"block_device_driver"`
   103  	EntropySource           string   `toml:"entropy_source"`
   104  	SharedFS                string   `toml:"shared_fs"`
   105  	VirtioFSDaemon          string   `toml:"virtio_fs_daemon"`
   106  	VirtioFSDaemonList      []string `toml:"valid_virtio_fs_daemon_paths"`
   107  	VirtioFSCache           string   `toml:"virtio_fs_cache"`
   108  	VirtioFSExtraArgs       []string `toml:"virtio_fs_extra_args"`
   109  	PFlashList              []string `toml:"pflashes"`
   110  	VirtioFSCacheSize       uint32   `toml:"virtio_fs_cache_size"`
   111  	BlockDeviceCacheSet     bool     `toml:"block_device_cache_set"`
   112  	BlockDeviceCacheDirect  bool     `toml:"block_device_cache_direct"`
   113  	BlockDeviceCacheNoflush bool     `toml:"block_device_cache_noflush"`
   114  	EnableVhostUserStore    bool     `toml:"enable_vhost_user_store"`
   115  	VhostUserStorePath      string   `toml:"vhost_user_store_path"`
   116  	VhostUserStorePathList  []string `toml:"valid_vhost_user_store_paths"`
   117  	NumVCPUs                int32    `toml:"default_vcpus"`
   118  	DefaultMaxVCPUs         uint32   `toml:"default_maxvcpus"`
   119  	MemorySize              uint32   `toml:"default_memory"`
   120  	MemSlots                uint32   `toml:"memory_slots"`
   121  	MemOffset               uint32   `toml:"memory_offset"`
   122  	DefaultBridges          uint32   `toml:"default_bridges"`
   123  	Msize9p                 uint32   `toml:"msize_9p"`
   124  	PCIeRootPort            uint32   `toml:"pcie_root_port"`
   125  	DisableBlockDeviceUse   bool     `toml:"disable_block_device_use"`
   126  	MemPrealloc             bool     `toml:"enable_mem_prealloc"`
   127  	HugePages               bool     `toml:"enable_hugepages"`
   128  	VirtioMem               bool     `toml:"enable_virtio_mem"`
   129  	IOMMU                   bool     `toml:"enable_iommu"`
   130  	IOMMUPlatform           bool     `toml:"enable_iommu_platform"`
   131  	FileBackedMemRootDir    string   `toml:"file_mem_backend"`
   132  	FileBackedMemRootList   []string `toml:"valid_file_mem_backends"`
   133  	Swap                    bool     `toml:"enable_swap"`
   134  	Debug                   bool     `toml:"enable_debug"`
   135  	DisableNestingChecks    bool     `toml:"disable_nesting_checks"`
   136  	EnableIOThreads         bool     `toml:"enable_iothreads"`
   137  	UseVSock                bool     `toml:"use_vsock"`
   138  	DisableImageNvdimm      bool     `toml:"disable_image_nvdimm"`
   139  	HotplugVFIOOnRootBus    bool     `toml:"hotplug_vfio_on_root_bus"`
   140  	DisableVhostNet         bool     `toml:"disable_vhost_net"`
   141  	GuestHookPath           string   `toml:"guest_hook_path"`
   142  	EnableAnnotations       []string `toml:"enable_annotations"`
   143  }
   144  
   145  type proxy struct {
   146  	Path  string `toml:"path"`
   147  	Debug bool   `toml:"enable_debug"`
   148  }
   149  
   150  type runtime struct {
   151  	Debug               bool     `toml:"enable_debug"`
   152  	Tracing             bool     `toml:"enable_tracing"`
   153  	DisableNewNetNs     bool     `toml:"disable_new_netns"`
   154  	DisableGuestSeccomp bool     `toml:"disable_guest_seccomp"`
   155  	SandboxCgroupOnly   bool     `toml:"sandbox_cgroup_only"`
   156  	EnableAgentPidNs    bool     `toml:"enable_agent_pidns"`
   157  	Experimental        []string `toml:"experimental"`
   158  	InterNetworkModel   string   `toml:"internetworking_model"`
   159  }
   160  
   161  type shim struct {
   162  	Path    string `toml:"path"`
   163  	Debug   bool   `toml:"enable_debug"`
   164  	Tracing bool   `toml:"enable_tracing"`
   165  }
   166  
   167  type agent struct {
   168  	Debug         bool     `toml:"enable_debug"`
   169  	Tracing       bool     `toml:"enable_tracing"`
   170  	TraceMode     string   `toml:"trace_mode"`
   171  	TraceType     string   `toml:"trace_type"`
   172  	KernelModules []string `toml:"kernel_modules"`
   173  }
   174  
   175  type netmon struct {
   176  	Path   string `toml:"path"`
   177  	Debug  bool   `toml:"enable_debug"`
   178  	Enable bool   `toml:"enable_netmon"`
   179  }
   180  
   181  func (h hypervisor) path() (string, error) {
   182  	p := h.Path
   183  
   184  	if h.Path == "" {
   185  		p = defaultHypervisorPath
   186  	}
   187  
   188  	return ResolvePath(p)
   189  }
   190  
   191  func (h hypervisor) ctlpath() (string, error) {
   192  	p := h.CtlPath
   193  
   194  	if h.CtlPath == "" {
   195  		p = defaultHypervisorCtlPath
   196  	}
   197  
   198  	return ResolvePath(p)
   199  }
   200  
   201  func (h hypervisor) jailerPath() (string, error) {
   202  	p := h.JailerPath
   203  
   204  	if h.JailerPath == "" {
   205  		return "", nil
   206  	}
   207  
   208  	return ResolvePath(p)
   209  }
   210  
   211  func (h hypervisor) kernel() (string, error) {
   212  	p := h.Kernel
   213  
   214  	if p == "" {
   215  		p = defaultKernelPath
   216  	}
   217  
   218  	return ResolvePath(p)
   219  }
   220  
   221  func (h hypervisor) initrd() (string, error) {
   222  	p := h.Initrd
   223  
   224  	if p == "" {
   225  		return "", errors.New("initrd is not set")
   226  	}
   227  
   228  	return ResolvePath(p)
   229  }
   230  
   231  func (h hypervisor) image() (string, error) {
   232  	p := h.Image
   233  
   234  	if p == "" {
   235  		return "", errors.New("image is not set")
   236  	}
   237  
   238  	return ResolvePath(p)
   239  }
   240  
   241  func (h hypervisor) firmware() (string, error) {
   242  	p := h.Firmware
   243  
   244  	if p == "" {
   245  		if defaultFirmwarePath == "" {
   246  			return "", nil
   247  		}
   248  		p = defaultFirmwarePath
   249  	}
   250  
   251  	return ResolvePath(p)
   252  }
   253  
   254  func (h hypervisor) PFlash() ([]string, error) {
   255  	pflashes := h.PFlashList
   256  
   257  	if len(pflashes) == 0 {
   258  		return []string(nil), nil
   259  	}
   260  
   261  	for _, pflash := range pflashes {
   262  		_, err := ResolvePath(pflash)
   263  		if err != nil {
   264  			return []string{}, fmt.Errorf("pflash path doesn't exist: %s", pflash)
   265  		}
   266  	}
   267  
   268  	return pflashes, nil
   269  }
   270  
   271  func (h hypervisor) machineAccelerators() string {
   272  	var machineAccelerators string
   273  	for _, accelerator := range strings.Split(h.MachineAccelerators, ",") {
   274  		if accelerator != "" {
   275  			machineAccelerators += strings.TrimSpace(accelerator) + ","
   276  		}
   277  	}
   278  
   279  	machineAccelerators = strings.Trim(machineAccelerators, ",")
   280  
   281  	return machineAccelerators
   282  }
   283  
   284  func (h hypervisor) cpuFeatures() string {
   285  	var cpuFeatures string
   286  	for _, feature := range strings.Split(h.CPUFeatures, ",") {
   287  		if feature != "" {
   288  			cpuFeatures += strings.TrimSpace(feature) + ","
   289  		}
   290  	}
   291  
   292  	cpuFeatures = strings.Trim(cpuFeatures, ",")
   293  
   294  	return cpuFeatures
   295  }
   296  
   297  func (h hypervisor) kernelParams() string {
   298  	if h.KernelParams == "" {
   299  		return defaultKernelParams
   300  	}
   301  
   302  	return h.KernelParams
   303  }
   304  
   305  func (h hypervisor) machineType() string {
   306  	if h.MachineType == "" {
   307  		return defaultMachineType
   308  	}
   309  
   310  	return h.MachineType
   311  }
   312  
   313  func (h hypervisor) GetEntropySource() string {
   314  	if h.EntropySource == "" {
   315  		return defaultEntropySource
   316  	}
   317  
   318  	return h.EntropySource
   319  }
   320  
   321  func (h hypervisor) defaultVCPUs() uint32 {
   322  	numCPUs := goruntime.NumCPU()
   323  
   324  	if h.NumVCPUs < 0 || h.NumVCPUs > int32(numCPUs) {
   325  		return uint32(numCPUs)
   326  	}
   327  	if h.NumVCPUs == 0 { // or unspecified
   328  		return defaultVCPUCount
   329  	}
   330  
   331  	return uint32(h.NumVCPUs)
   332  }
   333  
   334  func (h hypervisor) defaultMaxVCPUs() uint32 {
   335  	numcpus := uint32(goruntime.NumCPU())
   336  	maxvcpus := vc.MaxQemuVCPUs()
   337  	reqVCPUs := h.DefaultMaxVCPUs
   338  
   339  	//don't exceed the number of physical CPUs. If a default is not provided, use the
   340  	// numbers of physical CPUs
   341  	if reqVCPUs >= numcpus || reqVCPUs == 0 {
   342  		reqVCPUs = numcpus
   343  	}
   344  
   345  	// Don't exceed the maximum number of vCPUs supported by hypervisor
   346  	if reqVCPUs > maxvcpus {
   347  		return maxvcpus
   348  	}
   349  
   350  	return reqVCPUs
   351  }
   352  
   353  func (h hypervisor) defaultMemSz() uint32 {
   354  	if h.MemorySize > 0 {
   355  		return h.MemorySize
   356  	}
   357  
   358  	return defaultMemSize
   359  }
   360  
   361  func (h hypervisor) defaultMemSlots() uint32 {
   362  	slots := h.MemSlots
   363  	if slots == 0 {
   364  		slots = defaultMemSlots
   365  	}
   366  
   367  	return slots
   368  }
   369  
   370  func (h hypervisor) defaultMemOffset() uint32 {
   371  	offset := h.MemOffset
   372  	if offset == 0 {
   373  		offset = defaultMemOffset
   374  	}
   375  
   376  	return offset
   377  }
   378  
   379  func (h hypervisor) defaultBridges() uint32 {
   380  	if h.DefaultBridges == 0 {
   381  		return defaultBridgesCount
   382  	}
   383  
   384  	if h.DefaultBridges > maxPCIBridges {
   385  		return maxPCIBridges
   386  	}
   387  
   388  	return h.DefaultBridges
   389  }
   390  
   391  func (h hypervisor) defaultVirtioFSCache() string {
   392  	if h.VirtioFSCache == "" {
   393  		return defaultVirtioFSCacheMode
   394  	}
   395  
   396  	return h.VirtioFSCache
   397  }
   398  
   399  func (h hypervisor) blockDeviceDriver() (string, error) {
   400  	supportedBlockDrivers := []string{config.VirtioSCSI, config.VirtioBlock, config.VirtioMmio, config.Nvdimm, config.VirtioBlockCCW}
   401  
   402  	if h.BlockDeviceDriver == "" {
   403  		return defaultBlockDeviceDriver, nil
   404  	}
   405  
   406  	for _, b := range supportedBlockDrivers {
   407  		if b == h.BlockDeviceDriver {
   408  			return h.BlockDeviceDriver, nil
   409  		}
   410  	}
   411  
   412  	return "", fmt.Errorf("Invalid hypervisor block storage driver %v specified (supported drivers: %v)", h.BlockDeviceDriver, supportedBlockDrivers)
   413  }
   414  
   415  func (h hypervisor) sharedFS() (string, error) {
   416  	supportedSharedFS := []string{config.Virtio9P, config.VirtioFS}
   417  
   418  	if h.SharedFS == "" {
   419  		return config.Virtio9P, nil
   420  	}
   421  
   422  	for _, fs := range supportedSharedFS {
   423  		if fs == h.SharedFS {
   424  			return h.SharedFS, nil
   425  		}
   426  	}
   427  
   428  	return "", fmt.Errorf("Invalid hypervisor shared file system %v specified (supported file systems: %v)", h.SharedFS, supportedSharedFS)
   429  }
   430  
   431  func (h hypervisor) msize9p() uint32 {
   432  	if h.Msize9p == 0 {
   433  		return defaultMsize9p
   434  	}
   435  
   436  	return h.Msize9p
   437  }
   438  
   439  func (h hypervisor) useVSock() bool {
   440  	return h.UseVSock
   441  }
   442  
   443  func (h hypervisor) guestHookPath() string {
   444  	if h.GuestHookPath == "" {
   445  		return defaultGuestHookPath
   446  	}
   447  	return h.GuestHookPath
   448  }
   449  
   450  func (h hypervisor) vhostUserStorePath() string {
   451  	if h.VhostUserStorePath == "" {
   452  		return defaultVhostUserStorePath
   453  	}
   454  	return h.VhostUserStorePath
   455  }
   456  
   457  func (h hypervisor) getInitrdAndImage() (initrd string, image string, err error) {
   458  	initrd, errInitrd := h.initrd()
   459  
   460  	image, errImage := h.image()
   461  
   462  	if image != "" && initrd != "" {
   463  		return "", "", errors.New("having both an image and an initrd defined in the configuration file is not supported")
   464  	}
   465  
   466  	if errInitrd != nil && errImage != nil {
   467  		return "", "", fmt.Errorf("Either initrd or image must be set to a valid path (initrd: %v) (image: %v)", errInitrd, errImage)
   468  	}
   469  
   470  	return
   471  }
   472  
   473  func (h hypervisor) getIOMMUPlatform() bool {
   474  	if h.IOMMUPlatform {
   475  		kataUtilsLogger.Info("IOMMUPlatform is enabled by default.")
   476  	} else {
   477  		kataUtilsLogger.Info("IOMMUPlatform is disabled by default.")
   478  	}
   479  	return h.IOMMUPlatform
   480  }
   481  
   482  func (p proxy) path() (string, error) {
   483  	path := p.Path
   484  	if path == "" {
   485  		path = defaultProxyPath
   486  	}
   487  
   488  	return ResolvePath(path)
   489  }
   490  
   491  func (p proxy) debug() bool {
   492  	return p.Debug
   493  }
   494  
   495  func (s shim) path() (string, error) {
   496  	p := s.Path
   497  
   498  	if p == "" {
   499  		p = defaultShimPath
   500  	}
   501  
   502  	return ResolvePath(p)
   503  }
   504  
   505  func (s shim) debug() bool {
   506  	return s.Debug
   507  }
   508  
   509  func (s shim) trace() bool {
   510  	return s.Tracing
   511  }
   512  
   513  func (a agent) debug() bool {
   514  	return a.Debug
   515  }
   516  
   517  func (a agent) trace() bool {
   518  	return a.Tracing
   519  }
   520  
   521  func (a agent) traceMode() string {
   522  	return a.TraceMode
   523  }
   524  
   525  func (a agent) traceType() string {
   526  	return a.TraceType
   527  }
   528  
   529  func (a agent) kernelModules() []string {
   530  	return a.KernelModules
   531  }
   532  
   533  func (n netmon) enable() bool {
   534  	return n.Enable
   535  }
   536  
   537  func (n netmon) path() string {
   538  	if n.Path == "" {
   539  		return defaultNetmonPath
   540  	}
   541  
   542  	return n.Path
   543  }
   544  
   545  func (n netmon) debug() bool {
   546  	return n.Debug
   547  }
   548  
   549  func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
   550  	hypervisor, err := h.path()
   551  	if err != nil {
   552  		return vc.HypervisorConfig{}, err
   553  	}
   554  
   555  	jailer, err := h.jailerPath()
   556  	if err != nil {
   557  		return vc.HypervisorConfig{}, err
   558  	}
   559  
   560  	kernel, err := h.kernel()
   561  	if err != nil {
   562  		return vc.HypervisorConfig{}, err
   563  	}
   564  
   565  	initrd, image, err := h.getInitrdAndImage()
   566  	if err != nil {
   567  		return vc.HypervisorConfig{}, err
   568  	}
   569  
   570  	firmware, err := h.firmware()
   571  	if err != nil {
   572  		return vc.HypervisorConfig{}, err
   573  	}
   574  
   575  	kernelParams := h.kernelParams()
   576  
   577  	blockDriver, err := h.blockDeviceDriver()
   578  	if err != nil {
   579  		return vc.HypervisorConfig{}, err
   580  	}
   581  
   582  	if !utils.SupportsVsocks() {
   583  		return vc.HypervisorConfig{}, errors.New("No vsock support, firecracker cannot be used")
   584  	}
   585  
   586  	return vc.HypervisorConfig{
   587  		HypervisorPath:        hypervisor,
   588  		HypervisorPathList:    h.HypervisorPathList,
   589  		JailerPath:            jailer,
   590  		JailerPathList:        h.JailerPathList,
   591  		KernelPath:            kernel,
   592  		InitrdPath:            initrd,
   593  		ImagePath:             image,
   594  		FirmwarePath:          firmware,
   595  		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)),
   596  		NumVCPUs:              h.defaultVCPUs(),
   597  		DefaultMaxVCPUs:       h.defaultMaxVCPUs(),
   598  		MemorySize:            h.defaultMemSz(),
   599  		MemSlots:              h.defaultMemSlots(),
   600  		EntropySource:         h.GetEntropySource(),
   601  		DefaultBridges:        h.defaultBridges(),
   602  		DisableBlockDeviceUse: h.DisableBlockDeviceUse,
   603  		HugePages:             h.HugePages,
   604  		Mlock:                 !h.Swap,
   605  		Debug:                 h.Debug,
   606  		DisableNestingChecks:  h.DisableNestingChecks,
   607  		BlockDeviceDriver:     blockDriver,
   608  		EnableIOThreads:       h.EnableIOThreads,
   609  		DisableVhostNet:       true, // vhost-net backend is not supported in Firecracker
   610  		UseVSock:              true,
   611  		GuestHookPath:         h.guestHookPath(),
   612  		EnableAnnotations:     h.EnableAnnotations,
   613  	}, nil
   614  }
   615  
   616  func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
   617  	hypervisor, err := h.path()
   618  	if err != nil {
   619  		return vc.HypervisorConfig{}, err
   620  	}
   621  
   622  	kernel, err := h.kernel()
   623  	if err != nil {
   624  		return vc.HypervisorConfig{}, err
   625  	}
   626  
   627  	initrd, image, err := h.getInitrdAndImage()
   628  	if err != nil {
   629  		return vc.HypervisorConfig{}, err
   630  	}
   631  
   632  	if image != "" && initrd != "" {
   633  		return vc.HypervisorConfig{},
   634  			errors.New("having both an image and an initrd defined in the configuration file is not supported")
   635  	}
   636  
   637  	if image == "" && initrd == "" {
   638  		return vc.HypervisorConfig{},
   639  			errors.New("either image or initrd must be defined in the configuration file")
   640  	}
   641  
   642  	firmware, err := h.firmware()
   643  	if err != nil {
   644  		return vc.HypervisorConfig{}, err
   645  	}
   646  
   647  	pflashes, err := h.PFlash()
   648  	if err != nil {
   649  		return vc.HypervisorConfig{}, err
   650  	}
   651  
   652  	machineAccelerators := h.machineAccelerators()
   653  	cpuFeatures := h.cpuFeatures()
   654  	kernelParams := h.kernelParams()
   655  	machineType := h.machineType()
   656  
   657  	// The "microvm" machine type doesn't support NVDIMM so override the
   658  	// config setting to explicitly disable it (i.e. don't require the
   659  	// user to add 'disable_image_nvdimm = true' in the .toml file).
   660  	if machineType == govmmQemu.MachineTypeMicrovm && !h.DisableImageNvdimm {
   661  		h.DisableImageNvdimm = true
   662  		kataUtilsLogger.Info("Setting 'disable_image_nvdimm = true' as microvm does not support NVDIMM")
   663  	}
   664  
   665  	blockDriver, err := h.blockDeviceDriver()
   666  	if err != nil {
   667  		return vc.HypervisorConfig{}, err
   668  	}
   669  
   670  	sharedFS, err := h.sharedFS()
   671  	if err != nil {
   672  		return vc.HypervisorConfig{}, err
   673  	}
   674  
   675  	if sharedFS == config.VirtioFS && h.VirtioFSDaemon == "" {
   676  		return vc.HypervisorConfig{},
   677  			errors.New("cannot enable virtio-fs without daemon path in configuration file")
   678  	}
   679  
   680  	useVSock := false
   681  	if h.useVSock() {
   682  		if utils.SupportsVsocks() {
   683  			kataUtilsLogger.Info("vsock supported")
   684  			useVSock = true
   685  		} else {
   686  			kataUtilsLogger.Warn("No vsock support, falling back to legacy serial port")
   687  		}
   688  	}
   689  
   690  	return vc.HypervisorConfig{
   691  		HypervisorPath:          hypervisor,
   692  		HypervisorPathList:      h.HypervisorPathList,
   693  		KernelPath:              kernel,
   694  		InitrdPath:              initrd,
   695  		ImagePath:               image,
   696  		FirmwarePath:            firmware,
   697  		MachineAccelerators:     machineAccelerators,
   698  		CPUFeatures:             cpuFeatures,
   699  		KernelParams:            vc.DeserializeParams(strings.Fields(kernelParams)),
   700  		HypervisorMachineType:   machineType,
   701  		NumVCPUs:                h.defaultVCPUs(),
   702  		DefaultMaxVCPUs:         h.defaultMaxVCPUs(),
   703  		MemorySize:              h.defaultMemSz(),
   704  		MemSlots:                h.defaultMemSlots(),
   705  		MemOffset:               h.defaultMemOffset(),
   706  		VirtioMem:               h.VirtioMem,
   707  		EntropySource:           h.GetEntropySource(),
   708  		DefaultBridges:          h.defaultBridges(),
   709  		DisableBlockDeviceUse:   h.DisableBlockDeviceUse,
   710  		SharedFS:                sharedFS,
   711  		VirtioFSDaemon:          h.VirtioFSDaemon,
   712  		VirtioFSDaemonList:      h.VirtioFSDaemonList,
   713  		VirtioFSCacheSize:       h.VirtioFSCacheSize,
   714  		VirtioFSCache:           h.defaultVirtioFSCache(),
   715  		VirtioFSExtraArgs:       h.VirtioFSExtraArgs,
   716  		PFlash:                  pflashes,
   717  		MemPrealloc:             h.MemPrealloc,
   718  		HugePages:               h.HugePages,
   719  		IOMMU:                   h.IOMMU,
   720  		IOMMUPlatform:           h.getIOMMUPlatform(),
   721  		FileBackedMemRootDir:    h.FileBackedMemRootDir,
   722  		FileBackedMemRootList:   h.FileBackedMemRootList,
   723  		Mlock:                   !h.Swap,
   724  		Debug:                   h.Debug,
   725  		DisableNestingChecks:    h.DisableNestingChecks,
   726  		BlockDeviceDriver:       blockDriver,
   727  		BlockDeviceCacheSet:     h.BlockDeviceCacheSet,
   728  		BlockDeviceCacheDirect:  h.BlockDeviceCacheDirect,
   729  		BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush,
   730  		EnableIOThreads:         h.EnableIOThreads,
   731  		Msize9p:                 h.msize9p(),
   732  		UseVSock:                useVSock,
   733  		DisableImageNvdimm:      h.DisableImageNvdimm,
   734  		HotplugVFIOOnRootBus:    h.HotplugVFIOOnRootBus,
   735  		PCIeRootPort:            h.PCIeRootPort,
   736  		DisableVhostNet:         h.DisableVhostNet,
   737  		EnableVhostUserStore:    h.EnableVhostUserStore,
   738  		VhostUserStorePath:      h.vhostUserStorePath(),
   739  		VhostUserStorePathList:  h.VhostUserStorePathList,
   740  		GuestHookPath:           h.guestHookPath(),
   741  		EnableAnnotations:       h.EnableAnnotations,
   742  	}, nil
   743  }
   744  
   745  func newAcrnHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
   746  	hypervisor, err := h.path()
   747  	if err != nil {
   748  		return vc.HypervisorConfig{}, err
   749  	}
   750  
   751  	hypervisorctl, err := h.ctlpath()
   752  	if err != nil {
   753  		return vc.HypervisorConfig{}, err
   754  	}
   755  
   756  	kernel, err := h.kernel()
   757  	if err != nil {
   758  		return vc.HypervisorConfig{}, err
   759  	}
   760  
   761  	image, err := h.image()
   762  	if err != nil {
   763  		return vc.HypervisorConfig{}, err
   764  	}
   765  
   766  	if image == "" {
   767  		return vc.HypervisorConfig{},
   768  			errors.New("image must be defined in the configuration file")
   769  	}
   770  
   771  	firmware, err := h.firmware()
   772  	if err != nil {
   773  		return vc.HypervisorConfig{}, err
   774  	}
   775  
   776  	kernelParams := h.kernelParams()
   777  
   778  	blockDriver, err := h.blockDeviceDriver()
   779  	if err != nil {
   780  		return vc.HypervisorConfig{}, err
   781  	}
   782  
   783  	return vc.HypervisorConfig{
   784  		HypervisorPath:        hypervisor,
   785  		HypervisorPathList:    h.HypervisorPathList,
   786  		KernelPath:            kernel,
   787  		ImagePath:             image,
   788  		HypervisorCtlPath:     hypervisorctl,
   789  		HypervisorCtlPathList: h.CtlPathList,
   790  		FirmwarePath:          firmware,
   791  		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)),
   792  		NumVCPUs:              h.defaultVCPUs(),
   793  		DefaultMaxVCPUs:       h.defaultMaxVCPUs(),
   794  		MemorySize:            h.defaultMemSz(),
   795  		MemSlots:              h.defaultMemSlots(),
   796  		EntropySource:         h.GetEntropySource(),
   797  		DefaultBridges:        h.defaultBridges(),
   798  		HugePages:             h.HugePages,
   799  		Mlock:                 !h.Swap,
   800  		Debug:                 h.Debug,
   801  		DisableNestingChecks:  h.DisableNestingChecks,
   802  		BlockDeviceDriver:     blockDriver,
   803  		DisableVhostNet:       h.DisableVhostNet,
   804  		GuestHookPath:         h.guestHookPath(),
   805  		EnableAnnotations:     h.EnableAnnotations,
   806  	}, nil
   807  }
   808  
   809  func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
   810  	hypervisor, err := h.path()
   811  	if err != nil {
   812  		return vc.HypervisorConfig{}, err
   813  	}
   814  
   815  	kernel, err := h.kernel()
   816  	if err != nil {
   817  		return vc.HypervisorConfig{}, err
   818  	}
   819  
   820  	initrd, image, err := h.getInitrdAndImage()
   821  	if err != nil {
   822  		return vc.HypervisorConfig{}, err
   823  	}
   824  
   825  	if initrd != "" {
   826  		return vc.HypervisorConfig{},
   827  			errors.New("having an initrd defined in the configuration file is not supported")
   828  	}
   829  
   830  	if image == "" {
   831  		return vc.HypervisorConfig{},
   832  			errors.New("image must be defined in the configuration file")
   833  	}
   834  
   835  	firmware, err := h.firmware()
   836  	if err != nil {
   837  		return vc.HypervisorConfig{}, err
   838  	}
   839  
   840  	machineAccelerators := h.machineAccelerators()
   841  	kernelParams := h.kernelParams()
   842  	machineType := h.machineType()
   843  
   844  	blockDriver, err := h.blockDeviceDriver()
   845  	if err != nil {
   846  		return vc.HypervisorConfig{}, err
   847  	}
   848  
   849  	sharedFS := config.VirtioFS
   850  
   851  	if h.VirtioFSDaemon == "" {
   852  		return vc.HypervisorConfig{},
   853  			errors.New("virtio-fs daemon path is missing in configuration file")
   854  	}
   855  
   856  	return vc.HypervisorConfig{
   857  		HypervisorPath:          hypervisor,
   858  		HypervisorPathList:      h.HypervisorPathList,
   859  		KernelPath:              kernel,
   860  		InitrdPath:              initrd,
   861  		ImagePath:               image,
   862  		FirmwarePath:            firmware,
   863  		MachineAccelerators:     machineAccelerators,
   864  		KernelParams:            vc.DeserializeParams(strings.Fields(kernelParams)),
   865  		HypervisorMachineType:   machineType,
   866  		NumVCPUs:                h.defaultVCPUs(),
   867  		DefaultMaxVCPUs:         h.defaultMaxVCPUs(),
   868  		MemorySize:              h.defaultMemSz(),
   869  		MemSlots:                h.defaultMemSlots(),
   870  		MemOffset:               h.defaultMemOffset(),
   871  		VirtioMem:               h.VirtioMem,
   872  		EntropySource:           h.GetEntropySource(),
   873  		DefaultBridges:          h.defaultBridges(),
   874  		DisableBlockDeviceUse:   h.DisableBlockDeviceUse,
   875  		SharedFS:                sharedFS,
   876  		VirtioFSDaemon:          h.VirtioFSDaemon,
   877  		VirtioFSDaemonList:      h.VirtioFSDaemonList,
   878  		VirtioFSCacheSize:       h.VirtioFSCacheSize,
   879  		VirtioFSCache:           h.VirtioFSCache,
   880  		MemPrealloc:             h.MemPrealloc,
   881  		HugePages:               h.HugePages,
   882  		FileBackedMemRootDir:    h.FileBackedMemRootDir,
   883  		FileBackedMemRootList:   h.FileBackedMemRootList,
   884  		Mlock:                   !h.Swap,
   885  		Debug:                   h.Debug,
   886  		DisableNestingChecks:    h.DisableNestingChecks,
   887  		BlockDeviceDriver:       blockDriver,
   888  		BlockDeviceCacheSet:     h.BlockDeviceCacheSet,
   889  		BlockDeviceCacheDirect:  h.BlockDeviceCacheDirect,
   890  		BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush,
   891  		EnableIOThreads:         h.EnableIOThreads,
   892  		Msize9p:                 h.msize9p(),
   893  		HotplugVFIOOnRootBus:    h.HotplugVFIOOnRootBus,
   894  		PCIeRootPort:            h.PCIeRootPort,
   895  		DisableVhostNet:         true,
   896  		UseVSock:                true,
   897  		VirtioFSExtraArgs:       h.VirtioFSExtraArgs,
   898  		EnableAnnotations:       h.EnableAnnotations,
   899  	}, nil
   900  }
   901  
   902  func newFactoryConfig(f factory) (oci.FactoryConfig, error) {
   903  	if f.TemplatePath == "" {
   904  		f.TemplatePath = defaultTemplatePath
   905  	}
   906  	if f.VMCacheEndpoint == "" {
   907  		f.VMCacheEndpoint = defaultVMCacheEndpoint
   908  	}
   909  	return oci.FactoryConfig{
   910  		Template:        f.Template,
   911  		TemplatePath:    f.TemplatePath,
   912  		VMCacheNumber:   f.VMCacheNumber,
   913  		VMCacheEndpoint: f.VMCacheEndpoint,
   914  	}, nil
   915  }
   916  
   917  func newShimConfig(s shim) (vc.ShimConfig, error) {
   918  	path, err := s.path()
   919  	if err != nil {
   920  		return vc.ShimConfig{}, err
   921  	}
   922  
   923  	return vc.ShimConfig{
   924  		Path:  path,
   925  		Debug: s.debug(),
   926  		Trace: s.trace(),
   927  	}, nil
   928  }
   929  
   930  func updateRuntimeConfigHypervisor(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
   931  	for k, hypervisor := range tomlConf.Hypervisor {
   932  		var err error
   933  		var hConfig vc.HypervisorConfig
   934  
   935  		switch k {
   936  		case firecrackerHypervisorTableType:
   937  			config.HypervisorType = vc.FirecrackerHypervisor
   938  			hConfig, err = newFirecrackerHypervisorConfig(hypervisor)
   939  		case qemuHypervisorTableType:
   940  			config.HypervisorType = vc.QemuHypervisor
   941  			hConfig, err = newQemuHypervisorConfig(hypervisor)
   942  		case acrnHypervisorTableType:
   943  			config.HypervisorType = vc.AcrnHypervisor
   944  			hConfig, err = newAcrnHypervisorConfig(hypervisor)
   945  		case clhHypervisorTableType:
   946  			config.HypervisorType = vc.ClhHypervisor
   947  			hConfig, err = newClhHypervisorConfig(hypervisor)
   948  		}
   949  
   950  		if err != nil {
   951  			return fmt.Errorf("%v: %v", configPath, err)
   952  		}
   953  
   954  		config.HypervisorConfig = hConfig
   955  	}
   956  
   957  	return nil
   958  }
   959  
   960  func updateRuntimeConfigProxy(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error {
   961  	if builtIn {
   962  		config.ProxyType = vc.KataBuiltInProxyType
   963  		config.ProxyConfig = vc.ProxyConfig{
   964  			Debug: config.Debug,
   965  		}
   966  		return nil
   967  	}
   968  
   969  	for k, proxy := range tomlConf.Proxy {
   970  		switch k {
   971  		case kataProxyTableType:
   972  			config.ProxyType = vc.KataProxyType
   973  		default:
   974  			return fmt.Errorf("%s proxy type not supported", k)
   975  		}
   976  
   977  		path, err := proxy.path()
   978  		if err != nil {
   979  			return err
   980  		}
   981  
   982  		config.ProxyConfig = vc.ProxyConfig{
   983  			Path:  path,
   984  			Debug: proxy.debug(),
   985  		}
   986  	}
   987  
   988  	return nil
   989  }
   990  
   991  func updateRuntimeConfigAgent(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error {
   992  	if builtIn {
   993  		var agentConfig vc.KataAgentConfig
   994  
   995  		// If the agent config section isn't a Kata one, just default
   996  		// to everything being disabled.
   997  		agentConfig, _ = config.AgentConfig.(vc.KataAgentConfig)
   998  
   999  		config.AgentType = vc.KataContainersAgent
  1000  		config.AgentConfig = vc.KataAgentConfig{
  1001  			LongLiveConn:  true,
  1002  			UseVSock:      config.HypervisorConfig.UseVSock,
  1003  			Debug:         agentConfig.Debug,
  1004  			KernelModules: agentConfig.KernelModules,
  1005  		}
  1006  
  1007  		return nil
  1008  	}
  1009  
  1010  	for k, agent := range tomlConf.Agent {
  1011  		switch k {
  1012  		case kataAgentTableType:
  1013  			config.AgentType = vc.KataContainersAgent
  1014  			config.AgentConfig = vc.KataAgentConfig{
  1015  				UseVSock:      config.HypervisorConfig.UseVSock,
  1016  				Debug:         agent.debug(),
  1017  				Trace:         agent.trace(),
  1018  				TraceMode:     agent.traceMode(),
  1019  				TraceType:     agent.traceType(),
  1020  				KernelModules: agent.kernelModules(),
  1021  			}
  1022  		default:
  1023  			return fmt.Errorf("%s agent type is not supported", k)
  1024  		}
  1025  	}
  1026  
  1027  	return nil
  1028  }
  1029  
  1030  func updateRuntimeConfigShim(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error {
  1031  	if builtIn {
  1032  		config.ShimType = vc.KataBuiltInShimType
  1033  		config.ShimConfig = vc.ShimConfig{}
  1034  		return nil
  1035  	}
  1036  
  1037  	for k, shim := range tomlConf.Shim {
  1038  		switch k {
  1039  		case kataShimTableType:
  1040  			config.ShimType = vc.KataShimType
  1041  		default:
  1042  			return fmt.Errorf("%s shim is not supported", k)
  1043  		}
  1044  
  1045  		shConfig, err := newShimConfig(shim)
  1046  		if err != nil {
  1047  			return fmt.Errorf("%v: %v", configPath, err)
  1048  		}
  1049  
  1050  		config.ShimConfig = shConfig
  1051  	}
  1052  
  1053  	return nil
  1054  }
  1055  
  1056  // SetKernelParams adds the user-specified kernel parameters (from the
  1057  // configuration file) to the defaults so that the former take priority.
  1058  func SetKernelParams(runtimeConfig *oci.RuntimeConfig) error {
  1059  	defaultKernelParams := GetKernelParamsFunc(needSystemd(runtimeConfig.HypervisorConfig), runtimeConfig.Trace)
  1060  
  1061  	if runtimeConfig.HypervisorConfig.Debug {
  1062  		strParams := vc.SerializeParams(defaultKernelParams, "=")
  1063  		formatted := strings.Join(strParams, " ")
  1064  		kataUtilsLogger.WithField("default-kernel-parameters", formatted).Debug()
  1065  	}
  1066  
  1067  	// retrieve the parameters specified in the config file
  1068  	userKernelParams := runtimeConfig.HypervisorConfig.KernelParams
  1069  
  1070  	// reset
  1071  	runtimeConfig.HypervisorConfig.KernelParams = []vc.Param{}
  1072  
  1073  	// first, add default values
  1074  	for _, p := range defaultKernelParams {
  1075  		if err := runtimeConfig.AddKernelParam(p); err != nil {
  1076  			return err
  1077  		}
  1078  	}
  1079  
  1080  	// set the scsi scan mode to none for virtio-scsi
  1081  	if runtimeConfig.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI {
  1082  		p := vc.Param{
  1083  			Key:   "scsi_mod.scan",
  1084  			Value: "none",
  1085  		}
  1086  		if err := runtimeConfig.AddKernelParam(p); err != nil {
  1087  			return err
  1088  		}
  1089  	}
  1090  
  1091  	// next, check for agent specific kernel params
  1092  	if agentConfig, ok := runtimeConfig.AgentConfig.(vc.KataAgentConfig); ok {
  1093  		err := vc.KataAgentSetDefaultTraceConfigOptions(&agentConfig)
  1094  		if err != nil {
  1095  			return err
  1096  		}
  1097  
  1098  		params := vc.KataAgentKernelParams(agentConfig)
  1099  
  1100  		for _, p := range params {
  1101  			if err := runtimeConfig.AddKernelParam(p); err != nil {
  1102  				return err
  1103  			}
  1104  		}
  1105  	}
  1106  
  1107  	// now re-add the user-specified values so that they take priority.
  1108  	for _, p := range userKernelParams {
  1109  		if err := runtimeConfig.AddKernelParam(p); err != nil {
  1110  			return err
  1111  		}
  1112  	}
  1113  
  1114  	return nil
  1115  }
  1116  
  1117  func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error {
  1118  	if err := updateRuntimeConfigHypervisor(configPath, tomlConf, config); err != nil {
  1119  		return err
  1120  	}
  1121  
  1122  	if err := updateRuntimeConfigProxy(configPath, tomlConf, config, builtIn); err != nil {
  1123  		return err
  1124  	}
  1125  
  1126  	if err := updateRuntimeConfigAgent(configPath, tomlConf, config, builtIn); err != nil {
  1127  		return err
  1128  	}
  1129  
  1130  	if err := updateRuntimeConfigShim(configPath, tomlConf, config, builtIn); err != nil {
  1131  		return err
  1132  	}
  1133  
  1134  	fConfig, err := newFactoryConfig(tomlConf.Factory)
  1135  	if err != nil {
  1136  		return fmt.Errorf("%v: %v", configPath, err)
  1137  	}
  1138  	config.FactoryConfig = fConfig
  1139  
  1140  	config.NetmonConfig = vc.NetmonConfig{
  1141  		Path:   tomlConf.Netmon.path(),
  1142  		Debug:  tomlConf.Netmon.debug(),
  1143  		Enable: tomlConf.Netmon.enable(),
  1144  	}
  1145  
  1146  	err = SetKernelParams(config)
  1147  	if err != nil {
  1148  		return err
  1149  	}
  1150  
  1151  	return nil
  1152  }
  1153  
  1154  func GetDefaultHypervisorConfig() vc.HypervisorConfig {
  1155  	return vc.HypervisorConfig{
  1156  		HypervisorPath:          defaultHypervisorPath,
  1157  		JailerPath:              defaultJailerPath,
  1158  		KernelPath:              defaultKernelPath,
  1159  		ImagePath:               defaultImagePath,
  1160  		InitrdPath:              defaultInitrdPath,
  1161  		FirmwarePath:            defaultFirmwarePath,
  1162  		MachineAccelerators:     defaultMachineAccelerators,
  1163  		CPUFeatures:             defaultCPUFeatures,
  1164  		HypervisorMachineType:   defaultMachineType,
  1165  		NumVCPUs:                defaultVCPUCount,
  1166  		DefaultMaxVCPUs:         defaultMaxVCPUCount,
  1167  		MemorySize:              defaultMemSize,
  1168  		MemOffset:               defaultMemOffset,
  1169  		VirtioMem:               defaultVirtioMem,
  1170  		DisableBlockDeviceUse:   defaultDisableBlockDeviceUse,
  1171  		DefaultBridges:          defaultBridgesCount,
  1172  		MemPrealloc:             defaultEnableMemPrealloc,
  1173  		HugePages:               defaultEnableHugePages,
  1174  		IOMMU:                   defaultEnableIOMMU,
  1175  		IOMMUPlatform:           defaultEnableIOMMUPlatform,
  1176  		FileBackedMemRootDir:    defaultFileBackedMemRootDir,
  1177  		Mlock:                   !defaultEnableSwap,
  1178  		Debug:                   defaultEnableDebug,
  1179  		DisableNestingChecks:    defaultDisableNestingChecks,
  1180  		BlockDeviceDriver:       defaultBlockDeviceDriver,
  1181  		BlockDeviceCacheSet:     defaultBlockDeviceCacheSet,
  1182  		BlockDeviceCacheDirect:  defaultBlockDeviceCacheDirect,
  1183  		BlockDeviceCacheNoflush: defaultBlockDeviceCacheNoflush,
  1184  		EnableIOThreads:         defaultEnableIOThreads,
  1185  		Msize9p:                 defaultMsize9p,
  1186  		HotplugVFIOOnRootBus:    defaultHotplugVFIOOnRootBus,
  1187  		PCIeRootPort:            defaultPCIeRootPort,
  1188  		GuestHookPath:           defaultGuestHookPath,
  1189  		VhostUserStorePath:      defaultVhostUserStorePath,
  1190  		VirtioFSCache:           defaultVirtioFSCacheMode,
  1191  		DisableImageNvdimm:      defaultDisableImageNvdimm,
  1192  	}
  1193  }
  1194  
  1195  func initConfig() (config oci.RuntimeConfig, err error) {
  1196  	var defaultAgentConfig interface{}
  1197  
  1198  	err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel)
  1199  	if err != nil {
  1200  		return oci.RuntimeConfig{}, err
  1201  	}
  1202  
  1203  	defaultAgentConfig = vc.KataAgentConfig{}
  1204  
  1205  	config = oci.RuntimeConfig{
  1206  		HypervisorType:   defaultHypervisor,
  1207  		HypervisorConfig: GetDefaultHypervisorConfig(),
  1208  		AgentType:        defaultAgent,
  1209  		AgentConfig:      defaultAgentConfig,
  1210  		ProxyType:        defaultProxy,
  1211  		ShimType:         defaultShim,
  1212  	}
  1213  
  1214  	return config, nil
  1215  }
  1216  
  1217  // LoadConfiguration loads the configuration file and converts it into a
  1218  // runtime configuration.
  1219  //
  1220  // If ignoreLogging is true, the system logger will not be initialised nor
  1221  // will this function make any log calls.
  1222  //
  1223  // All paths are resolved fully meaning if this function does not return an
  1224  // error, all paths are valid at the time of the call.
  1225  func LoadConfiguration(configPath string, ignoreLogging, builtIn bool) (resolvedConfigPath string, config oci.RuntimeConfig, err error) {
  1226  
  1227  	config, err = initConfig()
  1228  	if err != nil {
  1229  		return "", oci.RuntimeConfig{}, err
  1230  	}
  1231  
  1232  	tomlConf, resolved, err := decodeConfig(configPath)
  1233  	if err != nil {
  1234  		return "", oci.RuntimeConfig{}, err
  1235  	}
  1236  
  1237  	config.Debug = tomlConf.Runtime.Debug
  1238  	if !tomlConf.Runtime.Debug {
  1239  		// If debug is not required, switch back to the original
  1240  		// default log priority, otherwise continue in debug mode.
  1241  		kataUtilsLogger.Logger.Level = originalLoggerLevel
  1242  	}
  1243  
  1244  	config.Trace = tomlConf.Runtime.Tracing
  1245  	tracing = config.Trace
  1246  
  1247  	if tomlConf.Runtime.InterNetworkModel != "" {
  1248  		err = config.InterNetworkModel.SetModel(tomlConf.Runtime.InterNetworkModel)
  1249  		if err != nil {
  1250  			return "", config, err
  1251  		}
  1252  	}
  1253  
  1254  	if !ignoreLogging {
  1255  		err := handleSystemLog("", "")
  1256  		if err != nil {
  1257  			return "", config, err
  1258  		}
  1259  
  1260  		kataUtilsLogger.WithFields(
  1261  			logrus.Fields{
  1262  				"format": "TOML",
  1263  				"file":   resolved,
  1264  			}).Info("loaded configuration")
  1265  	}
  1266  
  1267  	if err := updateRuntimeConfig(resolved, tomlConf, &config, builtIn); err != nil {
  1268  		return "", config, err
  1269  	}
  1270  
  1271  	config.DisableGuestSeccomp = tomlConf.Runtime.DisableGuestSeccomp
  1272  
  1273  	// use no proxy if HypervisorConfig.UseVSock is true
  1274  	if config.HypervisorConfig.UseVSock {
  1275  		kataUtilsLogger.Info("VSOCK supported, configure to not use proxy")
  1276  		config.ProxyType = vc.NoProxyType
  1277  		config.ProxyConfig = vc.ProxyConfig{Debug: config.Debug}
  1278  	}
  1279  
  1280  	config.SandboxCgroupOnly = tomlConf.Runtime.SandboxCgroupOnly
  1281  	config.DisableNewNetNs = tomlConf.Runtime.DisableNewNetNs
  1282  	config.EnableAgentPidNs = tomlConf.Runtime.EnableAgentPidNs
  1283  	if config.EnableAgentPidNs {
  1284  		kataUtilsLogger.Warn("Feature to allow containers to share PID namespace with the agent has been enabled. Please understand this has security implications and should only be used for debug purposes")
  1285  	}
  1286  
  1287  	for _, f := range tomlConf.Runtime.Experimental {
  1288  		feature := exp.Get(f)
  1289  		if feature == nil {
  1290  			return "", config, fmt.Errorf("Unsupported experimental feature %q", f)
  1291  		}
  1292  		config.Experimental = append(config.Experimental, *feature)
  1293  	}
  1294  
  1295  	if err := checkConfig(config); err != nil {
  1296  		return "", config, err
  1297  	}
  1298  
  1299  	return resolved, config, nil
  1300  }
  1301  
  1302  func decodeConfig(configPath string) (tomlConfig, string, error) {
  1303  	var (
  1304  		resolved string
  1305  		tomlConf tomlConfig
  1306  		err      error
  1307  	)
  1308  
  1309  	if configPath == "" {
  1310  		resolved, err = getDefaultConfigFile()
  1311  	} else {
  1312  		resolved, err = ResolvePath(configPath)
  1313  	}
  1314  
  1315  	if err != nil {
  1316  		return tomlConf, "", fmt.Errorf("Cannot find usable config file (%v)", err)
  1317  	}
  1318  
  1319  	configData, err := ioutil.ReadFile(resolved)
  1320  	if err != nil {
  1321  		return tomlConf, resolved, err
  1322  	}
  1323  
  1324  	_, err = toml.Decode(string(configData), &tomlConf)
  1325  	if err != nil {
  1326  		return tomlConf, resolved, err
  1327  	}
  1328  
  1329  	return tomlConf, resolved, nil
  1330  }
  1331  
  1332  // checkConfig checks the validity of the specified config.
  1333  func checkConfig(config oci.RuntimeConfig) error {
  1334  	if err := checkNetNsConfig(config); err != nil {
  1335  		return err
  1336  	}
  1337  
  1338  	if err := checkHypervisorConfig(config.HypervisorConfig); err != nil {
  1339  		return err
  1340  	}
  1341  
  1342  	if err := checkFactoryConfig(config); err != nil {
  1343  		return err
  1344  	}
  1345  
  1346  	return nil
  1347  }
  1348  
  1349  // checkNetNsConfig performs sanity checks on disable_new_netns config.
  1350  // Because it is an expert option and conflicts with some other common configs.
  1351  func checkNetNsConfig(config oci.RuntimeConfig) error {
  1352  	if config.DisableNewNetNs {
  1353  		if config.NetmonConfig.Enable {
  1354  			return fmt.Errorf("config disable_new_netns conflicts with enable_netmon")
  1355  		}
  1356  		if config.InterNetworkModel != vc.NetXConnectNoneModel {
  1357  			return fmt.Errorf("config disable_new_netns only works with 'none' internetworking_model")
  1358  		}
  1359  	} else if shim, ok := config.ShimConfig.(vc.ShimConfig); ok && shim.Trace {
  1360  		// Normally, the shim runs in a separate network namespace.
  1361  		// But when tracing, the shim process needs to be able to talk
  1362  		// to the Jaeger agent running in the host network namespace.
  1363  		return errors.New("Shim tracing requires disable_new_netns for Jaeger agent communication")
  1364  	}
  1365  
  1366  	return nil
  1367  }
  1368  
  1369  // checkFactoryConfig ensures the VM factory configuration is valid.
  1370  func checkFactoryConfig(config oci.RuntimeConfig) error {
  1371  	if config.FactoryConfig.Template {
  1372  		if config.HypervisorConfig.InitrdPath == "" {
  1373  			return errors.New("Factory option enable_template requires an initrd image")
  1374  		}
  1375  	}
  1376  
  1377  	if config.FactoryConfig.VMCacheNumber > 0 {
  1378  		if config.HypervisorType != vc.QemuHypervisor {
  1379  			return errors.New("VM cache just support qemu")
  1380  		}
  1381  		if config.AgentType != vc.KataContainersAgent {
  1382  			return errors.New("VM cache just support kata agent")
  1383  		}
  1384  	}
  1385  
  1386  	return nil
  1387  }
  1388  
  1389  // checkHypervisorConfig performs basic "sanity checks" on the hypervisor
  1390  // config.
  1391  func checkHypervisorConfig(config vc.HypervisorConfig) error {
  1392  	type image struct {
  1393  		path   string
  1394  		initrd bool
  1395  	}
  1396  
  1397  	images := []image{
  1398  		{
  1399  			path:   config.ImagePath,
  1400  			initrd: false,
  1401  		},
  1402  		{
  1403  			path:   config.InitrdPath,
  1404  			initrd: true,
  1405  		},
  1406  	}
  1407  
  1408  	memSizeMB := int64(config.MemorySize)
  1409  
  1410  	if memSizeMB == 0 {
  1411  		return errors.New("VM memory cannot be zero")
  1412  	}
  1413  
  1414  	mb := int64(1024 * 1024)
  1415  
  1416  	for _, image := range images {
  1417  		if image.path == "" {
  1418  			continue
  1419  		}
  1420  
  1421  		imageSizeBytes, err := fileSize(image.path)
  1422  		if err != nil {
  1423  			return err
  1424  		}
  1425  
  1426  		if imageSizeBytes == 0 {
  1427  			return fmt.Errorf("image %q is empty", image.path)
  1428  		}
  1429  
  1430  		if imageSizeBytes > mb {
  1431  			imageSizeMB := imageSizeBytes / mb
  1432  
  1433  			msg := fmt.Sprintf("VM memory (%dMB) smaller than image %q size (%dMB)",
  1434  				memSizeMB, image.path, imageSizeMB)
  1435  			if imageSizeMB >= memSizeMB {
  1436  				if image.initrd {
  1437  					// Initrd's need to be fully read into memory
  1438  					return errors.New(msg)
  1439  				}
  1440  
  1441  				// Images do not need to be fully read
  1442  				// into memory, but it would be highly
  1443  				// unusual to have an image larger
  1444  				// than the amount of memory assigned
  1445  				// to the VM.
  1446  				kataUtilsLogger.Warn(msg)
  1447  			}
  1448  		}
  1449  	}
  1450  
  1451  	return nil
  1452  }
  1453  
  1454  // GetDefaultConfigFilePaths returns a list of paths that will be
  1455  // considered as configuration files in priority order.
  1456  func GetDefaultConfigFilePaths() []string {
  1457  	return []string{
  1458  		// normally below "/etc"
  1459  		defaultSysConfRuntimeConfiguration,
  1460  
  1461  		// normally below "/usr/share"
  1462  		defaultRuntimeConfiguration,
  1463  	}
  1464  }
  1465  
  1466  // getDefaultConfigFile looks in multiple default locations for a
  1467  // configuration file and returns the resolved path for the first file
  1468  // found, or an error if no config files can be found.
  1469  func getDefaultConfigFile() (string, error) {
  1470  	var errs []string
  1471  
  1472  	for _, file := range GetDefaultConfigFilePaths() {
  1473  		resolved, err := ResolvePath(file)
  1474  		if err == nil {
  1475  			return resolved, nil
  1476  		}
  1477  		s := fmt.Sprintf("config file %q unresolvable: %v", file, err)
  1478  		errs = append(errs, s)
  1479  	}
  1480  
  1481  	return "", errors.New(strings.Join(errs, ", "))
  1482  }
  1483  
  1484  // SetConfigOptions will override some of the defaults settings.
  1485  func SetConfigOptions(n, runtimeConfig, sysRuntimeConfig string) {
  1486  	if n != "" {
  1487  		name = n
  1488  	}
  1489  
  1490  	if runtimeConfig != "" {
  1491  		defaultRuntimeConfiguration = runtimeConfig
  1492  	}
  1493  
  1494  	if sysRuntimeConfig != "" {
  1495  		defaultSysConfRuntimeConfiguration = sysRuntimeConfig
  1496  	}
  1497  }