gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/pkg/katautils/config_test.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  	"bytes"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"os"
    14  	"path"
    15  	"path/filepath"
    16  	"reflect"
    17  	goruntime "runtime"
    18  	"strings"
    19  	"syscall"
    20  	"testing"
    21  
    22  	ktu "github.com/kata-containers/runtime/pkg/katatestutils"
    23  	vc "github.com/kata-containers/runtime/virtcontainers"
    24  	"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
    25  	"github.com/kata-containers/runtime/virtcontainers/utils"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  var (
    30  	hypervisorDebug = false
    31  	proxyDebug      = false
    32  	runtimeDebug    = false
    33  	runtimeTrace    = false
    34  	shimDebug       = false
    35  	netmonDebug     = false
    36  	agentDebug      = false
    37  	agentTrace      = false
    38  )
    39  
    40  type testRuntimeConfig struct {
    41  	RuntimeConfig     oci.RuntimeConfig
    42  	RuntimeConfigFile string
    43  	ConfigPath        string
    44  	ConfigPathLink    string
    45  	LogDir            string
    46  	LogPath           string
    47  }
    48  
    49  func createConfig(configPath string, fileData string) error {
    50  
    51  	err := ioutil.WriteFile(configPath, []byte(fileData), testFileMode)
    52  	if err != nil {
    53  		fmt.Fprintf(os.Stderr, "Unable to create config file %s %v\n", configPath, err)
    54  		return err
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  // createAllRuntimeConfigFiles creates all files necessary to call
    61  // loadConfiguration().
    62  func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConfig, err error) {
    63  	if dir == "" {
    64  		return config, fmt.Errorf("BUG: need directory")
    65  	}
    66  
    67  	if hypervisor == "" {
    68  		return config, fmt.Errorf("BUG: need hypervisor")
    69  	}
    70  
    71  	hypervisorPath := path.Join(dir, "hypervisor")
    72  	kernelPath := path.Join(dir, "kernel")
    73  	kernelParams := "foo=bar xyz"
    74  	imagePath := path.Join(dir, "image")
    75  	shimPath := path.Join(dir, "shim")
    76  	proxyPath := path.Join(dir, "proxy")
    77  	netmonPath := path.Join(dir, "netmon")
    78  	logDir := path.Join(dir, "logs")
    79  	logPath := path.Join(logDir, "runtime.log")
    80  	machineType := "machineType"
    81  	disableBlockDevice := true
    82  	blockDeviceDriver := "virtio-scsi"
    83  	enableIOThreads := true
    84  	hotplugVFIOOnRootBus := true
    85  	pcieRootPort := uint32(2)
    86  	disableNewNetNs := false
    87  	sharedFS := "virtio-9p"
    88  
    89  	configFileOptions := ktu.RuntimeConfigOptions{
    90  		Hypervisor:           "qemu",
    91  		HypervisorPath:       hypervisorPath,
    92  		KernelPath:           kernelPath,
    93  		ImagePath:            imagePath,
    94  		KernelParams:         kernelParams,
    95  		MachineType:          machineType,
    96  		ShimPath:             shimPath,
    97  		ProxyPath:            proxyPath,
    98  		NetmonPath:           netmonPath,
    99  		LogPath:              logPath,
   100  		DefaultGuestHookPath: defaultGuestHookPath,
   101  		DisableBlock:         disableBlockDevice,
   102  		BlockDeviceDriver:    blockDeviceDriver,
   103  		EnableIOThreads:      enableIOThreads,
   104  		HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
   105  		PCIeRootPort:         pcieRootPort,
   106  		DisableNewNetNs:      disableNewNetNs,
   107  		DefaultVCPUCount:     defaultVCPUCount,
   108  		DefaultMaxVCPUCount:  defaultMaxVCPUCount,
   109  		DefaultMemSize:       defaultMemSize,
   110  		DefaultMsize9p:       defaultMsize9p,
   111  		HypervisorDebug:      hypervisorDebug,
   112  		RuntimeDebug:         runtimeDebug,
   113  		RuntimeTrace:         runtimeTrace,
   114  		ProxyDebug:           proxyDebug,
   115  		ShimDebug:            shimDebug,
   116  		NetmonDebug:          netmonDebug,
   117  		AgentDebug:           agentDebug,
   118  		AgentTrace:           agentTrace,
   119  		SharedFS:             sharedFS,
   120  	}
   121  
   122  	runtimeConfigFileData := ktu.MakeRuntimeConfigFileData(configFileOptions)
   123  
   124  	configPath := path.Join(dir, "runtime.toml")
   125  	err = createConfig(configPath, runtimeConfigFileData)
   126  	if err != nil {
   127  		return config, err
   128  	}
   129  
   130  	configPathLink := path.Join(filepath.Dir(configPath), "link-to-configuration.toml")
   131  
   132  	// create a link to the config file
   133  	err = syscall.Symlink(configPath, configPathLink)
   134  	if err != nil {
   135  		return config, err
   136  	}
   137  
   138  	files := []string{hypervisorPath, kernelPath, imagePath, shimPath, proxyPath}
   139  
   140  	for _, file := range files {
   141  		// create the resource (which must be >0 bytes)
   142  		err := WriteFile(file, "foo", testFileMode)
   143  		if err != nil {
   144  			return config, err
   145  		}
   146  	}
   147  
   148  	hypervisorConfig := vc.HypervisorConfig{
   149  		HypervisorPath:        hypervisorPath,
   150  		KernelPath:            kernelPath,
   151  		ImagePath:             imagePath,
   152  		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)),
   153  		HypervisorMachineType: machineType,
   154  		NumVCPUs:              defaultVCPUCount,
   155  		DefaultMaxVCPUs:       uint32(goruntime.NumCPU()),
   156  		MemorySize:            defaultMemSize,
   157  		DisableBlockDeviceUse: disableBlockDevice,
   158  		BlockDeviceDriver:     defaultBlockDeviceDriver,
   159  		DefaultBridges:        defaultBridgesCount,
   160  		Mlock:                 !defaultEnableSwap,
   161  		EnableIOThreads:       enableIOThreads,
   162  		HotplugVFIOOnRootBus:  hotplugVFIOOnRootBus,
   163  		PCIeRootPort:          pcieRootPort,
   164  		Msize9p:               defaultMsize9p,
   165  		MemSlots:              defaultMemSlots,
   166  		EntropySource:         defaultEntropySource,
   167  		GuestHookPath:         defaultGuestHookPath,
   168  		VhostUserStorePath:    defaultVhostUserStorePath,
   169  		SharedFS:              sharedFS,
   170  		VirtioFSDaemon:        "/path/to/virtiofsd",
   171  		VirtioFSCache:         defaultVirtioFSCacheMode,
   172  	}
   173  
   174  	agentConfig := vc.KataAgentConfig{}
   175  
   176  	proxyConfig := vc.ProxyConfig{
   177  		Path: proxyPath,
   178  	}
   179  
   180  	shimConfig := vc.ShimConfig{
   181  		Path: shimPath,
   182  	}
   183  
   184  	netmonConfig := vc.NetmonConfig{
   185  		Path:   netmonPath,
   186  		Debug:  false,
   187  		Enable: false,
   188  	}
   189  
   190  	factoryConfig := oci.FactoryConfig{
   191  		TemplatePath:    defaultTemplatePath,
   192  		VMCacheEndpoint: defaultVMCacheEndpoint,
   193  	}
   194  
   195  	runtimeConfig := oci.RuntimeConfig{
   196  		HypervisorType:   defaultHypervisor,
   197  		HypervisorConfig: hypervisorConfig,
   198  
   199  		AgentType:   defaultAgent,
   200  		AgentConfig: agentConfig,
   201  
   202  		ProxyType:   defaultProxy,
   203  		ProxyConfig: proxyConfig,
   204  
   205  		ShimType:   defaultShim,
   206  		ShimConfig: shimConfig,
   207  
   208  		NetmonConfig:    netmonConfig,
   209  		DisableNewNetNs: disableNewNetNs,
   210  
   211  		FactoryConfig: factoryConfig,
   212  	}
   213  
   214  	err = SetKernelParams(&runtimeConfig)
   215  	if err != nil {
   216  		return config, err
   217  	}
   218  
   219  	config = testRuntimeConfig{
   220  		RuntimeConfig:     runtimeConfig,
   221  		RuntimeConfigFile: configPath,
   222  		ConfigPath:        configPath,
   223  		ConfigPathLink:    configPathLink,
   224  		LogDir:            logDir,
   225  		LogPath:           logPath,
   226  	}
   227  
   228  	return config, nil
   229  }
   230  
   231  // testLoadConfiguration accepts an optional function that can be used
   232  // to modify the test: if a function is specified, it indicates if the
   233  // subsequent call to loadConfiguration() is expected to fail by
   234  // returning a bool. If the function itself fails, that is considered an
   235  // error.
   236  func testLoadConfiguration(t *testing.T, dir string,
   237  	fn func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error)) {
   238  	subDir := path.Join(dir, "test")
   239  
   240  	for _, hypervisor := range []string{"qemu"} {
   241  	Loop:
   242  		for _, ignoreLogging := range []bool{true, false} {
   243  			err := os.RemoveAll(subDir)
   244  			assert.NoError(t, err)
   245  
   246  			err = os.MkdirAll(subDir, testDirMode)
   247  			assert.NoError(t, err)
   248  
   249  			testConfig, err := createAllRuntimeConfigFiles(subDir, hypervisor)
   250  			assert.NoError(t, err)
   251  
   252  			configFiles := []string{testConfig.ConfigPath, testConfig.ConfigPathLink, ""}
   253  
   254  			// override
   255  			defaultRuntimeConfiguration = testConfig.ConfigPath
   256  			defaultSysConfRuntimeConfiguration = ""
   257  
   258  			for _, file := range configFiles {
   259  				var err error
   260  				expectFail := false
   261  
   262  				if fn != nil {
   263  					expectFail, err = fn(testConfig, file, ignoreLogging)
   264  					assert.NoError(t, err)
   265  				}
   266  
   267  				resolvedConfigPath, config, err := LoadConfiguration(file, ignoreLogging, false)
   268  				if expectFail {
   269  					assert.Error(t, err)
   270  
   271  					// no point proceeding in the error scenario.
   272  					break Loop
   273  				} else {
   274  					assert.NoError(t, err)
   275  				}
   276  
   277  				if file == "" {
   278  					assert.Equal(t, defaultRuntimeConfiguration, resolvedConfigPath)
   279  				} else {
   280  					assert.Equal(t, testConfig.ConfigPath, resolvedConfigPath)
   281  				}
   282  
   283  				assert.Equal(t, defaultRuntimeConfiguration, resolvedConfigPath)
   284  				result := reflect.DeepEqual(config, testConfig.RuntimeConfig)
   285  				if !result {
   286  					t.Fatalf("Expected\n%+v\nGot\n%+v", config, testConfig.RuntimeConfig)
   287  				}
   288  				assert.True(t, result)
   289  
   290  				err = os.RemoveAll(testConfig.LogDir)
   291  				assert.NoError(t, err)
   292  			}
   293  		}
   294  	}
   295  }
   296  
   297  func TestConfigLoadConfiguration(t *testing.T) {
   298  	tmpdir, err := ioutil.TempDir(testDir, "load-config-")
   299  	assert.NoError(t, err)
   300  	defer os.RemoveAll(tmpdir)
   301  
   302  	testLoadConfiguration(t, tmpdir, nil)
   303  }
   304  
   305  func TestConfigLoadConfigurationFailBrokenSymLink(t *testing.T) {
   306  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   307  	assert.NoError(t, err)
   308  	defer os.RemoveAll(tmpdir)
   309  
   310  	testLoadConfiguration(t, tmpdir,
   311  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   312  			expectFail := false
   313  
   314  			if configFile == config.ConfigPathLink {
   315  				// break the symbolic link
   316  				err = os.Remove(config.ConfigPathLink)
   317  				if err != nil {
   318  					return expectFail, err
   319  				}
   320  
   321  				expectFail = true
   322  			}
   323  
   324  			return expectFail, nil
   325  		})
   326  }
   327  
   328  func TestConfigLoadConfigurationFailSymLinkLoop(t *testing.T) {
   329  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   330  	assert.NoError(t, err)
   331  	defer os.RemoveAll(tmpdir)
   332  
   333  	testLoadConfiguration(t, tmpdir,
   334  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   335  			expectFail := false
   336  
   337  			if configFile == config.ConfigPathLink {
   338  				// remove the config file
   339  				err = os.Remove(config.ConfigPath)
   340  				if err != nil {
   341  					return expectFail, err
   342  				}
   343  
   344  				// now, create a sym-link loop
   345  				err := os.Symlink(config.ConfigPathLink, config.ConfigPath)
   346  				if err != nil {
   347  					return expectFail, err
   348  				}
   349  
   350  				expectFail = true
   351  			}
   352  
   353  			return expectFail, nil
   354  		})
   355  }
   356  
   357  func TestConfigLoadConfigurationFailMissingHypervisor(t *testing.T) {
   358  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   359  	assert.NoError(t, err)
   360  	defer os.RemoveAll(tmpdir)
   361  
   362  	testLoadConfiguration(t, tmpdir,
   363  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   364  			expectFail := true
   365  
   366  			err = os.Remove(config.RuntimeConfig.HypervisorConfig.HypervisorPath)
   367  			if err != nil {
   368  				return expectFail, err
   369  			}
   370  
   371  			return expectFail, nil
   372  		})
   373  }
   374  
   375  func TestConfigLoadConfigurationFailMissingImage(t *testing.T) {
   376  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   377  	assert.NoError(t, err)
   378  	defer os.RemoveAll(tmpdir)
   379  
   380  	testLoadConfiguration(t, tmpdir,
   381  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   382  			expectFail := true
   383  
   384  			err = os.Remove(config.RuntimeConfig.HypervisorConfig.ImagePath)
   385  			if err != nil {
   386  				return expectFail, err
   387  			}
   388  
   389  			return expectFail, nil
   390  		})
   391  }
   392  
   393  func TestConfigLoadConfigurationFailMissingKernel(t *testing.T) {
   394  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   395  	assert.NoError(t, err)
   396  	defer os.RemoveAll(tmpdir)
   397  
   398  	testLoadConfiguration(t, tmpdir,
   399  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   400  			expectFail := true
   401  
   402  			err = os.Remove(config.RuntimeConfig.HypervisorConfig.KernelPath)
   403  			if err != nil {
   404  				return expectFail, err
   405  			}
   406  
   407  			return expectFail, nil
   408  		})
   409  }
   410  
   411  func TestConfigLoadConfigurationFailMissingShim(t *testing.T) {
   412  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   413  	assert.NoError(t, err)
   414  	defer os.RemoveAll(tmpdir)
   415  
   416  	testLoadConfiguration(t, tmpdir,
   417  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   418  			expectFail := true
   419  
   420  			shimConfig, ok := config.RuntimeConfig.ShimConfig.(vc.ShimConfig)
   421  			if !ok {
   422  				return expectFail, fmt.Errorf("cannot determine shim config")
   423  			}
   424  			err = os.Remove(shimConfig.Path)
   425  			if err != nil {
   426  				return expectFail, err
   427  			}
   428  
   429  			return expectFail, nil
   430  		})
   431  }
   432  
   433  func TestConfigLoadConfigurationFailUnreadableConfig(t *testing.T) {
   434  	if tc.NotValid(ktu.NeedNonRoot()) {
   435  		t.Skip(ktu.TestDisabledNeedNonRoot)
   436  	}
   437  
   438  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   439  	assert.NoError(t, err)
   440  	defer os.RemoveAll(tmpdir)
   441  
   442  	testLoadConfiguration(t, tmpdir,
   443  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   444  			expectFail := true
   445  
   446  			// make file unreadable by non-root user
   447  			err = os.Chmod(config.ConfigPath, 0000)
   448  			if err != nil {
   449  				return expectFail, err
   450  			}
   451  
   452  			return expectFail, nil
   453  		})
   454  }
   455  
   456  func TestConfigLoadConfigurationFailTOMLConfigFileInvalidContents(t *testing.T) {
   457  	if tc.NotValid(ktu.NeedNonRoot()) {
   458  		t.Skip(ktu.TestDisabledNeedNonRoot)
   459  	}
   460  
   461  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   462  	assert.NoError(t, err)
   463  	defer os.RemoveAll(tmpdir)
   464  
   465  	testLoadConfiguration(t, tmpdir,
   466  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   467  			expectFail := true
   468  
   469  			err := createFile(config.ConfigPath,
   470  				`<?xml version="1.0"?>
   471  			<foo>I am not TOML! ;-)</foo>
   472  			<bar>I am invalid XML!`)
   473  
   474  			if err != nil {
   475  				return expectFail, err
   476  			}
   477  
   478  			return expectFail, nil
   479  		})
   480  }
   481  
   482  func TestConfigLoadConfigurationFailTOMLConfigFileDuplicatedData(t *testing.T) {
   483  	if tc.NotValid(ktu.NeedNonRoot()) {
   484  		t.Skip(ktu.TestDisabledNeedNonRoot)
   485  	}
   486  
   487  	tmpdir, err := ioutil.TempDir(testDir, "runtime-config-")
   488  	assert.NoError(t, err)
   489  	defer os.RemoveAll(tmpdir)
   490  
   491  	testLoadConfiguration(t, tmpdir,
   492  		func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
   493  			expectFail := true
   494  
   495  			text, err := GetFileContents(config.ConfigPath)
   496  			if err != nil {
   497  				return expectFail, err
   498  			}
   499  
   500  			// create a config file containing two sets of
   501  			// data.
   502  			err = createFile(config.ConfigPath, fmt.Sprintf("%s\n%s\n", text, text))
   503  			if err != nil {
   504  				return expectFail, err
   505  			}
   506  
   507  			return expectFail, nil
   508  		})
   509  }
   510  
   511  func TestMinimalRuntimeConfig(t *testing.T) {
   512  	dir, err := ioutil.TempDir(testDir, "minimal-runtime-config-")
   513  	if err != nil {
   514  		t.Fatal(err)
   515  	}
   516  	defer os.RemoveAll(dir)
   517  
   518  	shimPath := path.Join(dir, "shim")
   519  	proxyPath := path.Join(dir, "proxy")
   520  	hypervisorPath := path.Join(dir, "hypervisor")
   521  	defaultHypervisorPath = hypervisorPath
   522  	jailerPath := path.Join(dir, "jailer")
   523  	defaultJailerPath = jailerPath
   524  	netmonPath := path.Join(dir, "netmon")
   525  
   526  	imagePath := path.Join(dir, "image.img")
   527  	initrdPath := path.Join(dir, "initrd.img")
   528  
   529  	kernelPath := path.Join(dir, "kernel")
   530  
   531  	savedDefaultImagePath := defaultImagePath
   532  	savedDefaultInitrdPath := defaultInitrdPath
   533  	savedDefaultHypervisorPath := defaultHypervisorPath
   534  	savedDefaultJailerPath := defaultJailerPath
   535  	savedDefaultKernelPath := defaultKernelPath
   536  
   537  	defer func() {
   538  		defaultImagePath = savedDefaultImagePath
   539  		defaultInitrdPath = savedDefaultInitrdPath
   540  		defaultHypervisorPath = savedDefaultHypervisorPath
   541  		defaultJailerPath = savedDefaultJailerPath
   542  		defaultKernelPath = savedDefaultKernelPath
   543  	}()
   544  
   545  	// Temporarily change the defaults to avoid this test using the real
   546  	// resource files that might be installed on the system!
   547  	defaultImagePath = imagePath
   548  	defaultInitrdPath = initrdPath
   549  	defaultHypervisorPath = hypervisorPath
   550  	defaultJailerPath = jailerPath
   551  	defaultKernelPath = kernelPath
   552  
   553  	for _, file := range []string{defaultImagePath, defaultInitrdPath, defaultHypervisorPath, defaultJailerPath, defaultKernelPath} {
   554  		err = WriteFile(file, "foo", testFileMode)
   555  		if err != nil {
   556  			t.Fatal(err)
   557  		}
   558  	}
   559  
   560  	runtimeMinimalConfig := `
   561  	# Runtime configuration file
   562  
   563  	[proxy.kata]
   564  	path = "` + proxyPath + `"
   565  
   566  	[shim.kata]
   567  	path = "` + shimPath + `"
   568  
   569  	[agent.kata]
   570  
   571  	[netmon]
   572  	path = "` + netmonPath + `"
   573  `
   574  
   575  	configPath := path.Join(dir, "runtime.toml")
   576  	err = createConfig(configPath, runtimeMinimalConfig)
   577  	if err != nil {
   578  		t.Fatal(err)
   579  	}
   580  
   581  	_, config, err := LoadConfiguration(configPath, false, false)
   582  	if err == nil {
   583  		t.Fatalf("Expected loadConfiguration to fail as shim path does not exist: %+v", config)
   584  	}
   585  
   586  	err = createEmptyFile(shimPath)
   587  	if err != nil {
   588  		t.Error(err)
   589  	}
   590  
   591  	err = createEmptyFile(proxyPath)
   592  	if err != nil {
   593  		t.Error(err)
   594  	}
   595  
   596  	err = createEmptyFile(hypervisorPath)
   597  	if err != nil {
   598  		t.Error(err)
   599  	}
   600  
   601  	err = createEmptyFile(jailerPath)
   602  	if err != nil {
   603  		t.Error(err)
   604  	}
   605  
   606  	err = createEmptyFile(netmonPath)
   607  	if err != nil {
   608  		t.Error(err)
   609  	}
   610  
   611  	_, config, err = LoadConfiguration(configPath, false, false)
   612  	if err != nil {
   613  		t.Fatal(err)
   614  	}
   615  
   616  	expectedHypervisorConfig := vc.HypervisorConfig{
   617  		HypervisorPath:        defaultHypervisorPath,
   618  		JailerPath:            defaultJailerPath,
   619  		KernelPath:            defaultKernelPath,
   620  		ImagePath:             defaultImagePath,
   621  		InitrdPath:            defaultInitrdPath,
   622  		HypervisorMachineType: defaultMachineType,
   623  		NumVCPUs:              defaultVCPUCount,
   624  		DefaultMaxVCPUs:       defaultMaxVCPUCount,
   625  		MemorySize:            defaultMemSize,
   626  		DisableBlockDeviceUse: defaultDisableBlockDeviceUse,
   627  		DefaultBridges:        defaultBridgesCount,
   628  		Mlock:                 !defaultEnableSwap,
   629  		BlockDeviceDriver:     defaultBlockDeviceDriver,
   630  		Msize9p:               defaultMsize9p,
   631  		GuestHookPath:         defaultGuestHookPath,
   632  		VhostUserStorePath:    defaultVhostUserStorePath,
   633  		VirtioFSCache:         defaultVirtioFSCacheMode,
   634  	}
   635  
   636  	expectedAgentConfig := vc.KataAgentConfig{}
   637  
   638  	expectedProxyConfig := vc.ProxyConfig{
   639  		Path: proxyPath,
   640  	}
   641  
   642  	expectedShimConfig := vc.ShimConfig{
   643  		Path: shimPath,
   644  	}
   645  
   646  	expectedNetmonConfig := vc.NetmonConfig{
   647  		Path:   netmonPath,
   648  		Debug:  false,
   649  		Enable: false,
   650  	}
   651  
   652  	expectedFactoryConfig := oci.FactoryConfig{
   653  		TemplatePath:    defaultTemplatePath,
   654  		VMCacheEndpoint: defaultVMCacheEndpoint,
   655  	}
   656  
   657  	expectedConfig := oci.RuntimeConfig{
   658  		HypervisorType:   defaultHypervisor,
   659  		HypervisorConfig: expectedHypervisorConfig,
   660  
   661  		AgentType:   defaultAgent,
   662  		AgentConfig: expectedAgentConfig,
   663  
   664  		ProxyType:   defaultProxy,
   665  		ProxyConfig: expectedProxyConfig,
   666  
   667  		ShimType:   defaultShim,
   668  		ShimConfig: expectedShimConfig,
   669  
   670  		NetmonConfig: expectedNetmonConfig,
   671  
   672  		FactoryConfig: expectedFactoryConfig,
   673  	}
   674  	err = SetKernelParams(&expectedConfig)
   675  	if err != nil {
   676  		t.Fatal(err)
   677  	}
   678  
   679  	if reflect.DeepEqual(config, expectedConfig) == false {
   680  		t.Fatalf("Got %+v\n expecting %+v", config, expectedConfig)
   681  	}
   682  }
   683  
   684  func TestMinimalRuntimeConfigWithVsock(t *testing.T) {
   685  	dir, err := ioutil.TempDir(testDir, "minimal-runtime-config-")
   686  	if err != nil {
   687  		t.Fatal(err)
   688  	}
   689  	defer os.RemoveAll(dir)
   690  
   691  	imagePath := path.Join(dir, "image.img")
   692  	initrdPath := path.Join(dir, "initrd.img")
   693  	proxyPath := path.Join(dir, "proxy")
   694  	shimPath := path.Join(dir, "shim")
   695  	hypervisorPath := path.Join(dir, "hypervisor")
   696  	kernelPath := path.Join(dir, "kernel")
   697  
   698  	savedDefaultImagePath := defaultImagePath
   699  	savedDefaultInitrdPath := defaultInitrdPath
   700  	savedDefaultHypervisorPath := defaultHypervisorPath
   701  	savedDefaultKernelPath := defaultKernelPath
   702  
   703  	defer func() {
   704  		defaultImagePath = savedDefaultImagePath
   705  		defaultInitrdPath = savedDefaultInitrdPath
   706  		defaultHypervisorPath = savedDefaultHypervisorPath
   707  		defaultKernelPath = savedDefaultKernelPath
   708  	}()
   709  
   710  	// Temporarily change the defaults to avoid this test using the real
   711  	// resource files that might be installed on the system!
   712  	defaultImagePath = imagePath
   713  	defaultInitrdPath = initrdPath
   714  	defaultHypervisorPath = hypervisorPath
   715  	defaultKernelPath = kernelPath
   716  
   717  	for _, file := range []string{proxyPath, shimPath, hypervisorPath, kernelPath, imagePath} {
   718  		err = WriteFile(file, "foo", testFileMode)
   719  		if err != nil {
   720  			t.Fatal(err)
   721  		}
   722  	}
   723  
   724  	// minimal config with vsock enabled
   725  	runtimeMinimalConfig := `
   726  	# Runtime configuration file
   727  	[hypervisor.qemu]
   728  	use_vsock = true
   729  	image = "` + imagePath + `"
   730  
   731  	[proxy.kata]
   732  	path = "` + proxyPath + `"
   733  
   734  	[shim.kata]
   735  	path = "` + shimPath + `"
   736  
   737  	[agent.kata]
   738  `
   739  	orgVHostVSockDevicePath := utils.VHostVSockDevicePath
   740  	defer func() {
   741  		utils.VHostVSockDevicePath = orgVHostVSockDevicePath
   742  	}()
   743  	utils.VHostVSockDevicePath = "/dev/null"
   744  
   745  	configPath := path.Join(dir, "runtime.toml")
   746  	err = createConfig(configPath, runtimeMinimalConfig)
   747  	if err != nil {
   748  		t.Fatal(err)
   749  	}
   750  
   751  	_, config, err := LoadConfiguration(configPath, false, false)
   752  	if err != nil {
   753  		t.Fatal(err)
   754  	}
   755  
   756  	if config.ProxyType != vc.NoProxyType {
   757  		t.Fatalf("Proxy type must be NoProxy, got %+v", config.ProxyType)
   758  	}
   759  
   760  	if !reflect.DeepEqual(config.ProxyConfig, vc.ProxyConfig{}) {
   761  		t.Fatalf("Got %+v\n expecting %+v", config.ProxyConfig, vc.ProxyConfig{})
   762  	}
   763  
   764  	if config.HypervisorConfig.UseVSock != true {
   765  		t.Fatalf("use_vsock must be true, got %v", config.HypervisorConfig.UseVSock)
   766  	}
   767  }
   768  
   769  func TestNewQemuHypervisorConfig(t *testing.T) {
   770  	dir, err := ioutil.TempDir(testDir, "hypervisor-config-")
   771  	if err != nil {
   772  		t.Fatal(err)
   773  	}
   774  	defer os.RemoveAll(dir)
   775  
   776  	hypervisorPath := path.Join(dir, "hypervisor")
   777  	kernelPath := path.Join(dir, "kernel")
   778  	imagePath := path.Join(dir, "image")
   779  	machineType := "machineType"
   780  	disableBlock := true
   781  	enableIOThreads := true
   782  	hotplugVFIOOnRootBus := true
   783  	pcieRootPort := uint32(2)
   784  	orgVHostVSockDevicePath := utils.VHostVSockDevicePath
   785  	defer func() {
   786  		utils.VHostVSockDevicePath = orgVHostVSockDevicePath
   787  	}()
   788  	utils.VHostVSockDevicePath = "/dev/abc/xyz"
   789  
   790  	hypervisor := hypervisor{
   791  		Path:                  hypervisorPath,
   792  		Kernel:                kernelPath,
   793  		Image:                 imagePath,
   794  		MachineType:           machineType,
   795  		DisableBlockDeviceUse: disableBlock,
   796  		EnableIOThreads:       enableIOThreads,
   797  		HotplugVFIOOnRootBus:  hotplugVFIOOnRootBus,
   798  		PCIeRootPort:          pcieRootPort,
   799  		UseVSock:              true,
   800  	}
   801  
   802  	files := []string{hypervisorPath, kernelPath, imagePath}
   803  	filesLen := len(files)
   804  
   805  	for i, file := range files {
   806  		_, err := newQemuHypervisorConfig(hypervisor)
   807  		if err == nil {
   808  			t.Fatalf("Expected newQemuHypervisorConfig to fail as not all paths exist (not created %v)",
   809  				strings.Join(files[i:filesLen], ","))
   810  		}
   811  
   812  		// create the resource
   813  		err = createEmptyFile(file)
   814  		if err != nil {
   815  			t.Error(err)
   816  		}
   817  	}
   818  
   819  	// falling back to legacy serial port
   820  	config, err := newQemuHypervisorConfig(hypervisor)
   821  	if err != nil {
   822  		t.Fatal(err)
   823  	}
   824  
   825  	utils.VHostVSockDevicePath = "/dev/null"
   826  
   827  	// all paths exist now
   828  	config, err = newQemuHypervisorConfig(hypervisor)
   829  	if err != nil {
   830  		t.Fatal(err)
   831  	}
   832  
   833  	if config.HypervisorPath != hypervisor.Path {
   834  		t.Errorf("Expected hypervisor path %v, got %v", hypervisor.Path, config.HypervisorPath)
   835  	}
   836  
   837  	if config.KernelPath != hypervisor.Kernel {
   838  		t.Errorf("Expected kernel path %v, got %v", hypervisor.Kernel, config.KernelPath)
   839  	}
   840  
   841  	if config.ImagePath != hypervisor.Image {
   842  		t.Errorf("Expected image path %v, got %v", hypervisor.Image, config.ImagePath)
   843  	}
   844  
   845  	if config.DisableBlockDeviceUse != disableBlock {
   846  		t.Errorf("Expected value for disable block usage %v, got %v", disableBlock, config.DisableBlockDeviceUse)
   847  	}
   848  
   849  	if config.EnableIOThreads != enableIOThreads {
   850  		t.Errorf("Expected value for enable IOThreads  %v, got %v", enableIOThreads, config.EnableIOThreads)
   851  	}
   852  
   853  	if config.HotplugVFIOOnRootBus != hotplugVFIOOnRootBus {
   854  		t.Errorf("Expected value for HotplugVFIOOnRootBus %v, got %v", hotplugVFIOOnRootBus, config.HotplugVFIOOnRootBus)
   855  	}
   856  
   857  	if config.PCIeRootPort != pcieRootPort {
   858  		t.Errorf("Expected value for PCIeRootPort %v, got %v", pcieRootPort, config.PCIeRootPort)
   859  	}
   860  }
   861  
   862  func TestNewQemuHypervisorConfigImageAndInitrd(t *testing.T) {
   863  	assert := assert.New(t)
   864  
   865  	tmpdir, err := ioutil.TempDir(testDir, "")
   866  	assert.NoError(err)
   867  	defer os.RemoveAll(tmpdir)
   868  
   869  	imagePath := filepath.Join(tmpdir, "image")
   870  	initrdPath := filepath.Join(tmpdir, "initrd")
   871  	hypervisorPath := path.Join(tmpdir, "hypervisor")
   872  	kernelPath := path.Join(tmpdir, "kernel")
   873  
   874  	for _, file := range []string{imagePath, initrdPath, hypervisorPath, kernelPath} {
   875  		err = createEmptyFile(file)
   876  		assert.NoError(err)
   877  	}
   878  
   879  	machineType := "machineType"
   880  	disableBlock := true
   881  	enableIOThreads := true
   882  	hotplugVFIOOnRootBus := true
   883  	pcieRootPort := uint32(2)
   884  
   885  	hypervisor := hypervisor{
   886  		Path:                  hypervisorPath,
   887  		Kernel:                kernelPath,
   888  		Image:                 imagePath,
   889  		Initrd:                initrdPath,
   890  		MachineType:           machineType,
   891  		DisableBlockDeviceUse: disableBlock,
   892  		EnableIOThreads:       enableIOThreads,
   893  		HotplugVFIOOnRootBus:  hotplugVFIOOnRootBus,
   894  		PCIeRootPort:          pcieRootPort,
   895  	}
   896  
   897  	_, err = newQemuHypervisorConfig(hypervisor)
   898  
   899  	// specifying both an image+initrd is invalid
   900  	assert.Error(err)
   901  }
   902  
   903  func TestNewClhHypervisorConfig(t *testing.T) {
   904  
   905  	assert := assert.New(t)
   906  
   907  	tmpdir, err := ioutil.TempDir(testDir, "")
   908  	assert.NoError(err)
   909  	defer os.RemoveAll(tmpdir)
   910  
   911  	hypervisorPath := path.Join(tmpdir, "hypervisor")
   912  	kernelPath := path.Join(tmpdir, "kernel")
   913  	imagePath := path.Join(tmpdir, "image")
   914  	virtioFsDaemon := path.Join(tmpdir, "virtiofsd")
   915  
   916  	for _, file := range []string{imagePath, hypervisorPath, kernelPath, virtioFsDaemon} {
   917  		err = createEmptyFile(file)
   918  		assert.NoError(err)
   919  	}
   920  
   921  	hypervisor := hypervisor{
   922  		Path:           hypervisorPath,
   923  		Kernel:         kernelPath,
   924  		Image:          imagePath,
   925  		VirtioFSDaemon: virtioFsDaemon,
   926  		VirtioFSCache:  "always",
   927  	}
   928  	config, err := newClhHypervisorConfig(hypervisor)
   929  	if err != nil {
   930  		t.Fatal(err)
   931  	}
   932  
   933  	if config.HypervisorPath != hypervisor.Path {
   934  		t.Errorf("Expected hypervisor path %v, got %v", hypervisor.Path, config.HypervisorPath)
   935  	}
   936  
   937  	if config.KernelPath != hypervisor.Kernel {
   938  		t.Errorf("Expected kernel path %v, got %v", hypervisor.Kernel, config.KernelPath)
   939  	}
   940  
   941  	if config.ImagePath != hypervisor.Image {
   942  		t.Errorf("Expected image path %v, got %v", hypervisor.Image, config.ImagePath)
   943  	}
   944  
   945  	if config.ImagePath != hypervisor.Image {
   946  		t.Errorf("Expected image path %v, got %v", hypervisor.Image, config.ImagePath)
   947  	}
   948  
   949  	if config.UseVSock != true {
   950  		t.Errorf("Expected UseVSock %v, got %v", true, config.UseVSock)
   951  	}
   952  
   953  	if config.DisableVhostNet != true {
   954  		t.Errorf("Expected DisableVhostNet %v, got %v", true, config.DisableVhostNet)
   955  	}
   956  
   957  	if config.VirtioFSCache != "always" {
   958  		t.Errorf("Expected VirtioFSCache %v, got %v", true, config.VirtioFSCache)
   959  	}
   960  
   961  }
   962  
   963  func TestNewShimConfig(t *testing.T) {
   964  	dir, err := ioutil.TempDir(testDir, "shim-config-")
   965  	if err != nil {
   966  		t.Fatal(err)
   967  	}
   968  	defer os.RemoveAll(dir)
   969  
   970  	shimPath := path.Join(dir, "shim")
   971  
   972  	shim := shim{
   973  		Path: shimPath,
   974  	}
   975  
   976  	_, err = newShimConfig(shim)
   977  	if err == nil {
   978  		t.Fatalf("Expected newShimConfig to fail as no paths exist")
   979  	}
   980  
   981  	err = createEmptyFile(shimPath)
   982  	if err != nil {
   983  		t.Error(err)
   984  	}
   985  
   986  	shConfig, err := newShimConfig(shim)
   987  	if err != nil {
   988  		t.Fatalf("newShimConfig failed unexpectedly: %v", err)
   989  	}
   990  
   991  	if shConfig.Path != shimPath {
   992  		t.Errorf("Expected shim path %v, got %v", shimPath, shConfig.Path)
   993  	}
   994  }
   995  
   996  func TestHypervisorDefaults(t *testing.T) {
   997  	assert := assert.New(t)
   998  
   999  	numCPUs := goruntime.NumCPU()
  1000  
  1001  	h := hypervisor{}
  1002  
  1003  	assert.Equal(h.machineType(), defaultMachineType, "default hypervisor machine type wrong")
  1004  	assert.Equal(h.defaultVCPUs(), defaultVCPUCount, "default vCPU number is wrong")
  1005  	assert.Equal(h.defaultMaxVCPUs(), uint32(numCPUs), "default max vCPU number is wrong")
  1006  	assert.Equal(h.defaultMemSz(), defaultMemSize, "default memory size is wrong")
  1007  
  1008  	machineType := "foo"
  1009  	h.MachineType = machineType
  1010  	assert.Equal(h.machineType(), machineType, "custom hypervisor machine type wrong")
  1011  
  1012  	// auto inferring
  1013  	h.NumVCPUs = -1
  1014  	assert.Equal(h.defaultVCPUs(), uint32(numCPUs), "default vCPU number is wrong")
  1015  
  1016  	h.NumVCPUs = 2
  1017  	assert.Equal(h.defaultVCPUs(), uint32(2), "default vCPU number is wrong")
  1018  
  1019  	h.NumVCPUs = int32(numCPUs) + 1
  1020  	assert.Equal(h.defaultVCPUs(), uint32(numCPUs), "default vCPU number is wrong")
  1021  
  1022  	h.DefaultMaxVCPUs = 2
  1023  	assert.Equal(h.defaultMaxVCPUs(), uint32(2), "default max vCPU number is wrong")
  1024  
  1025  	h.DefaultMaxVCPUs = uint32(numCPUs) + 1
  1026  	assert.Equal(h.defaultMaxVCPUs(), uint32(numCPUs), "default max vCPU number is wrong")
  1027  
  1028  	maxvcpus := vc.MaxQemuVCPUs()
  1029  	h.DefaultMaxVCPUs = maxvcpus + 1
  1030  	assert.Equal(h.defaultMaxVCPUs(), uint32(numCPUs), "default max vCPU number is wrong")
  1031  
  1032  	h.MemorySize = 1024
  1033  	assert.Equal(h.defaultMemSz(), uint32(1024), "default memory size is wrong")
  1034  }
  1035  
  1036  func TestHypervisorDefaultsHypervisor(t *testing.T) {
  1037  	assert := assert.New(t)
  1038  
  1039  	tmpdir, err := ioutil.TempDir(testDir, "")
  1040  	assert.NoError(err)
  1041  	defer os.RemoveAll(tmpdir)
  1042  
  1043  	testHypervisorPath := filepath.Join(tmpdir, "hypervisor")
  1044  	testHypervisorLinkPath := filepath.Join(tmpdir, "hypervisor-link")
  1045  
  1046  	err = createEmptyFile(testHypervisorPath)
  1047  	assert.NoError(err)
  1048  
  1049  	err = syscall.Symlink(testHypervisorPath, testHypervisorLinkPath)
  1050  	assert.NoError(err)
  1051  
  1052  	savedHypervisorPath := defaultHypervisorPath
  1053  
  1054  	defer func() {
  1055  		defaultHypervisorPath = savedHypervisorPath
  1056  	}()
  1057  
  1058  	defaultHypervisorPath = testHypervisorPath
  1059  	h := hypervisor{}
  1060  	p, err := h.path()
  1061  	assert.NoError(err)
  1062  	assert.Equal(p, defaultHypervisorPath, "default hypervisor path wrong")
  1063  
  1064  	// test path resolution
  1065  	defaultHypervisorPath = testHypervisorLinkPath
  1066  	h = hypervisor{}
  1067  	p, err = h.path()
  1068  	assert.NoError(err)
  1069  	assert.Equal(p, testHypervisorPath)
  1070  }
  1071  
  1072  func TestHypervisorDefaultsKernel(t *testing.T) {
  1073  	assert := assert.New(t)
  1074  
  1075  	tmpdir, err := ioutil.TempDir(testDir, "")
  1076  	assert.NoError(err)
  1077  	defer os.RemoveAll(tmpdir)
  1078  
  1079  	testKernelPath := filepath.Join(tmpdir, "kernel")
  1080  	testKernelLinkPath := filepath.Join(tmpdir, "kernel-link")
  1081  
  1082  	err = createEmptyFile(testKernelPath)
  1083  	assert.NoError(err)
  1084  
  1085  	err = syscall.Symlink(testKernelPath, testKernelLinkPath)
  1086  	assert.NoError(err)
  1087  
  1088  	savedKernelPath := defaultKernelPath
  1089  
  1090  	defer func() {
  1091  		defaultKernelPath = savedKernelPath
  1092  	}()
  1093  
  1094  	defaultKernelPath = testKernelPath
  1095  
  1096  	h := hypervisor{}
  1097  	p, err := h.kernel()
  1098  	assert.NoError(err)
  1099  	assert.Equal(p, defaultKernelPath, "default Kernel path wrong")
  1100  
  1101  	// test path resolution
  1102  	defaultKernelPath = testKernelLinkPath
  1103  	h = hypervisor{}
  1104  	p, err = h.kernel()
  1105  	assert.NoError(err)
  1106  	assert.Equal(p, testKernelPath)
  1107  
  1108  	assert.Equal(h.kernelParams(), defaultKernelParams, "default hypervisor image wrong")
  1109  	kernelParams := "foo=bar xyz"
  1110  	h.KernelParams = kernelParams
  1111  	assert.Equal(h.kernelParams(), kernelParams, "custom hypervisor kernel parameterms wrong")
  1112  }
  1113  
  1114  // The default initrd path is not returned by h.initrd()
  1115  func TestHypervisorDefaultsInitrd(t *testing.T) {
  1116  	assert := assert.New(t)
  1117  
  1118  	tmpdir, err := ioutil.TempDir(testDir, "")
  1119  	assert.NoError(err)
  1120  	defer os.RemoveAll(tmpdir)
  1121  
  1122  	testInitrdPath := filepath.Join(tmpdir, "initrd")
  1123  	testInitrdLinkPath := filepath.Join(tmpdir, "initrd-link")
  1124  
  1125  	err = createEmptyFile(testInitrdPath)
  1126  	assert.NoError(err)
  1127  
  1128  	err = syscall.Symlink(testInitrdPath, testInitrdLinkPath)
  1129  	assert.NoError(err)
  1130  
  1131  	savedInitrdPath := defaultInitrdPath
  1132  
  1133  	defer func() {
  1134  		defaultInitrdPath = savedInitrdPath
  1135  	}()
  1136  
  1137  	defaultInitrdPath = testInitrdPath
  1138  	h := hypervisor{}
  1139  	p, err := h.initrd()
  1140  	assert.Error(err)
  1141  	assert.Equal(p, "", "default Image path wrong")
  1142  
  1143  	// test path resolution
  1144  	defaultInitrdPath = testInitrdLinkPath
  1145  	h = hypervisor{}
  1146  	p, err = h.initrd()
  1147  	assert.Error(err)
  1148  	assert.Equal(p, "")
  1149  }
  1150  
  1151  // The default image path is not returned by h.image()
  1152  func TestHypervisorDefaultsImage(t *testing.T) {
  1153  	assert := assert.New(t)
  1154  
  1155  	tmpdir, err := ioutil.TempDir(testDir, "")
  1156  	assert.NoError(err)
  1157  	defer os.RemoveAll(tmpdir)
  1158  
  1159  	testImagePath := filepath.Join(tmpdir, "image")
  1160  	testImageLinkPath := filepath.Join(tmpdir, "image-link")
  1161  
  1162  	err = createEmptyFile(testImagePath)
  1163  	assert.NoError(err)
  1164  
  1165  	err = syscall.Symlink(testImagePath, testImageLinkPath)
  1166  	assert.NoError(err)
  1167  
  1168  	savedImagePath := defaultImagePath
  1169  
  1170  	defer func() {
  1171  		defaultImagePath = savedImagePath
  1172  	}()
  1173  
  1174  	defaultImagePath = testImagePath
  1175  	h := hypervisor{}
  1176  	p, err := h.image()
  1177  	assert.Error(err)
  1178  	assert.Equal(p, "", "default Image path wrong")
  1179  
  1180  	// test path resolution
  1181  	defaultImagePath = testImageLinkPath
  1182  	h = hypervisor{}
  1183  	p, err = h.image()
  1184  	assert.Error(err)
  1185  	assert.Equal(p, "")
  1186  }
  1187  
  1188  func TestHypervisorDefaultsGuestHookPath(t *testing.T) {
  1189  	assert := assert.New(t)
  1190  
  1191  	h := hypervisor{}
  1192  	guestHookPath := h.guestHookPath()
  1193  	assert.Equal(guestHookPath, defaultGuestHookPath, "default guest hook path wrong")
  1194  
  1195  	testGuestHookPath := "/test/guest/hook/path"
  1196  	h = hypervisor{
  1197  		GuestHookPath: testGuestHookPath,
  1198  	}
  1199  	guestHookPath = h.guestHookPath()
  1200  	assert.Equal(guestHookPath, testGuestHookPath, "custom guest hook path wrong")
  1201  }
  1202  
  1203  func TestHypervisorDefaultsVhostUserStorePath(t *testing.T) {
  1204  	assert := assert.New(t)
  1205  
  1206  	h := hypervisor{}
  1207  	vhostUserStorePath := h.vhostUserStorePath()
  1208  	assert.Equal(vhostUserStorePath, defaultVhostUserStorePath, "default vhost-user store path wrong")
  1209  
  1210  	testVhostUserStorePath := "/test/vhost/user/store/path"
  1211  	h = hypervisor{
  1212  		VhostUserStorePath: testVhostUserStorePath,
  1213  	}
  1214  	vhostUserStorePath = h.vhostUserStorePath()
  1215  	assert.Equal(vhostUserStorePath, testVhostUserStorePath, "custom vhost-user store path wrong")
  1216  }
  1217  
  1218  func TestProxyDefaults(t *testing.T) {
  1219  	assert := assert.New(t)
  1220  
  1221  	tmpdir, err := ioutil.TempDir(testDir, "")
  1222  	assert.NoError(err)
  1223  	defer os.RemoveAll(tmpdir)
  1224  
  1225  	testProxyPath := filepath.Join(tmpdir, "proxy")
  1226  	testProxyLinkPath := filepath.Join(tmpdir, "proxy-link")
  1227  
  1228  	err = createEmptyFile(testProxyPath)
  1229  	assert.NoError(err)
  1230  
  1231  	err = syscall.Symlink(testProxyPath, testProxyLinkPath)
  1232  	assert.NoError(err)
  1233  
  1234  	savedProxyPath := defaultProxyPath
  1235  
  1236  	defer func() {
  1237  		defaultProxyPath = savedProxyPath
  1238  	}()
  1239  
  1240  	defaultProxyPath = testProxyPath
  1241  	p := proxy{}
  1242  	path, err := p.path()
  1243  	assert.NoError(err)
  1244  	assert.Equal(path, defaultProxyPath, "default proxy path wrong")
  1245  
  1246  	// test path resolution
  1247  	defaultProxyPath = testProxyLinkPath
  1248  	p = proxy{}
  1249  	path, err = p.path()
  1250  	assert.NoError(err)
  1251  	assert.Equal(path, testProxyPath)
  1252  
  1253  	assert.False(p.debug())
  1254  	p.Debug = true
  1255  	assert.True(p.debug())
  1256  }
  1257  
  1258  func TestShimDefaults(t *testing.T) {
  1259  	assert := assert.New(t)
  1260  
  1261  	tmpdir, err := ioutil.TempDir(testDir, "")
  1262  	assert.NoError(err)
  1263  	defer os.RemoveAll(tmpdir)
  1264  
  1265  	testShimPath := filepath.Join(tmpdir, "shim")
  1266  	testShimLinkPath := filepath.Join(tmpdir, "shim-link")
  1267  
  1268  	err = createEmptyFile(testShimPath)
  1269  	assert.NoError(err)
  1270  
  1271  	err = syscall.Symlink(testShimPath, testShimLinkPath)
  1272  	assert.NoError(err)
  1273  
  1274  	savedShimPath := defaultShimPath
  1275  
  1276  	defer func() {
  1277  		defaultShimPath = savedShimPath
  1278  	}()
  1279  
  1280  	defaultShimPath = testShimPath
  1281  	s := shim{}
  1282  	p, err := s.path()
  1283  	assert.NoError(err)
  1284  	assert.Equal(p, defaultShimPath, "default shim path wrong")
  1285  
  1286  	// test path resolution
  1287  	defaultShimPath = testShimLinkPath
  1288  	s = shim{}
  1289  	p, err = s.path()
  1290  	assert.NoError(err)
  1291  	assert.Equal(p, testShimPath)
  1292  
  1293  	assert.False(s.debug())
  1294  	s.Debug = true
  1295  	assert.True(s.debug())
  1296  
  1297  	assert.False(s.trace())
  1298  	s.Tracing = true
  1299  	assert.True(s.trace())
  1300  }
  1301  
  1302  func TestAgentDefaults(t *testing.T) {
  1303  	assert := assert.New(t)
  1304  
  1305  	a := agent{}
  1306  
  1307  	assert.Equal(a.debug(), a.Debug)
  1308  
  1309  	a.Debug = true
  1310  	assert.Equal(a.debug(), a.Debug)
  1311  
  1312  	assert.Equal(a.trace(), a.Tracing)
  1313  
  1314  	a.Tracing = true
  1315  	assert.Equal(a.trace(), a.Tracing)
  1316  
  1317  	assert.Equal(a.traceMode(), a.TraceMode)
  1318  	assert.Equal(a.traceType(), a.TraceType)
  1319  }
  1320  
  1321  func TestGetDefaultConfigFilePaths(t *testing.T) {
  1322  	assert := assert.New(t)
  1323  
  1324  	results := GetDefaultConfigFilePaths()
  1325  	// There should be atleast two config file locations
  1326  	assert.True(len(results) >= 2)
  1327  
  1328  	for _, f := range results {
  1329  		// Paths cannot be empty
  1330  		assert.NotNil(f)
  1331  	}
  1332  }
  1333  
  1334  func TestGetDefaultConfigFile(t *testing.T) {
  1335  	assert := assert.New(t)
  1336  
  1337  	tmpdir, err := ioutil.TempDir(testDir, "")
  1338  	assert.NoError(err)
  1339  	defer os.RemoveAll(tmpdir)
  1340  
  1341  	hypervisor := "qemu"
  1342  	confDir := filepath.Join(tmpdir, "conf")
  1343  	sysConfDir := filepath.Join(tmpdir, "sysconf")
  1344  
  1345  	for _, dir := range []string{confDir, sysConfDir} {
  1346  		err = os.MkdirAll(dir, testDirMode)
  1347  		assert.NoError(err)
  1348  	}
  1349  
  1350  	confDirConfig, err := createAllRuntimeConfigFiles(confDir, hypervisor)
  1351  	assert.NoError(err)
  1352  
  1353  	sysConfDirConfig, err := createAllRuntimeConfigFiles(sysConfDir, hypervisor)
  1354  	assert.NoError(err)
  1355  
  1356  	savedConf := defaultRuntimeConfiguration
  1357  	savedSysConf := defaultSysConfRuntimeConfiguration
  1358  
  1359  	defaultRuntimeConfiguration = confDirConfig.ConfigPath
  1360  	defaultSysConfRuntimeConfiguration = sysConfDirConfig.ConfigPath
  1361  
  1362  	defer func() {
  1363  		defaultRuntimeConfiguration = savedConf
  1364  		defaultSysConfRuntimeConfiguration = savedSysConf
  1365  
  1366  	}()
  1367  
  1368  	got, err := getDefaultConfigFile()
  1369  	assert.NoError(err)
  1370  	// defaultSysConfRuntimeConfiguration has priority over defaultRuntimeConfiguration
  1371  	assert.Equal(got, defaultSysConfRuntimeConfiguration)
  1372  
  1373  	// force defaultRuntimeConfiguration to be returned
  1374  	os.Remove(defaultSysConfRuntimeConfiguration)
  1375  
  1376  	got, err = getDefaultConfigFile()
  1377  	assert.NoError(err)
  1378  	assert.Equal(got, defaultRuntimeConfiguration)
  1379  
  1380  	// force error
  1381  	os.Remove(defaultRuntimeConfiguration)
  1382  
  1383  	_, err = getDefaultConfigFile()
  1384  	assert.Error(err)
  1385  }
  1386  
  1387  func TestDefaultBridges(t *testing.T) {
  1388  	assert := assert.New(t)
  1389  
  1390  	h := hypervisor{DefaultBridges: 0}
  1391  
  1392  	bridges := h.defaultBridges()
  1393  	assert.Equal(defaultBridgesCount, bridges)
  1394  
  1395  	h.DefaultBridges = maxPCIBridges + 1
  1396  	bridges = h.defaultBridges()
  1397  	assert.Equal(maxPCIBridges, bridges)
  1398  
  1399  	h.DefaultBridges = maxPCIBridges
  1400  	bridges = h.defaultBridges()
  1401  	assert.Equal(maxPCIBridges, bridges)
  1402  }
  1403  
  1404  func TestDefaultVirtioFSCache(t *testing.T) {
  1405  	assert := assert.New(t)
  1406  
  1407  	h := hypervisor{VirtioFSCache: ""}
  1408  
  1409  	cache := h.defaultVirtioFSCache()
  1410  	assert.Equal(defaultVirtioFSCacheMode, cache)
  1411  
  1412  	h.VirtioFSCache = "always"
  1413  	cache = h.defaultVirtioFSCache()
  1414  	assert.Equal("always", cache)
  1415  
  1416  	h.VirtioFSCache = "none"
  1417  	cache = h.defaultVirtioFSCache()
  1418  	assert.Equal("none", cache)
  1419  }
  1420  
  1421  func TestDefaultFirmware(t *testing.T) {
  1422  	assert := assert.New(t)
  1423  
  1424  	// save default firmware path
  1425  	oldDefaultFirmwarePath := defaultFirmwarePath
  1426  
  1427  	f, err := ioutil.TempFile(os.TempDir(), "qboot.bin")
  1428  	assert.NoError(err)
  1429  	assert.NoError(f.Close())
  1430  	defer os.RemoveAll(f.Name())
  1431  
  1432  	h := hypervisor{}
  1433  	defaultFirmwarePath = ""
  1434  	p, err := h.firmware()
  1435  	assert.NoError(err)
  1436  	assert.Empty(p)
  1437  
  1438  	defaultFirmwarePath = f.Name()
  1439  	p, err = h.firmware()
  1440  	assert.NoError(err)
  1441  	assert.NotEmpty(p)
  1442  
  1443  	// restore default firmware path
  1444  	defaultFirmwarePath = oldDefaultFirmwarePath
  1445  }
  1446  
  1447  func TestDefaultMachineAccelerators(t *testing.T) {
  1448  	assert := assert.New(t)
  1449  	machineAccelerators := "abc,123,rgb"
  1450  	h := hypervisor{MachineAccelerators: machineAccelerators}
  1451  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1452  
  1453  	machineAccelerators = ""
  1454  	h.MachineAccelerators = machineAccelerators
  1455  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1456  
  1457  	machineAccelerators = "abc"
  1458  	h.MachineAccelerators = machineAccelerators
  1459  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1460  
  1461  	machineAccelerators = "abc,123"
  1462  	h.MachineAccelerators = "abc,,123"
  1463  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1464  
  1465  	machineAccelerators = "abc,123"
  1466  	h.MachineAccelerators = ",,abc,,123,,,"
  1467  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1468  
  1469  	machineAccelerators = "abc,123"
  1470  	h.MachineAccelerators = "abc,,123,,,"
  1471  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1472  
  1473  	machineAccelerators = "abc"
  1474  	h.MachineAccelerators = ",,abc,"
  1475  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1476  
  1477  	machineAccelerators = "abc"
  1478  	h.MachineAccelerators = ", , abc , ,"
  1479  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1480  
  1481  	machineAccelerators = "abc"
  1482  	h.MachineAccelerators = " abc "
  1483  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1484  
  1485  	machineAccelerators = "abc,123"
  1486  	h.MachineAccelerators = ", abc , 123 ,"
  1487  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1488  
  1489  	machineAccelerators = "abc,123"
  1490  	h.MachineAccelerators = ",, abc ,,, 123 ,,"
  1491  	assert.Equal(machineAccelerators, h.machineAccelerators())
  1492  }
  1493  
  1494  func TestDefaultCPUFeatures(t *testing.T) {
  1495  	assert := assert.New(t)
  1496  	cpuFeatures := "abc,123,rgb"
  1497  	h := hypervisor{CPUFeatures: cpuFeatures}
  1498  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1499  
  1500  	cpuFeatures = ""
  1501  	h.CPUFeatures = cpuFeatures
  1502  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1503  
  1504  	cpuFeatures = "abc"
  1505  	h.CPUFeatures = cpuFeatures
  1506  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1507  
  1508  	cpuFeatures = "abc,123"
  1509  	h.CPUFeatures = "abc,,123"
  1510  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1511  
  1512  	cpuFeatures = "abc,123"
  1513  	h.CPUFeatures = ",,abc,,123,,,"
  1514  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1515  
  1516  	cpuFeatures = "abc,123"
  1517  	h.CPUFeatures = "abc,,123,,,"
  1518  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1519  
  1520  	cpuFeatures = "abc"
  1521  	h.CPUFeatures = ",,abc,"
  1522  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1523  
  1524  	cpuFeatures = "abc"
  1525  	h.CPUFeatures = ", , abc , ,"
  1526  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1527  
  1528  	cpuFeatures = "abc"
  1529  	h.CPUFeatures = " abc "
  1530  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1531  
  1532  	cpuFeatures = "abc,123"
  1533  	h.CPUFeatures = ", abc , 123 ,"
  1534  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1535  
  1536  	cpuFeatures = "abc,123"
  1537  	h.CPUFeatures = ",, abc ,,, 123 ,,"
  1538  	assert.Equal(cpuFeatures, h.cpuFeatures())
  1539  }
  1540  
  1541  func TestUpdateRuntimeConfiguration(t *testing.T) {
  1542  	assert := assert.New(t)
  1543  
  1544  	assert.Equal(defaultAgent, vc.KataContainersAgent)
  1545  
  1546  	config := oci.RuntimeConfig{}
  1547  
  1548  	tomlConf := tomlConfig{
  1549  		Agent: map[string]agent{
  1550  			// force a non-default value
  1551  			kataAgentTableType: {},
  1552  		},
  1553  	}
  1554  
  1555  	assert.NotEqual(config.AgentType, vc.AgentType(kataAgentTableType))
  1556  	assert.NotEqual(config.AgentConfig, vc.KataAgentConfig{})
  1557  
  1558  	err := updateRuntimeConfig("", tomlConf, &config, false)
  1559  	assert.NoError(err)
  1560  
  1561  	assert.Equal(config.AgentType, vc.AgentType(kataAgentTableType))
  1562  	assert.Equal(config.AgentConfig, vc.KataAgentConfig{})
  1563  }
  1564  
  1565  func TestUpdateRuntimeConfigurationVMConfig(t *testing.T) {
  1566  	assert := assert.New(t)
  1567  
  1568  	vcpus := uint(2)
  1569  	mem := uint32(2048)
  1570  
  1571  	config := oci.RuntimeConfig{}
  1572  	expectedVMConfig := mem
  1573  
  1574  	tomlConf := tomlConfig{
  1575  		Hypervisor: map[string]hypervisor{
  1576  			qemuHypervisorTableType: {
  1577  				NumVCPUs:   int32(vcpus),
  1578  				MemorySize: mem,
  1579  				Path:       "/",
  1580  				Kernel:     "/",
  1581  				Image:      "/",
  1582  				Firmware:   "/",
  1583  			},
  1584  		},
  1585  	}
  1586  
  1587  	err := updateRuntimeConfig("", tomlConf, &config, false)
  1588  	assert.NoError(err)
  1589  
  1590  	assert.Equal(expectedVMConfig, config.HypervisorConfig.MemorySize)
  1591  }
  1592  
  1593  func TestUpdateRuntimeConfigurationFactoryConfig(t *testing.T) {
  1594  	assert := assert.New(t)
  1595  
  1596  	config := oci.RuntimeConfig{}
  1597  	expectedFactoryConfig := oci.FactoryConfig{
  1598  		Template:        true,
  1599  		TemplatePath:    defaultTemplatePath,
  1600  		VMCacheEndpoint: defaultVMCacheEndpoint,
  1601  	}
  1602  
  1603  	tomlConf := tomlConfig{Factory: factory{Template: true}}
  1604  
  1605  	err := updateRuntimeConfig("", tomlConf, &config, false)
  1606  	assert.NoError(err)
  1607  
  1608  	assert.Equal(expectedFactoryConfig, config.FactoryConfig)
  1609  }
  1610  
  1611  func TestUpdateRuntimeConfigurationInvalidKernelParams(t *testing.T) {
  1612  	assert := assert.New(t)
  1613  
  1614  	assert.Equal(defaultAgent, vc.KataContainersAgent)
  1615  
  1616  	config := oci.RuntimeConfig{}
  1617  
  1618  	tomlConf := tomlConfig{}
  1619  
  1620  	savedFunc := GetKernelParamsFunc
  1621  	defer func() {
  1622  		GetKernelParamsFunc = savedFunc
  1623  	}()
  1624  
  1625  	GetKernelParamsFunc = func(needSystemd, trace bool) []vc.Param {
  1626  		return []vc.Param{
  1627  			{
  1628  				Key:   "",
  1629  				Value: "",
  1630  			},
  1631  		}
  1632  	}
  1633  
  1634  	err := updateRuntimeConfig("", tomlConf, &config, false)
  1635  	assert.EqualError(err, "Empty kernel parameter")
  1636  }
  1637  
  1638  func TestCheckHypervisorConfig(t *testing.T) {
  1639  	assert := assert.New(t)
  1640  
  1641  	dir, err := ioutil.TempDir(testDir, "")
  1642  	if err != nil {
  1643  		t.Fatal(err)
  1644  	}
  1645  	defer os.RemoveAll(dir)
  1646  
  1647  	// Not created on purpose
  1648  	imageENOENT := filepath.Join(dir, "image-ENOENT.img")
  1649  	initrdENOENT := filepath.Join(dir, "initrd-ENOENT.img")
  1650  
  1651  	imageEmpty := filepath.Join(dir, "image-empty.img")
  1652  	initrdEmpty := filepath.Join(dir, "initrd-empty.img")
  1653  
  1654  	for _, file := range []string{imageEmpty, initrdEmpty} {
  1655  		err = createEmptyFile(file)
  1656  		assert.NoError(err)
  1657  	}
  1658  
  1659  	image := filepath.Join(dir, "image.img")
  1660  	initrd := filepath.Join(dir, "initrd.img")
  1661  
  1662  	mb := uint32(1024 * 1024)
  1663  
  1664  	fileSizeMB := uint32(3)
  1665  	fileSizeBytes := fileSizeMB * mb
  1666  
  1667  	fileData := strings.Repeat("X", int(fileSizeBytes))
  1668  
  1669  	for _, file := range []string{image, initrd} {
  1670  		err = WriteFile(file, fileData, testFileMode)
  1671  		assert.NoError(err)
  1672  	}
  1673  
  1674  	type testData struct {
  1675  		imagePath        string
  1676  		initrdPath       string
  1677  		memBytes         uint32
  1678  		expectError      bool
  1679  		expectLogWarning bool
  1680  	}
  1681  
  1682  	// Note that checkHypervisorConfig() does not check to ensure an image
  1683  	// or an initrd has been specified - that's handled by a separate
  1684  	// function, hence no test for it here.
  1685  
  1686  	data := []testData{
  1687  		{"", "", 0, true, false},
  1688  
  1689  		{imageENOENT, "", 2, true, false},
  1690  		{"", initrdENOENT, 2, true, false},
  1691  
  1692  		{imageEmpty, "", 2, true, false},
  1693  		{"", initrdEmpty, 2, true, false},
  1694  
  1695  		{image, "", fileSizeMB + 2, false, false},
  1696  		{image, "", fileSizeMB + 1, false, false},
  1697  		{image, "", fileSizeMB + 0, false, true},
  1698  		{image, "", fileSizeMB - 1, false, true},
  1699  		{image, "", fileSizeMB - 2, false, true},
  1700  
  1701  		{"", initrd, fileSizeMB + 2, false, false},
  1702  		{"", initrd, fileSizeMB + 1, false, false},
  1703  		{"", initrd, fileSizeMB + 0, true, false},
  1704  		{"", initrd, fileSizeMB - 1, true, false},
  1705  		{"", initrd, fileSizeMB - 2, true, false},
  1706  	}
  1707  
  1708  	for i, d := range data {
  1709  		savedOut := kataUtilsLogger.Logger.Out
  1710  
  1711  		// create buffer to save logger output
  1712  		logBuf := &bytes.Buffer{}
  1713  
  1714  		// capture output to buffer
  1715  		kataUtilsLogger.Logger.Out = logBuf
  1716  
  1717  		config := vc.HypervisorConfig{
  1718  			ImagePath:  d.imagePath,
  1719  			InitrdPath: d.initrdPath,
  1720  			MemorySize: d.memBytes,
  1721  		}
  1722  
  1723  		err := checkHypervisorConfig(config)
  1724  
  1725  		if d.expectError {
  1726  			assert.Error(err, "test %d (%+v)", i, d)
  1727  		} else {
  1728  			assert.NoError(err, "test %d (%+v)", i, d)
  1729  		}
  1730  
  1731  		if d.expectLogWarning {
  1732  			assert.True(strings.Contains(logBuf.String(), "warning"))
  1733  		} else {
  1734  			assert.Empty(logBuf.String())
  1735  		}
  1736  
  1737  		// reset logger
  1738  		kataUtilsLogger.Logger.Out = savedOut
  1739  	}
  1740  }
  1741  
  1742  func TestCheckNetNsConfig(t *testing.T) {
  1743  	assert := assert.New(t)
  1744  
  1745  	config := oci.RuntimeConfig{
  1746  		DisableNewNetNs: true,
  1747  		NetmonConfig: vc.NetmonConfig{
  1748  			Enable: true,
  1749  		},
  1750  	}
  1751  	err := checkNetNsConfig(config)
  1752  	assert.Error(err)
  1753  
  1754  	config = oci.RuntimeConfig{
  1755  		DisableNewNetNs:   true,
  1756  		InterNetworkModel: vc.NetXConnectDefaultModel,
  1757  	}
  1758  	err = checkNetNsConfig(config)
  1759  	assert.Error(err)
  1760  }
  1761  
  1762  func TestCheckFactoryConfig(t *testing.T) {
  1763  	assert := assert.New(t)
  1764  
  1765  	type testData struct {
  1766  		factoryEnabled bool
  1767  		expectError    bool
  1768  		imagePath      string
  1769  		initrdPath     string
  1770  	}
  1771  
  1772  	data := []testData{
  1773  		{false, false, "", ""},
  1774  		{false, false, "image", ""},
  1775  		{false, false, "", "initrd"},
  1776  
  1777  		{true, false, "", "initrd"},
  1778  		{true, true, "image", ""},
  1779  	}
  1780  
  1781  	for i, d := range data {
  1782  		config := oci.RuntimeConfig{
  1783  			HypervisorConfig: vc.HypervisorConfig{
  1784  				ImagePath:  d.imagePath,
  1785  				InitrdPath: d.initrdPath,
  1786  			},
  1787  
  1788  			FactoryConfig: oci.FactoryConfig{
  1789  				Template: d.factoryEnabled,
  1790  			},
  1791  		}
  1792  
  1793  		err := checkFactoryConfig(config)
  1794  
  1795  		if d.expectError {
  1796  			assert.Error(err, "test %d (%+v)", i, d)
  1797  		} else {
  1798  			assert.NoError(err, "test %d (%+v)", i, d)
  1799  		}
  1800  	}
  1801  }
  1802  
  1803  func TestCheckNetNsConfigShimTrace(t *testing.T) {
  1804  	assert := assert.New(t)
  1805  
  1806  	type testData struct {
  1807  		networkModel vc.NetInterworkingModel
  1808  		disableNetNs bool
  1809  		shimTrace    bool
  1810  		expectError  bool
  1811  	}
  1812  
  1813  	data := []testData{
  1814  		{vc.NetXConnectMacVtapModel, false, false, false},
  1815  		{vc.NetXConnectMacVtapModel, false, true, true},
  1816  		{vc.NetXConnectMacVtapModel, true, true, true},
  1817  		{vc.NetXConnectMacVtapModel, true, false, true},
  1818  		{vc.NetXConnectNoneModel, true, false, false},
  1819  		{vc.NetXConnectNoneModel, true, true, false},
  1820  	}
  1821  
  1822  	for i, d := range data {
  1823  		config := oci.RuntimeConfig{
  1824  			DisableNewNetNs:   d.disableNetNs,
  1825  			InterNetworkModel: d.networkModel,
  1826  			ShimConfig: vc.ShimConfig{
  1827  				Trace: d.shimTrace,
  1828  			},
  1829  		}
  1830  
  1831  		err := checkNetNsConfig(config)
  1832  
  1833  		if d.expectError {
  1834  			assert.Error(err, "test %d (%+v)", i, d)
  1835  		} else {
  1836  			assert.NoError(err, "test %d (%+v)", i, d)
  1837  		}
  1838  	}
  1839  }