diff --git a/Makefile b/Makefile index 6ec64689e..96b26dc6e 100644 --- a/Makefile +++ b/Makefile @@ -116,6 +116,9 @@ SHIMPATH := $(PKGLIBEXECDIR)/$(SHIMCMD) PROXYCMD := $(BIN_PREFIX)-proxy PROXYPATH := $(PKGLIBEXECDIR)/$(PROXYCMD) +NETMONCMD := $(BIN_PREFIX)-netmon +NETMONPATH := $(PKGLIBEXECDIR)/$(NETMONCMD) + # Default number of vCPUs DEFVCPUS := 1 # Default maximum number of vCPUs @@ -189,6 +192,7 @@ USER_VARS += PROJECT_NAME USER_VARS += PROJECT_PREFIX USER_VARS += PROJECT_TYPE USER_VARS += PROXYPATH +USER_VARS += NETMONPATH USER_VARS += QEMUBINDIR USER_VARS += QEMUCMD USER_VARS += QEMUPATH @@ -319,6 +323,7 @@ var defaultRuntimeConfiguration = "$(CONFIG_PATH)" var defaultSysConfRuntimeConfiguration = "$(SYSCONFIG)" var defaultProxyPath = "$(PROXYPATH)" +var defaultNetmonPath = "$(NETMONPATH)" endef export GENERATED_CODE @@ -373,6 +378,7 @@ $(GENERATED_FILES): %: %.in Makefile VERSION -e "s|@LOCALSTATEDIR@|$(LOCALSTATEDIR)|g" \ -e "s|@PKGLIBEXECDIR@|$(PKGLIBEXECDIR)|g" \ -e "s|@PROXYPATH@|$(PROXYPATH)|g" \ + -e "s|@NETMONPATH@|$(NETMONPATH)|g" \ -e "s|@PROJECT_BUG_URL@|$(PROJECT_BUG_URL)|g" \ -e "s|@PROJECT_URL@|$(PROJECT_URL)|g" \ -e "s|@PROJECT_NAME@|$(PROJECT_NAME)|g" \ diff --git a/cli/config.go b/cli/config.go index 2e463c488..7c69fb0ff 100644 --- a/cli/config.go +++ b/cli/config.go @@ -64,6 +64,7 @@ type tomlConfig struct { Agent map[string]agent Runtime runtime Factory factory + Netmon netmon } type factory struct { @@ -116,6 +117,12 @@ type shim struct { type agent struct { } +type netmon struct { + Path string `toml:"path"` + Debug bool `toml:"enable_debug"` + Enable bool `toml:"enable_netmon"` +} + func (h hypervisor) path() (string, error) { p := h.Path @@ -302,6 +309,22 @@ func (s shim) debug() bool { return s.Debug } +func (n netmon) enable() bool { + return n.Enable +} + +func (n netmon) path() string { + if n.Path == "" { + return defaultNetmonPath + } + + return n.Path +} + +func (n netmon) debug() bool { + return n.Debug +} + func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { hypervisor, err := h.path() if err != nil { @@ -464,6 +487,12 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run } config.FactoryConfig = fConfig + config.NetmonConfig = vc.NetmonConfig{ + Path: tomlConf.Netmon.path(), + Debug: tomlConf.Netmon.debug(), + Enable: tomlConf.Netmon.enable(), + } + return nil } diff --git a/cli/config/configuration.toml.in b/cli/config/configuration.toml.in index 842ff16b0..305fc275f 100644 --- a/cli/config/configuration.toml.in +++ b/cli/config/configuration.toml.in @@ -181,6 +181,21 @@ path = "@SHIMPATH@" # There is no field for this section. The goal is only to be able to # specify which type of agent the user wants to use. +[netmon] +# If enabled, the network monitoring process gets started when the +# sandbox is created. This allows for the detection of some additional +# network being added to the existing network namespace, after the +# sandbox has been created. +# (default: disabled) +#enable_netmon = true + +# Specify the path to the netmon binary. +path = "@NETMONPATH@" + +# If enabled, netmon messages will be sent to the system log +# (default: disabled) +#enable_debug = true + [runtime] # If enabled, the runtime will log additional debug messages to the # system log diff --git a/cli/config_test.go b/cli/config_test.go index 10290d89e..c83563966 100644 --- a/cli/config_test.go +++ b/cli/config_test.go @@ -30,6 +30,7 @@ var ( proxyDebug = false runtimeDebug = false shimDebug = false + netmonDebug = false ) type testRuntimeConfig struct { @@ -41,7 +42,7 @@ type testRuntimeConfig struct { LogPath string } -func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus bool) string { +func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus bool) string { return ` # Runtime configuration file @@ -71,6 +72,10 @@ func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath [agent.kata] + [netmon] + path = "` + netmonPath + `" + enable_debug = ` + strconv.FormatBool(netmonDebug) + ` + [runtime] enable_debug = ` + strconv.FormatBool(runtimeDebug) } @@ -103,6 +108,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf imagePath := path.Join(dir, "image") shimPath := path.Join(dir, "shim") proxyPath := path.Join(dir, "proxy") + netmonPath := path.Join(dir, "netmon") logDir := path.Join(dir, "logs") logPath := path.Join(logDir, "runtime.log") machineType := "machineType" @@ -111,7 +117,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf enableIOThreads := true hotplugVFIOOnRootBus := true - runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads, hotplugVFIOOnRootBus) + runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads, hotplugVFIOOnRootBus) configPath := path.Join(dir, "runtime.toml") err = createConfig(configPath, runtimeConfigFileData) @@ -165,6 +171,12 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf Path: shimPath, } + netmonConfig := vc.NetmonConfig{ + Path: netmonPath, + Debug: false, + Enable: false, + } + runtimeConfig := oci.RuntimeConfig{ HypervisorType: defaultHypervisor, HypervisorConfig: hypervisorConfig, @@ -177,6 +189,8 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf ShimType: defaultShim, ShimConfig: shimConfig, + + NetmonConfig: netmonConfig, } config = testRuntimeConfig{ @@ -482,11 +496,11 @@ func TestMinimalRuntimeConfig(t *testing.T) { proxyPath := path.Join(dir, "proxy") hypervisorPath := path.Join(dir, "hypervisor") defaultHypervisorPath = hypervisorPath + netmonPath := path.Join(dir, "netmon") imagePath := path.Join(dir, "image.img") initrdPath := path.Join(dir, "initrd.img") - hypervisorPath = path.Join(dir, "hypervisor") kernelPath := path.Join(dir, "kernel") savedDefaultImagePath := defaultImagePath @@ -525,6 +539,9 @@ func TestMinimalRuntimeConfig(t *testing.T) { path = "` + shimPath + `" [agent.kata] + + [netmon] + path = "` + netmonPath + `" ` configPath := path.Join(dir, "runtime.toml") @@ -553,6 +570,11 @@ func TestMinimalRuntimeConfig(t *testing.T) { t.Error(err) } + err = createEmptyFile(netmonPath) + if err != nil { + t.Error(err) + } + _, config, err = loadConfiguration(configPath, false) if err != nil { t.Fatal(err) @@ -584,6 +606,12 @@ func TestMinimalRuntimeConfig(t *testing.T) { Path: shimPath, } + expectedNetmonConfig := vc.NetmonConfig{ + Path: netmonPath, + Debug: false, + Enable: false, + } + expectedConfig := oci.RuntimeConfig{ HypervisorType: defaultHypervisor, HypervisorConfig: expectedHypervisorConfig, @@ -596,6 +624,8 @@ func TestMinimalRuntimeConfig(t *testing.T) { ShimType: defaultShim, ShimConfig: expectedShimConfig, + + NetmonConfig: expectedNetmonConfig, } if reflect.DeepEqual(config, expectedConfig) == false { diff --git a/cli/kata-env.go b/cli/kata-env.go index 595ce19f1..e2a24c746 100644 --- a/cli/kata-env.go +++ b/cli/kata-env.go @@ -25,7 +25,7 @@ import ( // // XXX: Increment for every change to the output format // (meaning any change to the EnvInfo type). -const formatVersion = "1.0.15" +const formatVersion = "1.0.16" // MetaInfo stores information on the format of the output itself type MetaInfo struct { @@ -123,6 +123,14 @@ type HostInfo struct { SupportVSocks bool } +// NetmonInfo stores netmon details +type NetmonInfo struct { + Version string + Path string + Debug bool + Enable bool +} + // EnvInfo collects all information that will be displayed by the // env command. // @@ -138,6 +146,7 @@ type EnvInfo struct { Shim ShimInfo Agent AgentInfo Host HostInfo + Netmon NetmonInfo } func getMetaInfo() MetaInfo { @@ -241,6 +250,22 @@ func getProxyInfo(config oci.RuntimeConfig) (ProxyInfo, error) { return proxy, nil } +func getNetmonInfo(config oci.RuntimeConfig) (NetmonInfo, error) { + version, err := getCommandVersion(defaultNetmonPath) + if err != nil { + version = unknown + } + + netmon := NetmonInfo{ + Version: version, + Path: config.NetmonConfig.Path, + Debug: config.NetmonConfig.Debug, + Enable: config.NetmonConfig.Enable, + } + + return netmon, nil +} + func getCommandVersion(cmd string) (string, error) { return runCommand([]string{cmd, "--version"}) } @@ -309,6 +334,8 @@ func getEnvInfo(configFile string, config oci.RuntimeConfig) (env EnvInfo, err e proxy, _ := getProxyInfo(config) + netmon, _ := getNetmonInfo(config) + shim, err := getShimInfo(config) if err != nil { return EnvInfo{}, err @@ -342,6 +369,7 @@ func getEnvInfo(configFile string, config oci.RuntimeConfig) (env EnvInfo, err e Shim: shim, Agent: agent, Host: host, + Netmon: netmon, } return env, nil diff --git a/cli/kata-env_test.go b/cli/kata-env_test.go index c49d98995..c3a888e8b 100644 --- a/cli/kata-env_test.go +++ b/cli/kata-env_test.go @@ -31,6 +31,7 @@ import ( const testProxyURL = "file:///proxyURL" const testProxyVersion = "proxy version 0.1" 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" // makeVersionBinary creates a shell script with the specified file @@ -61,6 +62,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC machineType := "machineType" shimPath := filepath.Join(prefixDir, "shim") proxyPath := filepath.Join(prefixDir, "proxy") + netmonPath := filepath.Join(prefixDir, "netmon") disableBlock := true blockStorageDriver := "virtio-scsi" enableIOThreads := true @@ -68,6 +70,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC // override defaultProxyPath = proxyPath + defaultNetmonPath = netmonPath filesToCreate := []string{ hypervisorPath, @@ -93,6 +96,11 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC return "", oci.RuntimeConfig{}, err } + err = makeVersionBinary(netmonPath, testNetmonVersion) + if err != nil { + return "", oci.RuntimeConfig{}, err + } + err = makeVersionBinary(hypervisorPath, testHypervisorVersion) if err != nil { return "", oci.RuntimeConfig{}, err @@ -107,6 +115,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC machineType, shimPath, testProxyURL, + netmonPath, logPath, disableBlock, blockStorageDriver, @@ -137,6 +146,15 @@ func getExpectedProxyDetails(config oci.RuntimeConfig) (ProxyInfo, error) { }, nil } +func getExpectedNetmonDetails(config oci.RuntimeConfig) (NetmonInfo, error) { + return NetmonInfo{ + Version: testNetmonVersion, + Path: config.NetmonConfig.Path, + Debug: config.NetmonConfig.Debug, + Enable: config.NetmonConfig.Enable, + }, nil +} + func getExpectedShimDetails(config oci.RuntimeConfig) (ShimInfo, error) { shimConfig, ok := config.ShimConfig.(vc.ShimConfig) if !ok { @@ -303,6 +321,11 @@ func getExpectedSettings(config oci.RuntimeConfig, tmpdir, configFile string) (E return EnvInfo{}, err } + netmon, err := getExpectedNetmonDetails(config) + if err != nil { + return EnvInfo{}, err + } + hypervisor := getExpectedHypervisor(config) kernel := getExpectedKernel(config) image := getExpectedImage(config) @@ -317,6 +340,7 @@ func getExpectedSettings(config oci.RuntimeConfig, tmpdir, configFile string) (E Shim: shim, Agent: agent, Host: host, + Netmon: netmon, } return env, nil @@ -608,6 +632,50 @@ func TestEnvGetProxyInfoNoVersion(t *testing.T) { assert.Equal(t, expectedProxy, proxy) } +func TestEnvGetNetmonInfo(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "") + if err != nil { + panic(err) + } + defer os.RemoveAll(tmpdir) + + _, config, err := makeRuntimeConfig(tmpdir) + assert.NoError(t, err) + + expectedNetmon, err := getExpectedNetmonDetails(config) + assert.NoError(t, err) + + netmon, err := getNetmonInfo(config) + assert.NoError(t, err) + + assert.Equal(t, expectedNetmon, netmon) +} + +func TestEnvGetNetmonInfoNoVersion(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "") + if err != nil { + panic(err) + } + defer os.RemoveAll(tmpdir) + + _, config, err := makeRuntimeConfig(tmpdir) + assert.NoError(t, err) + + expectedNetmon, err := getExpectedNetmonDetails(config) + assert.NoError(t, err) + + // remove the netmon ensuring its version cannot be queried + err = os.Remove(defaultNetmonPath) + assert.NoError(t, err) + + expectedNetmon.Version = unknown + + netmon, err := getNetmonInfo(config) + assert.NoError(t, err) + + assert.Equal(t, expectedNetmon, netmon) +} + func TestEnvGetShimInfo(t *testing.T) { tmpdir, err := ioutil.TempDir("", "") if err != nil { diff --git a/virtcontainers/pkg/oci/utils.go b/virtcontainers/pkg/oci/utils.go index 66a809c5a..665b54123 100644 --- a/virtcontainers/pkg/oci/utils.go +++ b/virtcontainers/pkg/oci/utils.go @@ -103,6 +103,8 @@ type RuntimeConfig struct { HypervisorType vc.HypervisorType HypervisorConfig vc.HypervisorConfig + NetmonConfig vc.NetmonConfig + AgentType vc.AgentType AgentConfig interface{} @@ -325,6 +327,12 @@ func networkConfig(ocispec CompatOCISpec, config RuntimeConfig) (vc.NetworkConfi } netConf.InterworkingModel = config.InterNetworkModel + netConf.NetmonConfig = vc.NetmonConfig{ + Path: config.NetmonConfig.Path, + Debug: config.NetmonConfig.Debug, + Enable: config.NetmonConfig.Enable, + } + return netConf, nil }