mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-15 16:13:20 +00:00
Merge pull request #870 from lifupan/cli_refactor
cli: refactor the config into a separated package
This commit is contained in:
commit
ebd86d604e
36
Makefile
36
Makefile
@ -291,6 +291,8 @@ const systemdUnitName = "$(PROJECT_TAG).target"
|
||||
// original URL for this project
|
||||
const projectURL = "$(PROJECT_URL)"
|
||||
|
||||
const defaultRootDirectory = "$(PKGRUNDIR)"
|
||||
|
||||
// commit is the git commit the runtime is compiled from.
|
||||
var commit = "$(COMMIT)"
|
||||
|
||||
@ -305,46 +307,12 @@ var checkCmd = fmt.Sprintf("%s-check", projectPrefix)
|
||||
var configFilePathOption = fmt.Sprintf("%s-config", projectPrefix)
|
||||
var showConfigPathsOption = fmt.Sprintf("%s-show-default-config-paths", projectPrefix)
|
||||
|
||||
var defaultHypervisorPath = "$(QEMUPATH)"
|
||||
var defaultImagePath = "$(IMAGEPATH)"
|
||||
var defaultKernelPath = "$(KERNELPATH)"
|
||||
var defaultInitrdPath = "$(INITRDPATH)"
|
||||
var defaultFirmwarePath = "$(FIRMWAREPATH)"
|
||||
var defaultMachineAccelerators = "$(MACHINEACCELERATORS)"
|
||||
var defaultShimPath = "$(SHIMPATH)"
|
||||
|
||||
const defaultKernelParams = "$(KERNELPARAMS)"
|
||||
const defaultMachineType = "$(MACHINETYPE)"
|
||||
const defaultRootDirectory = "$(PKGRUNDIR)"
|
||||
|
||||
const defaultVCPUCount uint32 = $(DEFVCPUS)
|
||||
const defaultMaxVCPUCount uint32 = $(DEFMAXVCPUS)
|
||||
const defaultMemSize uint32 = $(DEFMEMSZ) // MiB
|
||||
const defaultMemSlots uint32 = $(DEFMEMSLOTS)
|
||||
const defaultBridgesCount uint32 = $(DEFBRIDGES)
|
||||
const defaultInterNetworkingModel = "$(DEFNETWORKMODEL)"
|
||||
const defaultDisableBlockDeviceUse bool = $(DEFDISABLEBLOCK)
|
||||
const defaultBlockDeviceDriver = "$(DEFBLOCKSTORAGEDRIVER)"
|
||||
const defaultEnableIOThreads bool = $(DEFENABLEIOTHREADS)
|
||||
const defaultEnableMemPrealloc bool = $(DEFENABLEMEMPREALLOC)
|
||||
const defaultEnableHugePages bool = $(DEFENABLEHUGEPAGES)
|
||||
const defaultEnableSwap bool = $(DEFENABLESWAP)
|
||||
const defaultEnableDebug bool = $(DEFENABLEDEBUG)
|
||||
const defaultDisableNestingChecks bool = $(DEFDISABLENESTINGCHECKS)
|
||||
const defaultMsize9p uint32 = $(DEFMSIZE9P)
|
||||
const defaultHotplugVFIOOnRootBus bool = $(DEFHOTPLUGVFIOONROOTBUS)
|
||||
const defaultEntropySource = "$(DEFENTROPYSOURCE)"
|
||||
const defaultGuestHookPath string = ""
|
||||
|
||||
// Default config file used by stateless systems.
|
||||
var defaultRuntimeConfiguration = "$(CONFIG_PATH)"
|
||||
|
||||
// Alternate config file that takes precedence over
|
||||
// defaultRuntimeConfiguration.
|
||||
var defaultSysConfRuntimeConfiguration = "$(SYSCONFIG)"
|
||||
|
||||
var defaultProxyPath = "$(PROXYPATH)"
|
||||
var defaultNetmonPath = "$(NETMONPATH)"
|
||||
endef
|
||||
|
||||
export GENERATED_CODE
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
@ -70,7 +71,7 @@ var (
|
||||
|
||||
// getCPUInfo returns details of the first CPU read from the specified cpuinfo file
|
||||
func getCPUInfo(cpuInfoFile string) (string, error) {
|
||||
text, err := getFileContents(cpuInfoFile)
|
||||
text, err := katautils.GetFileContents(cpuInfoFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -206,7 +207,7 @@ func checkKernelModules(modules map[string]kernelModule, handler kernelParamHand
|
||||
|
||||
for param, expected := range details.parameters {
|
||||
path := filepath.Join(sysModuleDir, module, moduleParamDir, param)
|
||||
value, err := getFileContents(path)
|
||||
value, err := katautils.GetFileContents(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -60,7 +61,7 @@ func hostIsVMContainerCapable(details vmContainerCapableDetails) error {
|
||||
return err
|
||||
}
|
||||
|
||||
text, err := getFileContents(details.cpuInfoFile)
|
||||
text, err := katautils.GetFileContents(details.cpuInfoFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -24,8 +24,10 @@ import (
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const testProxyVersion = "proxy version 0.1"
|
||||
@ -33,6 +35,20 @@ const testShimVersion = "shim version 0.1"
|
||||
const testNetmonVersion = "netmon version 0.1"
|
||||
const testHypervisorVersion = "QEMU emulator version 2.7.0+git.741f430a96-6.1, Copyright (c) 2003-2016 Fabrice Bellard and the QEMU Project developers"
|
||||
|
||||
const defaultVCPUCount uint32 = 1
|
||||
const defaultMaxVCPUCount uint32 = 0
|
||||
const defaultMemSize uint32 = 2048 // MiB
|
||||
const defaultMsize9p uint32 = 8192
|
||||
const defaultGuestHookPath string = ""
|
||||
|
||||
var (
|
||||
hypervisorDebug = false
|
||||
proxyDebug = false
|
||||
runtimeDebug = false
|
||||
shimDebug = false
|
||||
netmonDebug = false
|
||||
)
|
||||
|
||||
// makeVersionBinary creates a shell script with the specified file
|
||||
// name. When run as "file --version", it will display the specified
|
||||
// version to stdout and exit successfully.
|
||||
@ -52,6 +68,57 @@ func makeVersionBinary(file, version string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createConfig(configPath string, fileData string) error {
|
||||
|
||||
err := ioutil.WriteFile(configPath, []byte(fileData), testFileMode)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to create config file %s %v\n", configPath, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus, disableNewNetNs bool) string {
|
||||
return `
|
||||
# Runtime configuration file
|
||||
|
||||
[hypervisor.` + hypervisor + `]
|
||||
path = "` + hypervisorPath + `"
|
||||
kernel = "` + kernelPath + `"
|
||||
block_device_driver = "` + blockDeviceDriver + `"
|
||||
kernel_params = "` + kernelParams + `"
|
||||
image = "` + imagePath + `"
|
||||
machine_type = "` + machineType + `"
|
||||
default_vcpus = ` + strconv.FormatUint(uint64(defaultVCPUCount), 10) + `
|
||||
default_maxvcpus = ` + strconv.FormatUint(uint64(defaultMaxVCPUCount), 10) + `
|
||||
default_memory = ` + strconv.FormatUint(uint64(defaultMemSize), 10) + `
|
||||
disable_block_device_use = ` + strconv.FormatBool(disableBlock) + `
|
||||
enable_iothreads = ` + strconv.FormatBool(enableIOThreads) + `
|
||||
hotplug_vfio_on_root_bus = ` + strconv.FormatBool(hotplugVFIOOnRootBus) + `
|
||||
msize_9p = ` + strconv.FormatUint(uint64(defaultMsize9p), 10) + `
|
||||
enable_debug = ` + strconv.FormatBool(hypervisorDebug) + `
|
||||
guest_hook_path = "` + defaultGuestHookPath + `"
|
||||
|
||||
[proxy.kata]
|
||||
enable_debug = ` + strconv.FormatBool(proxyDebug) + `
|
||||
path = "` + proxyPath + `"
|
||||
|
||||
[shim.kata]
|
||||
path = "` + shimPath + `"
|
||||
enable_debug = ` + strconv.FormatBool(shimDebug) + `
|
||||
|
||||
[agent.kata]
|
||||
|
||||
[netmon]
|
||||
path = "` + netmonPath + `"
|
||||
enable_debug = ` + strconv.FormatBool(netmonDebug) + `
|
||||
|
||||
[runtime]
|
||||
enable_debug = ` + strconv.FormatBool(runtimeDebug) + `
|
||||
disable_new_netns= ` + strconv.FormatBool(disableNewNetNs)
|
||||
}
|
||||
|
||||
func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeConfig, err error) {
|
||||
const logPath = "/log/path"
|
||||
hypervisorPath := filepath.Join(prefixDir, "hypervisor")
|
||||
@ -76,7 +143,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
|
||||
|
||||
for _, file := range filesToCreate {
|
||||
// files must exist and be >0 bytes.
|
||||
err := writeFile(file, "foo", testFileMode)
|
||||
err := katautils.WriteFile(file, "foo", testFileMode)
|
||||
if err != nil {
|
||||
return "", oci.RuntimeConfig{}, err
|
||||
}
|
||||
@ -126,7 +193,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
|
||||
return "", oci.RuntimeConfig{}, err
|
||||
}
|
||||
|
||||
_, config, err = loadConfiguration(configFile, true)
|
||||
_, config, _, err = katautils.LoadConfiguration(configFile, true, false)
|
||||
if err != nil {
|
||||
return "", oci.RuntimeConfig{}, err
|
||||
}
|
||||
@ -812,7 +879,7 @@ func testEnvShowTOMLSettings(t *testing.T, tmpdir string, tmpfile *os.File) erro
|
||||
return err
|
||||
}
|
||||
|
||||
contents, err := getFileContents(tmpfile.Name())
|
||||
contents, err := katautils.GetFileContents(tmpfile.Name())
|
||||
assert.NoError(t, err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
@ -881,7 +948,7 @@ func testEnvShowJSONSettings(t *testing.T, tmpdir string, tmpfile *os.File) erro
|
||||
return err
|
||||
}
|
||||
|
||||
contents, err := getFileContents(tmpfile.Name())
|
||||
contents, err := katautils.GetFileContents(tmpfile.Name())
|
||||
assert.NoError(t, err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
|
||||
@ -686,7 +687,7 @@ func TestListCLIFunctionQuiet(t *testing.T) {
|
||||
assert.NoError(err)
|
||||
f.Close()
|
||||
|
||||
text, err := getFileContents(output)
|
||||
text, err := katautils.GetFileContents(output)
|
||||
assert.NoError(err)
|
||||
|
||||
trimmed := strings.TrimSpace(text)
|
||||
|
17
cli/main.go
17
cli/main.go
@ -17,6 +17,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
"github.com/kata-containers/runtime/pkg/signals"
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
vf "github.com/kata-containers/runtime/virtcontainers/factory"
|
||||
@ -240,11 +241,18 @@ func setExternalLoggers(ctx context.Context, logger *logrus.Entry) {
|
||||
|
||||
// Set the OCI package logger.
|
||||
oci.SetLogger(ctx, logger)
|
||||
|
||||
// Set the katautils package logger
|
||||
katautils.SetLogger(ctx, logger, originalLoggerLevel)
|
||||
}
|
||||
|
||||
// beforeSubcommands is the function to perform preliminary checks
|
||||
// before command-line parsing occurs.
|
||||
func beforeSubcommands(c *cli.Context) error {
|
||||
var configFile string
|
||||
var runtimeConfig oci.RuntimeConfig
|
||||
var err error
|
||||
|
||||
handleShowConfig(c)
|
||||
|
||||
if userWantsUsage(c) || (c.NArg() == 1 && (c.Args()[0] == checkCmd)) {
|
||||
@ -297,11 +305,16 @@ func beforeSubcommands(c *cli.Context) error {
|
||||
ignoreLogging = true
|
||||
}
|
||||
|
||||
configFile, runtimeConfig, err := loadConfiguration(c.GlobalString(configFilePathOption), ignoreLogging)
|
||||
katautils.SetConfigOptions(name, defaultRuntimeConfiguration, defaultSysConfRuntimeConfiguration)
|
||||
|
||||
configFile, runtimeConfig, tracing, err = katautils.LoadConfiguration(c.GlobalString(configFilePathOption), ignoreLogging, false)
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
|
||||
debug = runtimeConfig.Debug
|
||||
crashOnError = runtimeConfig.Debug
|
||||
|
||||
if traceRootSpan != "" {
|
||||
// Create the tracer.
|
||||
//
|
||||
@ -336,7 +349,7 @@ func beforeSubcommands(c *cli.Context) error {
|
||||
// paths. If so, it will display them and then exit.
|
||||
func handleShowConfig(context *cli.Context) {
|
||||
if context.GlobalBool(showConfigPathsOption) {
|
||||
files := getDefaultConfigFilePaths()
|
||||
files := katautils.GetDefaultConfigFilePaths()
|
||||
|
||||
for _, file := range files {
|
||||
fmt.Fprintf(defaultOutputFile, "%s\n", file)
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/dlespiau/covertool/pkg/cover"
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
|
||||
@ -747,7 +748,7 @@ func TestMainBeforeSubCommandsShowCCConfigPaths(t *testing.T) {
|
||||
_ = beforeSubcommands(ctx)
|
||||
assert.Equal(exitStatus, 0)
|
||||
|
||||
text, err := getFileContents(output)
|
||||
text, err := katautils.GetFileContents(output)
|
||||
assert.NoError(err)
|
||||
|
||||
lines := strings.Split(text, "\n")
|
||||
@ -801,7 +802,7 @@ func TestMainFatal(t *testing.T) {
|
||||
fatal(exitError)
|
||||
assert.Equal(exitStatus, 1)
|
||||
|
||||
text, err := getFileContents(output)
|
||||
text, err := katautils.GetFileContents(output)
|
||||
assert.NoError(err)
|
||||
|
||||
trimmed := strings.TrimSpace(text)
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
)
|
||||
@ -107,7 +108,7 @@ func validCreateParams(ctx context.Context, containerID, bundlePath string) (str
|
||||
return "", fmt.Errorf("Invalid bundle path '%s', it should be a directory", bundlePath)
|
||||
}
|
||||
|
||||
resolved, err := resolvePath(bundlePath)
|
||||
resolved, err := katautils.ResolvePath(bundlePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
70
cli/utils.go
70
cli/utils.go
@ -7,12 +7,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/kata-containers/runtime/pkg/katautils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -37,15 +36,6 @@ func fileExists(path string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func getFileContents(file string) (string, error) {
|
||||
bytes, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
// IsEphemeralStorage returns true if the given path
|
||||
// to the storage belongs to kubernetes ephemeral storage
|
||||
//
|
||||
@ -67,7 +57,7 @@ func IsEphemeralStorage(path string) bool {
|
||||
}
|
||||
|
||||
func getKernelVersion() (string, error) {
|
||||
contents, err := getFileContents(procVersion)
|
||||
contents, err := katautils.GetFileContents(procVersion)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -90,7 +80,7 @@ func getDistroDetails() (name, version string, err error) {
|
||||
files := []string{osRelease, osReleaseClr}
|
||||
|
||||
for _, file := range files {
|
||||
contents, err := getFileContents(file)
|
||||
contents, err := katautils.GetFileContents(file)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
@ -162,31 +152,6 @@ func genericGetCPUDetails() (vendor, model string, err error) {
|
||||
return vendor, model, nil
|
||||
}
|
||||
|
||||
// resolvePath returns the fully resolved and expanded value of the
|
||||
// specified path.
|
||||
func resolvePath(path string) (string, error) {
|
||||
if path == "" {
|
||||
return "", fmt.Errorf("path must be specified")
|
||||
}
|
||||
|
||||
absolute, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resolved, err := filepath.EvalSymlinks(absolute)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// Make the error clearer than the default
|
||||
return "", fmt.Errorf("file %v does not exist", absolute)
|
||||
}
|
||||
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resolved, nil
|
||||
}
|
||||
|
||||
// runCommandFull returns the commands space-trimmed standard output and
|
||||
// error on success. Note that if the command fails, the requested output will
|
||||
// still be returned, along with an error.
|
||||
@ -210,30 +175,3 @@ func runCommandFull(args []string, includeStderr bool) (string, error) {
|
||||
func runCommand(args []string) (string, error) {
|
||||
return runCommandFull(args, false)
|
||||
}
|
||||
|
||||
// writeFile write data into specified file
|
||||
func writeFile(filePath string, data string, fileMode os.FileMode) error {
|
||||
// Normally dir should not be empty, one case is that cgroup subsystem
|
||||
// is not mounted, we will get empty dir, and we want it fail here.
|
||||
if filePath == "" {
|
||||
return fmt.Errorf("no such file for %s", filePath)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filePath, []byte(data), fileMode); err != nil {
|
||||
return fmt.Errorf("failed to write %v to %v: %v", data, filePath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// fileSize returns the number of bytes in the specified file
|
||||
func fileSize(file string) (int64, error) {
|
||||
st := syscall.Stat_t{}
|
||||
|
||||
err := syscall.Stat(file, &st)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return st.Size, nil
|
||||
}
|
||||
|
@ -9,9 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -52,48 +50,6 @@ func TestIsEphemeralStorage(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFileContents(t *testing.T) {
|
||||
type testData struct {
|
||||
contents string
|
||||
}
|
||||
|
||||
data := []testData{
|
||||
{""},
|
||||
{" "},
|
||||
{"\n"},
|
||||
{"\n\n"},
|
||||
{"\n\n\n"},
|
||||
{"foo"},
|
||||
{"foo\nbar"},
|
||||
{"processor : 0\nvendor_id : GenuineIntel\n"},
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
file := filepath.Join(dir, "foo")
|
||||
|
||||
// file doesn't exist
|
||||
_, err = getFileContents(file)
|
||||
assert.Error(t, err)
|
||||
|
||||
for _, d := range data {
|
||||
// create the file
|
||||
err = ioutil.WriteFile(file, []byte(d.contents), testFileMode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file)
|
||||
|
||||
contents, err := getFileContents(file)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, contents, d.contents)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetKernelVersion(t *testing.T) {
|
||||
type testData struct {
|
||||
contents string
|
||||
@ -230,76 +186,6 @@ VERSION_ID="%s"
|
||||
}
|
||||
}
|
||||
|
||||
func TestUtilsResolvePathEmptyPath(t *testing.T) {
|
||||
_, err := resolvePath("")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestUtilsResolvePathValidPath(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
target := path.Join(dir, "target")
|
||||
linkDir := path.Join(dir, "a/b/c")
|
||||
linkFile := path.Join(linkDir, "link")
|
||||
|
||||
err = createEmptyFile(target)
|
||||
assert.NoError(t, err)
|
||||
|
||||
absolute, err := filepath.Abs(target)
|
||||
assert.NoError(t, err)
|
||||
|
||||
resolvedTarget, err := filepath.EvalSymlinks(absolute)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.MkdirAll(linkDir, testDirMode)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = syscall.Symlink(target, linkFile)
|
||||
assert.NoError(t, err)
|
||||
|
||||
resolvedLink, err := resolvePath(linkFile)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, resolvedTarget, resolvedLink)
|
||||
}
|
||||
|
||||
func TestUtilsResolvePathENOENT(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
target := path.Join(dir, "target")
|
||||
linkDir := path.Join(dir, "a/b/c")
|
||||
linkFile := path.Join(linkDir, "link")
|
||||
|
||||
err = createEmptyFile(target)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.MkdirAll(linkDir, testDirMode)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = syscall.Symlink(target, linkFile)
|
||||
assert.NoError(t, err)
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
assert.NoError(t, err)
|
||||
defer os.Chdir(cwd)
|
||||
|
||||
err = os.Chdir(dir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.RemoveAll(dir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = resolvePath(filepath.Base(linkFile))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestUtilsRunCommand(t *testing.T) {
|
||||
output, err := runCommand([]string{"true"})
|
||||
assert.NoError(t, err)
|
||||
@ -343,56 +229,3 @@ func TestUtilsRunCommandInvalidCmds(t *testing.T) {
|
||||
assert.Equal(t, "", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteFileErrWriteFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
err := writeFile("", "", 0000)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestWriteFileErrNoPath(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// attempt to write a file over an existing directory
|
||||
err = writeFile(dir, "", 0000)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestFileSize(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
file := filepath.Join(dir, "foo")
|
||||
|
||||
// ENOENT
|
||||
_, err = fileSize(file)
|
||||
assert.Error(err)
|
||||
|
||||
err = createEmptyFile(file)
|
||||
assert.NoError(err)
|
||||
|
||||
// zero size
|
||||
size, err := fileSize(file)
|
||||
assert.NoError(err)
|
||||
assert.Equal(size, int64(0))
|
||||
|
||||
msg := "hello"
|
||||
msgLen := len(msg)
|
||||
|
||||
err = writeFile(file, msg, testFileMode)
|
||||
assert.NoError(err)
|
||||
|
||||
size, err = fileSize(file)
|
||||
assert.NoError(err)
|
||||
assert.Equal(size, int64(msgLen))
|
||||
}
|
||||
|
50
pkg/katautils/config-settings.go
Normal file
50
pkg/katautils/config-settings.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Note that some variables are "var" to allow them to be modified
|
||||
// by the tests.
|
||||
|
||||
package katautils
|
||||
|
||||
var defaultHypervisorPath = "/usr/bin/qemu-lite-system-x86_64"
|
||||
var defaultImagePath = "/usr/share/kata-containers/kata-containers.img"
|
||||
var defaultKernelPath = "/usr/share/kata-containers/vmlinuz.container"
|
||||
var defaultInitrdPath = "/usr/share/kata-containers/kata-containers-initrd.img"
|
||||
var defaultFirmwarePath = ""
|
||||
var defaultMachineAccelerators = ""
|
||||
var defaultShimPath = "/usr/libexec/kata-containers/kata-shim"
|
||||
|
||||
const defaultKernelParams = ""
|
||||
const defaultMachineType = "pc"
|
||||
|
||||
const defaultVCPUCount uint32 = 1
|
||||
const defaultMaxVCPUCount uint32 = 0
|
||||
const defaultMemSize uint32 = 2048 // MiB
|
||||
const defaultMemSlots uint32 = 10
|
||||
const defaultBridgesCount uint32 = 1
|
||||
const defaultInterNetworkingModel = "macvtap"
|
||||
const defaultDisableBlockDeviceUse bool = false
|
||||
const defaultBlockDeviceDriver = "virtio-scsi"
|
||||
const defaultEnableIOThreads bool = false
|
||||
const defaultEnableMemPrealloc bool = false
|
||||
const defaultEnableHugePages bool = false
|
||||
const defaultEnableSwap bool = false
|
||||
const defaultEnableDebug bool = false
|
||||
const defaultDisableNestingChecks bool = false
|
||||
const defaultMsize9p uint32 = 8192
|
||||
const defaultHotplugVFIOOnRootBus bool = false
|
||||
const defaultEntropySource = "/dev/urandom"
|
||||
const defaultGuestHookPath string = ""
|
||||
|
||||
// Default config file used by stateless systems.
|
||||
var defaultRuntimeConfiguration = "/usr/share/defaults/kata-containers/configuration.toml"
|
||||
|
||||
// Alternate config file that takes precedence over
|
||||
// defaultRuntimeConfiguration.
|
||||
var defaultSysConfRuntimeConfiguration = "/etc/kata-containers/configuration.toml"
|
||||
|
||||
var name = "kata"
|
||||
var defaultProxyPath = "/usr/libexec/kata-containers/kata-proxy"
|
||||
var defaultNetmonPath = "/usr/libexec/kata-containers/kata-netmon"
|
@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package main
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -21,11 +22,14 @@ import (
|
||||
|
||||
const (
|
||||
defaultHypervisor = vc.QemuHypervisor
|
||||
defaultProxy = vc.KataProxyType
|
||||
defaultShim = vc.KataShimType
|
||||
defaultAgent = vc.KataContainersAgent
|
||||
)
|
||||
|
||||
var (
|
||||
defaultProxy = vc.KataProxyType
|
||||
defaultShim = vc.KataShimType
|
||||
)
|
||||
|
||||
// The TOML configuration file contains a number of sections (or
|
||||
// tables). The names of these tables are in dotted ("nested table")
|
||||
// form:
|
||||
@ -134,7 +138,7 @@ func (h hypervisor) path() (string, error) {
|
||||
p = defaultHypervisorPath
|
||||
}
|
||||
|
||||
return resolvePath(p)
|
||||
return ResolvePath(p)
|
||||
}
|
||||
|
||||
func (h hypervisor) kernel() (string, error) {
|
||||
@ -144,7 +148,7 @@ func (h hypervisor) kernel() (string, error) {
|
||||
p = defaultKernelPath
|
||||
}
|
||||
|
||||
return resolvePath(p)
|
||||
return ResolvePath(p)
|
||||
}
|
||||
|
||||
func (h hypervisor) initrd() (string, error) {
|
||||
@ -154,7 +158,7 @@ func (h hypervisor) initrd() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return resolvePath(p)
|
||||
return ResolvePath(p)
|
||||
}
|
||||
|
||||
func (h hypervisor) image() (string, error) {
|
||||
@ -164,7 +168,7 @@ func (h hypervisor) image() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return resolvePath(p)
|
||||
return ResolvePath(p)
|
||||
}
|
||||
|
||||
func (h hypervisor) firmware() (string, error) {
|
||||
@ -177,7 +181,7 @@ func (h hypervisor) firmware() (string, error) {
|
||||
p = defaultFirmwarePath
|
||||
}
|
||||
|
||||
return resolvePath(p)
|
||||
return ResolvePath(p)
|
||||
}
|
||||
|
||||
func (h hypervisor) machineAccelerators() string {
|
||||
@ -330,7 +334,7 @@ func (s shim) path() (string, error) {
|
||||
p = defaultShimPath
|
||||
}
|
||||
|
||||
return resolvePath(p)
|
||||
return ResolvePath(p)
|
||||
}
|
||||
|
||||
func (s shim) debug() bool {
|
||||
@ -401,10 +405,10 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
useVSock := false
|
||||
if h.useVSock() {
|
||||
if utils.SupportsVsocks() {
|
||||
kataLog.Info("vsock supported")
|
||||
kataUtilsLogger.Info("vsock supported")
|
||||
useVSock = true
|
||||
} else {
|
||||
kataLog.Warn("No vsock support, falling back to legacy serial port")
|
||||
kataUtilsLogger.Warn("No vsock support, falling back to legacy serial port")
|
||||
}
|
||||
}
|
||||
|
||||
@ -527,15 +531,9 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadConfiguration loads the configuration file and converts it into a
|
||||
// runtime configuration.
|
||||
//
|
||||
// If ignoreLogging is true, the system logger will not be initialised nor
|
||||
// will this function make any log calls.
|
||||
//
|
||||
// All paths are resolved fully meaning if this function does not return an
|
||||
// error, all paths are valid at the time of the call.
|
||||
func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPath string, config oci.RuntimeConfig, err error) {
|
||||
func initConfig(builtIn bool) (config oci.RuntimeConfig, err error) {
|
||||
var defaultAgentConfig interface{}
|
||||
|
||||
defaultHypervisorConfig := vc.HypervisorConfig{
|
||||
HypervisorPath: defaultHypervisorPath,
|
||||
KernelPath: defaultKernelPath,
|
||||
@ -562,10 +560,17 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
||||
|
||||
err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel)
|
||||
if err != nil {
|
||||
return "", config, err
|
||||
return oci.RuntimeConfig{}, err
|
||||
}
|
||||
|
||||
defaultAgentConfig := vc.HyperConfig{}
|
||||
defaultAgentConfig = vc.HyperConfig{}
|
||||
|
||||
if builtIn {
|
||||
defaultProxy = vc.KataBuiltInProxyType
|
||||
defaultShim = vc.KataBuiltInShimType
|
||||
|
||||
defaultAgentConfig = vc.KataAgentConfig{LongLiveConn: true}
|
||||
}
|
||||
|
||||
config = oci.RuntimeConfig{
|
||||
HypervisorType: defaultHypervisor,
|
||||
@ -576,37 +581,51 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
||||
ShimType: defaultShim,
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// LoadConfiguration loads the configuration file and converts it into a
|
||||
// runtime configuration.
|
||||
//
|
||||
// If ignoreLogging is true, the system logger will not be initialised nor
|
||||
// will this function make any log calls.
|
||||
//
|
||||
// All paths are resolved fully meaning if this function does not return an
|
||||
// error, all paths are valid at the time of the call.
|
||||
func LoadConfiguration(configPath string, ignoreLogging, builtIn bool) (resolvedConfigPath string, config oci.RuntimeConfig, tracing bool, err error) {
|
||||
var resolved string
|
||||
|
||||
config, err = initConfig(builtIn)
|
||||
if err != nil {
|
||||
return "", oci.RuntimeConfig{}, tracing, err
|
||||
}
|
||||
|
||||
if configPath == "" {
|
||||
resolved, err = getDefaultConfigFile()
|
||||
} else {
|
||||
resolved, err = resolvePath(configPath)
|
||||
resolved, err = ResolvePath(configPath)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", config, fmt.Errorf("Cannot find usable config file (%v)", err)
|
||||
return "", config, tracing, fmt.Errorf("Cannot find usable config file (%v)", err)
|
||||
}
|
||||
|
||||
configData, err := ioutil.ReadFile(resolved)
|
||||
if err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
|
||||
var tomlConf tomlConfig
|
||||
_, err = toml.Decode(string(configData), &tomlConf)
|
||||
if err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
|
||||
if tomlConf.Runtime.Debug {
|
||||
config.Debug = true
|
||||
debug = true
|
||||
crashOnError = true
|
||||
} else {
|
||||
config.Debug = tomlConf.Runtime.Debug
|
||||
if !tomlConf.Runtime.Debug {
|
||||
// If debug is not required, switch back to the original
|
||||
// default log priority, otherwise continue in debug mode.
|
||||
kataLog.Logger.Level = originalLoggerLevel
|
||||
kataUtilsLogger.Logger.Level = originalLoggerLevel
|
||||
}
|
||||
|
||||
tracing = tomlConf.Runtime.Tracing
|
||||
@ -614,17 +633,17 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
||||
if tomlConf.Runtime.InterNetworkModel != "" {
|
||||
err = config.InterNetworkModel.SetModel(tomlConf.Runtime.InterNetworkModel)
|
||||
if err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
}
|
||||
|
||||
if !ignoreLogging {
|
||||
err = handleSystemLog("", "")
|
||||
err := handleSystemLog("", "")
|
||||
if err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
|
||||
kataLog.WithFields(
|
||||
kataUtilsLogger.WithFields(
|
||||
logrus.Fields{
|
||||
"format": "TOML",
|
||||
"file": resolved,
|
||||
@ -632,26 +651,26 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
||||
}
|
||||
|
||||
if err := updateRuntimeConfig(resolved, tomlConf, &config); err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
|
||||
config.DisableNewNetNs = tomlConf.Runtime.DisableNewNetNs
|
||||
if err := checkNetNsConfig(config); err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
|
||||
// use no proxy if HypervisorConfig.UseVSock is true
|
||||
if config.HypervisorConfig.UseVSock {
|
||||
kataLog.Info("VSOCK supported, configure to not use proxy")
|
||||
kataUtilsLogger.Info("VSOCK supported, configure to not use proxy")
|
||||
config.ProxyType = vc.NoProxyType
|
||||
config.ProxyConfig = vc.ProxyConfig{}
|
||||
}
|
||||
|
||||
if err := checkHypervisorConfig(config.HypervisorConfig); err != nil {
|
||||
return "", config, err
|
||||
return "", config, tracing, err
|
||||
}
|
||||
|
||||
return resolved, config, nil
|
||||
return resolved, config, tracing, nil
|
||||
}
|
||||
|
||||
// checkNetNsConfig performs sanity checks on disable_new_netns config.
|
||||
@ -714,7 +733,6 @@ func checkHypervisorConfig(config vc.HypervisorConfig) error {
|
||||
|
||||
msg := fmt.Sprintf("VM memory (%dMB) smaller than image %q size (%dMB)",
|
||||
memSizeMB, image.path, imageSizeMB)
|
||||
|
||||
if imageSizeMB >= memSizeMB {
|
||||
if image.initrd {
|
||||
// Initrd's need to be fully read into memory
|
||||
@ -726,7 +744,7 @@ func checkHypervisorConfig(config vc.HypervisorConfig) error {
|
||||
// unusual to have an image larger
|
||||
// than the amount of memory assigned
|
||||
// to the VM.
|
||||
kataLog.Warn(msg)
|
||||
kataUtilsLogger.Warn(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -734,9 +752,9 @@ func checkHypervisorConfig(config vc.HypervisorConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDefaultConfigFilePaths returns a list of paths that will be
|
||||
// GetDefaultConfigFilePaths returns a list of paths that will be
|
||||
// considered as configuration files in priority order.
|
||||
func getDefaultConfigFilePaths() []string {
|
||||
func GetDefaultConfigFilePaths() []string {
|
||||
return []string{
|
||||
// normally below "/etc"
|
||||
defaultSysConfRuntimeConfiguration,
|
||||
@ -752,8 +770,8 @@ func getDefaultConfigFilePaths() []string {
|
||||
func getDefaultConfigFile() (string, error) {
|
||||
var errs []string
|
||||
|
||||
for _, file := range getDefaultConfigFilePaths() {
|
||||
resolved, err := resolvePath(file)
|
||||
for _, file := range GetDefaultConfigFilePaths() {
|
||||
resolved, err := ResolvePath(file)
|
||||
if err == nil {
|
||||
return resolved, nil
|
||||
}
|
||||
@ -763,3 +781,18 @@ func getDefaultConfigFile() (string, error) {
|
||||
|
||||
return "", errors.New(strings.Join(errs, ", "))
|
||||
}
|
||||
|
||||
// SetConfigOptions will override some of the defaults settings.
|
||||
func SetConfigOptions(n, runtimeConfig, sysRuntimeConfig string) {
|
||||
if n != "" {
|
||||
name = n
|
||||
}
|
||||
|
||||
if runtimeConfig != "" {
|
||||
defaultRuntimeConfiguration = runtimeConfig
|
||||
}
|
||||
|
||||
if sysRuntimeConfig != "" {
|
||||
defaultSysConfRuntimeConfiguration = sysRuntimeConfig
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package main
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -140,7 +141,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
||||
|
||||
for _, file := range files {
|
||||
// create the resource (which must be >0 bytes)
|
||||
err := writeFile(file, "foo", testFileMode)
|
||||
err := WriteFile(file, "foo", testFileMode)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
@ -248,7 +249,7 @@ func testLoadConfiguration(t *testing.T, dir string,
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
resolvedConfigPath, config, err := loadConfiguration(file, ignoreLogging)
|
||||
resolvedConfigPath, config, _, err := LoadConfiguration(file, ignoreLogging, false)
|
||||
if expectFail {
|
||||
assert.Error(t, err)
|
||||
|
||||
@ -476,7 +477,7 @@ func TestConfigLoadConfigurationFailTOMLConfigFileDuplicatedData(t *testing.T) {
|
||||
func(config testRuntimeConfig, configFile string, ignoreLogging bool) (bool, error) {
|
||||
expectFail := true
|
||||
|
||||
text, err := getFileContents(config.ConfigPath)
|
||||
text, err := GetFileContents(config.ConfigPath)
|
||||
if err != nil {
|
||||
return expectFail, err
|
||||
}
|
||||
@ -530,7 +531,7 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
||||
defaultKernelPath = kernelPath
|
||||
|
||||
for _, file := range []string{defaultImagePath, defaultInitrdPath, defaultHypervisorPath, defaultKernelPath} {
|
||||
err = writeFile(file, "foo", testFileMode)
|
||||
err = WriteFile(file, "foo", testFileMode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -557,7 +558,7 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, config, err := loadConfiguration(configPath, false)
|
||||
_, config, _, err := LoadConfiguration(configPath, false, false)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected loadConfiguration to fail as shim path does not exist: %+v", config)
|
||||
}
|
||||
@ -582,7 +583,7 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, config, err = loadConfiguration(configPath, false)
|
||||
_, config, _, err = LoadConfiguration(configPath, false, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -675,7 +676,7 @@ func TestMinimalRuntimeConfigWithVsock(t *testing.T) {
|
||||
defaultKernelPath = kernelPath
|
||||
|
||||
for _, file := range []string{proxyPath, shimPath, hypervisorPath, kernelPath, imagePath} {
|
||||
err = writeFile(file, "foo", testFileMode)
|
||||
err = WriteFile(file, "foo", testFileMode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -711,7 +712,7 @@ func TestMinimalRuntimeConfigWithVsock(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, config, err := loadConfiguration(configPath, false)
|
||||
_, config, _, err := LoadConfiguration(configPath, false, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1152,7 +1153,7 @@ func TestShimDefaults(t *testing.T) {
|
||||
func TestGetDefaultConfigFilePaths(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
results := getDefaultConfigFilePaths()
|
||||
results := GetDefaultConfigFilePaths()
|
||||
// There should be atleast two config file locations
|
||||
assert.True(len(results) >= 2)
|
||||
|
||||
@ -1405,7 +1406,7 @@ func TestCheckHypervisorConfig(t *testing.T) {
|
||||
fileData := strings.Repeat("X", int(fileSizeBytes))
|
||||
|
||||
for _, file := range []string{image, initrd} {
|
||||
err = writeFile(file, fileData, testFileMode)
|
||||
err = WriteFile(file, fileData, testFileMode)
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
@ -1444,13 +1445,13 @@ func TestCheckHypervisorConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, d := range data {
|
||||
savedOut := kataLog.Logger.Out
|
||||
savedOut := kataUtilsLogger.Logger.Out
|
||||
|
||||
// create buffer to save logger output
|
||||
logBuf := &bytes.Buffer{}
|
||||
|
||||
// capture output to buffer
|
||||
kataLog.Logger.Out = logBuf
|
||||
kataUtilsLogger.Logger.Out = logBuf
|
||||
|
||||
config := vc.HypervisorConfig{
|
||||
ImagePath: d.imagePath,
|
||||
@ -1473,7 +1474,7 @@ func TestCheckHypervisorConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
// reset logger
|
||||
kataLog.Logger.Out = savedOut
|
||||
kataUtilsLogger.Logger.Out = savedOut
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package main
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/syslog"
|
||||
"time"
|
||||
|
||||
@ -13,6 +15,19 @@ import (
|
||||
lSyslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||
)
|
||||
|
||||
var originalLoggerLevel = logrus.InfoLevel
|
||||
var kataUtilsLogger = logrus.NewEntry(logrus.New())
|
||||
|
||||
// SetLogger sets the logger for the factory.
|
||||
func SetLogger(ctx context.Context, logger *logrus.Entry, level logrus.Level) {
|
||||
fields := logrus.Fields{
|
||||
"source": "katautils",
|
||||
}
|
||||
|
||||
originalLoggerLevel = level
|
||||
kataUtilsLogger = logger.WithFields(fields)
|
||||
}
|
||||
|
||||
// sysLogHook wraps a syslog logrus hook and a formatter to be used for all
|
||||
// syslog entries.
|
||||
//
|
||||
@ -64,7 +79,7 @@ func handleSystemLog(network, raddr string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
kataLog.Logger.Hooks.Add(hook)
|
||||
kataUtilsLogger.Logger.Hooks.Add(hook)
|
||||
|
||||
return nil
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package main
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -25,10 +26,10 @@ type testData struct {
|
||||
|
||||
func init() {
|
||||
// Ensure all log levels are logged
|
||||
kataLog.Logger.Level = logrus.DebugLevel
|
||||
kataUtilsLogger.Logger.Level = logrus.DebugLevel
|
||||
|
||||
// Discard log output
|
||||
kataLog.Logger.Out = ioutil.Discard
|
||||
kataUtilsLogger.Logger.Out = ioutil.Discard
|
||||
}
|
||||
|
||||
func TestHandleSystemLog(t *testing.T) {
|
77
pkg/katautils/utils.go
Normal file
77
pkg/katautils/utils.go
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ResolvePath returns the fully resolved and expanded value of the
|
||||
// specified path.
|
||||
func ResolvePath(path string) (string, error) {
|
||||
if path == "" {
|
||||
return "", fmt.Errorf("path must be specified")
|
||||
}
|
||||
|
||||
absolute, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resolved, err := filepath.EvalSymlinks(absolute)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// Make the error clearer than the default
|
||||
return "", fmt.Errorf("file %v does not exist", absolute)
|
||||
}
|
||||
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resolved, nil
|
||||
}
|
||||
|
||||
// fileSize returns the number of bytes in the specified file
|
||||
func fileSize(file string) (int64, error) {
|
||||
st := syscall.Stat_t{}
|
||||
|
||||
err := syscall.Stat(file, &st)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return st.Size, nil
|
||||
}
|
||||
|
||||
// WriteFile write data into specified file
|
||||
func WriteFile(filePath string, data string, fileMode os.FileMode) error {
|
||||
// Normally dir should not be empty, one case is that cgroup subsystem
|
||||
// is not mounted, we will get empty dir, and we want it fail here.
|
||||
if filePath == "" {
|
||||
return fmt.Errorf("no such file for %s", filePath)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filePath, []byte(data), fileMode); err != nil {
|
||||
return fmt.Errorf("failed to write %v to %v: %v", data, filePath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFileContents return the file contents as a string.
|
||||
func GetFileContents(file string) (string, error) {
|
||||
bytes, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(bytes), nil
|
||||
}
|
213
pkg/katautils/utils_test.go
Normal file
213
pkg/katautils/utils_test.go
Normal file
@ -0,0 +1,213 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
// Copyright (c) 2018 HyperHQ Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
testDirMode = os.FileMode(0750)
|
||||
testFileMode = os.FileMode(0640)
|
||||
|
||||
testDisabledNeedNonRoot = "Test disabled as requires non-root user"
|
||||
)
|
||||
|
||||
var testDir = ""
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
fmt.Printf("INFO: creating test directory\n")
|
||||
testDir, err = ioutil.TempDir("", fmt.Sprintf("%s-", name))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create test directory: %v", err))
|
||||
}
|
||||
|
||||
fmt.Printf("INFO: test directory is %v\n", testDir)
|
||||
}
|
||||
|
||||
func createFile(file, contents string) error {
|
||||
return ioutil.WriteFile(file, []byte(contents), testFileMode)
|
||||
}
|
||||
|
||||
func createEmptyFile(path string) (err error) {
|
||||
return ioutil.WriteFile(path, []byte(""), testFileMode)
|
||||
}
|
||||
|
||||
func TestUtilsResolvePathEmptyPath(t *testing.T) {
|
||||
_, err := ResolvePath("")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestUtilsResolvePathValidPath(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
target := path.Join(dir, "target")
|
||||
linkDir := path.Join(dir, "a/b/c")
|
||||
linkFile := path.Join(linkDir, "link")
|
||||
|
||||
err = createEmptyFile(target)
|
||||
assert.NoError(t, err)
|
||||
|
||||
absolute, err := filepath.Abs(target)
|
||||
assert.NoError(t, err)
|
||||
|
||||
resolvedTarget, err := filepath.EvalSymlinks(absolute)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.MkdirAll(linkDir, testDirMode)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = syscall.Symlink(target, linkFile)
|
||||
assert.NoError(t, err)
|
||||
|
||||
resolvedLink, err := ResolvePath(linkFile)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, resolvedTarget, resolvedLink)
|
||||
}
|
||||
|
||||
func TestUtilsResolvePathENOENT(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
target := path.Join(dir, "target")
|
||||
linkDir := path.Join(dir, "a/b/c")
|
||||
linkFile := path.Join(linkDir, "link")
|
||||
|
||||
err = createEmptyFile(target)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.MkdirAll(linkDir, testDirMode)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = syscall.Symlink(target, linkFile)
|
||||
assert.NoError(t, err)
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
assert.NoError(t, err)
|
||||
defer os.Chdir(cwd)
|
||||
|
||||
err = os.Chdir(dir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = os.RemoveAll(dir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = ResolvePath(filepath.Base(linkFile))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFileSize(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
file := filepath.Join(dir, "foo")
|
||||
|
||||
// ENOENT
|
||||
_, err = fileSize(file)
|
||||
assert.Error(err)
|
||||
|
||||
err = createEmptyFile(file)
|
||||
assert.NoError(err)
|
||||
|
||||
// zero size
|
||||
size, err := fileSize(file)
|
||||
assert.NoError(err)
|
||||
assert.Equal(size, int64(0))
|
||||
|
||||
msg := "hello"
|
||||
msgLen := len(msg)
|
||||
|
||||
err = WriteFile(file, msg, testFileMode)
|
||||
assert.NoError(err)
|
||||
|
||||
size, err = fileSize(file)
|
||||
assert.NoError(err)
|
||||
assert.Equal(size, int64(msgLen))
|
||||
}
|
||||
|
||||
func TestWriteFileErrWriteFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
err := WriteFile("", "", 0000)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestWriteFileErrNoPath(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// attempt to write a file over an existing directory
|
||||
err = WriteFile(dir, "", 0000)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestGetFileContents(t *testing.T) {
|
||||
type testData struct {
|
||||
contents string
|
||||
}
|
||||
|
||||
data := []testData{
|
||||
{""},
|
||||
{" "},
|
||||
{"\n"},
|
||||
{"\n\n"},
|
||||
{"\n\n\n"},
|
||||
{"foo"},
|
||||
{"foo\nbar"},
|
||||
{"processor : 0\nvendor_id : GenuineIntel\n"},
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
file := filepath.Join(dir, "foo")
|
||||
|
||||
// file doesn't exist
|
||||
_, err = GetFileContents(file)
|
||||
assert.Error(t, err)
|
||||
|
||||
for _, d := range data {
|
||||
// create the file
|
||||
err = ioutil.WriteFile(file, []byte(d.contents), testFileMode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file)
|
||||
|
||||
contents, err := GetFileContents(file)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, contents, d.contents)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user