virtcontainers: config validation is host specific

Ideally this config validation would be in a seperate package
(katautils?), but that would introduce circular dependency since we'd
call it from vc, and it depends on vc types (which, shouldn't be vc, but
probably a hypervisor package instead).

Signed-off-by: Eric Ernst <eric_ernst@apple.com>
This commit is contained in:
Eric Ernst 2022-05-23 17:15:50 -07:00
parent bdf5e5229b
commit 5f936f268f
5 changed files with 244 additions and 56 deletions

View File

@ -0,0 +1,33 @@
// Copyright (c) 2022 Apple Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"fmt"
)
func validateHypervisorConfig(conf *HypervisorConfig) error {
if conf.KernelPath == "" {
return fmt.Errorf("Missing kernel path")
}
if conf.ImagePath == "" && conf.InitrdPath == "" {
return fmt.Errorf("Missing image and initrd path")
} else if conf.ImagePath != "" && conf.InitrdPath != "" {
return fmt.Errorf("Image and initrd path cannot be both set")
}
if conf.NumVCPUs == 0 {
conf.NumVCPUs = defaultVCPUs
}
if conf.MemorySize == 0 {
conf.MemorySize = defaultMemSzMiB
}
return nil
}

View File

@ -0,0 +1,67 @@
// Copyright (c) 2022 Apple Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"fmt"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
)
func validateHypervisorConfig(conf *HypervisorConfig) error {
if conf.KernelPath == "" {
return fmt.Errorf("Missing kernel path")
}
if conf.ConfidentialGuest && conf.HypervisorMachineType == QemuCCWVirtio {
if conf.ImagePath != "" || conf.InitrdPath != "" {
fmt.Println("yes, failing")
return fmt.Errorf("Neither the image or initrd path may be set for Secure Execution")
}
} else if conf.ImagePath == "" && conf.InitrdPath == "" {
return fmt.Errorf("Missing image and initrd path")
} else if conf.ImagePath != "" && conf.InitrdPath != "" {
return fmt.Errorf("Image and initrd path cannot be both set")
}
if err := conf.CheckTemplateConfig(); err != nil {
return err
}
if conf.NumVCPUs == 0 {
conf.NumVCPUs = defaultVCPUs
}
if conf.MemorySize == 0 {
conf.MemorySize = defaultMemSzMiB
}
if conf.DefaultBridges == 0 {
conf.DefaultBridges = defaultBridges
}
if conf.BlockDeviceDriver == "" {
conf.BlockDeviceDriver = defaultBlockDriver
} else if conf.BlockDeviceDriver == config.VirtioBlock && conf.HypervisorMachineType == QemuCCWVirtio {
conf.BlockDeviceDriver = config.VirtioBlockCCW
}
if conf.DefaultMaxVCPUs == 0 || conf.DefaultMaxVCPUs > defaultMaxVCPUs {
conf.DefaultMaxVCPUs = defaultMaxVCPUs
}
if conf.ConfidentialGuest && conf.NumVCPUs != conf.DefaultMaxVCPUs {
hvLogger.Warnf("Confidential guests do not support hotplugging of vCPUs. Setting DefaultMaxVCPUs to NumVCPUs (%d)", conf.NumVCPUs)
conf.DefaultMaxVCPUs = conf.NumVCPUs
}
if conf.Msize9p == 0 && conf.SharedFS != config.VirtioFS {
conf.Msize9p = defaultMsize9p
}
return nil
}

View File

@ -0,0 +1,114 @@
// Copyright (c) 2022 Apple Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHypervisorConfigNoImagePath(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: "",
HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
}
testHypervisorConfigValid(t, hypervisorConfig, false)
}
func TestHypervisorConfigNoHypervisorPath(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
HypervisorPath: "",
}
testHypervisorConfigValid(t, hypervisorConfig, true)
}
func TestHypervisorConfigIsValid(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
}
testHypervisorConfigValid(t, hypervisorConfig, true)
}
func TestHypervisorConfigBothInitrdAndImage(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
InitrdPath: fmt.Sprintf("%s/%s", testDir, testInitrd),
HypervisorPath: "",
}
testHypervisorConfigValid(t, hypervisorConfig, false)
}
func TestHypervisorConfigSecureExecution(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
InitrdPath: fmt.Sprintf("%s/%s", testDir, testInitrd),
ConfidentialGuest: true,
HypervisorMachineType: QemuCCWVirtio,
}
// Secure Execution should only specify a kernel (encrypted image contains all components)
testHypervisorConfigValid(t, hypervisorConfig, false)
}
func TestHypervisorConfigValidTemplateConfig(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
BootToBeTemplate: true,
BootFromTemplate: true,
}
testHypervisorConfigValid(t, hypervisorConfig, false)
hypervisorConfig.BootToBeTemplate = false
testHypervisorConfigValid(t, hypervisorConfig, false)
hypervisorConfig.MemoryPath = "foobar"
testHypervisorConfigValid(t, hypervisorConfig, false)
hypervisorConfig.DevicesStatePath = "foobar"
testHypervisorConfigValid(t, hypervisorConfig, true)
hypervisorConfig.BootFromTemplate = false
hypervisorConfig.BootToBeTemplate = true
testHypervisorConfigValid(t, hypervisorConfig, true)
hypervisorConfig.MemoryPath = ""
testHypervisorConfigValid(t, hypervisorConfig, false)
}
func TestHypervisorConfigDefaults(t *testing.T) {
assert := assert.New(t)
hypervisorConfig := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
HypervisorPath: "",
}
testHypervisorConfigValid(t, hypervisorConfig, true)
hypervisorConfigDefaultsExpected := &HypervisorConfig{
KernelPath: fmt.Sprintf("%s/%s", testDir, testKernel),
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
HypervisorPath: "",
NumVCPUs: defaultVCPUs,
MemorySize: defaultMemSzMiB,
DefaultBridges: defaultBridges,
BlockDeviceDriver: defaultBlockDriver,
DefaultMaxVCPUs: defaultMaxVCPUs,
Msize9p: defaultMsize9p,
}
assert.Exactly(hypervisorConfig, hypervisorConfigDefaultsExpected)
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2022 Apple Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func testHypervisorConfigValid(t *testing.T, hypervisorConfig *HypervisorConfig, success bool) {
err := validateHypervisorConfig(hypervisorConfig)
assert := assert.New(t)
assert.False(success && err != nil)
assert.False(!success && err == nil)
}
func TestHypervisorConfigNoKernelPath(t *testing.T) {
hypervisorConfig := &HypervisorConfig{
KernelPath: "",
ImagePath: fmt.Sprintf("%s/%s", testDir, testImage),
HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
}
testHypervisorConfigValid(t, hypervisorConfig, false)
}

View File

@ -609,62 +609,6 @@ func newSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factor
return s, nil
}
func validateHypervisorConfig(conf *HypervisorConfig) error {
if conf.KernelPath == "" {
return fmt.Errorf("Missing kernel path")
}
QemuCCWVirtio := ""
if conf.ConfidentialGuest && conf.HypervisorMachineType == QemuCCWVirtio {
if conf.ImagePath != "" || conf.InitrdPath != "" {
fmt.Println("yes, failing")
return fmt.Errorf("Neither the image or initrd path may be set for Secure Execution")
}
} else if conf.ImagePath == "" && conf.InitrdPath == "" {
return fmt.Errorf("Missing image and initrd path")
} else if conf.ImagePath != "" && conf.InitrdPath != "" {
return fmt.Errorf("Image and initrd path cannot be both set")
}
if err := conf.CheckTemplateConfig(); err != nil {
return err
}
if conf.NumVCPUs == 0 {
conf.NumVCPUs = defaultVCPUs
}
if conf.MemorySize == 0 {
conf.MemorySize = defaultMemSzMiB
}
if conf.DefaultBridges == 0 {
conf.DefaultBridges = defaultBridges
}
if conf.BlockDeviceDriver == "" {
conf.BlockDeviceDriver = defaultBlockDriver
} else if conf.BlockDeviceDriver == config.VirtioBlock && conf.HypervisorMachineType == QemuCCWVirtio {
conf.BlockDeviceDriver = config.VirtioBlockCCW
}
if conf.DefaultMaxVCPUs == 0 || conf.DefaultMaxVCPUs > defaultMaxVCPUs {
conf.DefaultMaxVCPUs = defaultMaxVCPUs
}
if conf.ConfidentialGuest && conf.NumVCPUs != conf.DefaultMaxVCPUs {
hvLogger.Warnf("Confidential guests do not support hotplugging of vCPUs. Setting DefaultMaxVCPUs to NumVCPUs (%d)", conf.NumVCPUs)
conf.DefaultMaxVCPUs = conf.NumVCPUs
}
if conf.Msize9p == 0 && conf.SharedFS != config.VirtioFS {
conf.Msize9p = defaultMsize9p
}
return nil
}
func (s *Sandbox) createResourceController() error {
var err error
cgroupPath := ""