mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-01-30 19:54:28 +01:00
Add a new hypervisor capability to tell if it supports device hotplug. If not, we should run prestart hooks before starting new VMs as nerdctl is using the prestart hooks to set up netns. To make nerdctl + FC to work, we need to run the prestart hooks before starting new VMs. Fixes: #6384 Signed-off-by: Peng Tao <bergwolf@hyper.sh>
288 lines
5.9 KiB
Go
288 lines
5.9 KiB
Go
//go:build linux
|
|
|
|
// Copyright (c) 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package virtcontainers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
|
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist"
|
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func newAcrnConfig() HypervisorConfig {
|
|
return HypervisorConfig{
|
|
KernelPath: testAcrnKernelPath,
|
|
ImagePath: testAcrnImagePath,
|
|
HypervisorPath: testAcrnPath,
|
|
HypervisorCtlPath: testAcrnCtlPath,
|
|
NumVCPUs: defaultVCPUs,
|
|
MemorySize: defaultMemSzMiB,
|
|
BlockDeviceDriver: config.VirtioBlock,
|
|
DefaultBridges: defaultBridges,
|
|
DefaultMaxVCPUs: MaxAcrnVCPUs(),
|
|
// Adding this here, as hypervisorconfig.valid()
|
|
// forcefully adds it even when 9pfs is not supported
|
|
Msize9p: defaultMsize9p,
|
|
}
|
|
}
|
|
|
|
func testAcrnKernelParameters(t *testing.T, kernelParams []Param, debug bool) {
|
|
assert := assert.New(t)
|
|
acrnConfig := newAcrnConfig()
|
|
acrnConfig.KernelParams = kernelParams
|
|
|
|
if debug == true {
|
|
acrnConfig.Debug = true
|
|
}
|
|
|
|
a := &Acrn{
|
|
config: acrnConfig,
|
|
arch: &acrnArchBase{},
|
|
}
|
|
|
|
expected := fmt.Sprintf("panic=1 maxcpus=%d foo=foo bar=bar", a.config.DefaultMaxVCPUs)
|
|
|
|
params := a.kernelParameters()
|
|
assert.Equal(params, expected)
|
|
}
|
|
|
|
func TestAcrnKernelParameters(t *testing.T) {
|
|
params := []Param{
|
|
{
|
|
Key: "foo",
|
|
Value: "foo",
|
|
},
|
|
{
|
|
Key: "bar",
|
|
Value: "bar",
|
|
},
|
|
}
|
|
|
|
testAcrnKernelParameters(t, params, true)
|
|
testAcrnKernelParameters(t, params, false)
|
|
}
|
|
|
|
func TestAcrnCapabilities(t *testing.T) {
|
|
assert := assert.New(t)
|
|
a := &Acrn{
|
|
ctx: context.Background(),
|
|
arch: &acrnArchBase{},
|
|
}
|
|
|
|
caps := a.Capabilities(a.ctx)
|
|
assert.True(caps.IsBlockDeviceSupported())
|
|
assert.True(caps.IsBlockDeviceHotplugSupported())
|
|
assert.True(caps.IsNetworkDeviceHotplugSupported())
|
|
}
|
|
|
|
func testAcrnAddDevice(t *testing.T, devInfo interface{}, devType DeviceType, expected []Device) {
|
|
assert := assert.New(t)
|
|
a := &Acrn{
|
|
ctx: context.Background(),
|
|
arch: &acrnArchBase{},
|
|
}
|
|
|
|
err := a.AddDevice(context.Background(), devInfo, devType)
|
|
assert.NoError(err)
|
|
assert.Exactly(a.acrnConfig.Devices, expected)
|
|
}
|
|
|
|
func TestAcrnAddDeviceSerialPortDev(t *testing.T) {
|
|
name := "serial.test"
|
|
hostPath := "/tmp/serial.sock"
|
|
|
|
expectedOut := []Device{
|
|
ConsoleDevice{
|
|
Name: name,
|
|
Backend: Socket,
|
|
PortType: SerialBE,
|
|
Path: hostPath,
|
|
},
|
|
}
|
|
|
|
socket := types.Socket{
|
|
HostPath: hostPath,
|
|
Name: name,
|
|
}
|
|
|
|
testAcrnAddDevice(t, socket, SerialPortDev, expectedOut)
|
|
}
|
|
|
|
func TestAcrnAddDeviceBlockDev(t *testing.T) {
|
|
path := "/tmp/test.img"
|
|
index := 1
|
|
|
|
expectedOut := []Device{
|
|
BlockDevice{
|
|
FilePath: path,
|
|
Index: index,
|
|
},
|
|
}
|
|
|
|
drive := config.BlockDrive{
|
|
File: path,
|
|
Index: index,
|
|
}
|
|
|
|
testAcrnAddDevice(t, drive, BlockDev, expectedOut)
|
|
}
|
|
|
|
func TestAcrnHotplugUnsupportedDeviceType(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
acrnConfig := newAcrnConfig()
|
|
a := &Acrn{
|
|
ctx: context.Background(),
|
|
id: "acrnTest",
|
|
config: acrnConfig,
|
|
}
|
|
|
|
_, err := a.HotplugAddDevice(a.ctx, &MemoryDevice{0, 128, uint64(0), false}, FsDev)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestAcrnUpdateBlockDeviceInvalidPath(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
path := ""
|
|
index := 1
|
|
|
|
acrnConfig := newAcrnConfig()
|
|
a := &Acrn{
|
|
ctx: context.Background(),
|
|
id: "acrnBlkTest",
|
|
config: acrnConfig,
|
|
}
|
|
|
|
drive := &config.BlockDrive{
|
|
File: path,
|
|
Index: index,
|
|
}
|
|
|
|
err := a.updateBlockDevice(drive)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestAcrnUpdateBlockDeviceInvalidIdx(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
path := "/tmp/test.img"
|
|
index := AcrnBlkDevPoolSz + 1
|
|
|
|
acrnConfig := newAcrnConfig()
|
|
a := &Acrn{
|
|
ctx: context.Background(),
|
|
id: "acrnBlkTest",
|
|
config: acrnConfig,
|
|
}
|
|
|
|
drive := &config.BlockDrive{
|
|
File: path,
|
|
Index: index,
|
|
}
|
|
|
|
err := a.updateBlockDevice(drive)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestAcrnGetSandboxConsole(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
store, err := persist.GetDriver()
|
|
assert.NoError(err)
|
|
|
|
a := &Acrn{
|
|
ctx: context.Background(),
|
|
config: HypervisorConfig{
|
|
VMStorePath: store.RunVMStoragePath(),
|
|
RunStorePath: store.RunStoragePath(),
|
|
},
|
|
store: store,
|
|
}
|
|
sandboxID := "testSandboxID"
|
|
expected := filepath.Join(store.RunVMStoragePath(), sandboxID, consoleSocket)
|
|
|
|
proto, result, err := a.GetVMConsole(a.ctx, sandboxID)
|
|
assert.NoError(err)
|
|
assert.Equal(result, expected)
|
|
assert.Equal(proto, consoleProtoUnix)
|
|
}
|
|
|
|
func TestAcrnCreateVM(t *testing.T) {
|
|
assert := assert.New(t)
|
|
acrnConfig := newAcrnConfig()
|
|
store, err := persist.GetDriver()
|
|
assert.NoError(err)
|
|
|
|
a := &Acrn{
|
|
store: store,
|
|
config: HypervisorConfig{
|
|
VMStorePath: store.RunVMStoragePath(),
|
|
RunStorePath: store.RunStoragePath(),
|
|
},
|
|
}
|
|
|
|
sandbox := &Sandbox{
|
|
ctx: context.Background(),
|
|
id: "testSandbox",
|
|
config: &SandboxConfig{
|
|
HypervisorConfig: acrnConfig,
|
|
},
|
|
state: types.SandboxState{BlockIndexMap: make(map[int]struct{})},
|
|
}
|
|
|
|
a.sandbox = sandbox
|
|
|
|
a.state.PID = 1
|
|
network, err := NewNetwork()
|
|
assert.NoError(err)
|
|
err = a.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)
|
|
assert.NoError(err)
|
|
assert.Exactly(acrnConfig, a.config)
|
|
}
|
|
|
|
func TestAcrnMemoryTopology(t *testing.T) {
|
|
mem := uint32(1000)
|
|
assert := assert.New(t)
|
|
|
|
a := &Acrn{
|
|
arch: &acrnArchBase{},
|
|
config: HypervisorConfig{
|
|
MemorySize: mem,
|
|
},
|
|
}
|
|
|
|
expectedOut := Memory{
|
|
Size: fmt.Sprintf("%dM", mem),
|
|
}
|
|
|
|
memory, err := a.memoryTopology()
|
|
assert.NoError(err)
|
|
assert.Exactly(memory, expectedOut)
|
|
}
|
|
|
|
func TestAcrnSetConfig(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
config := newAcrnConfig()
|
|
|
|
a := &Acrn{}
|
|
|
|
assert.Equal(a.config, HypervisorConfig{})
|
|
|
|
err := a.setConfig(&config)
|
|
assert.NoError(err)
|
|
|
|
assert.Equal(a.config, config)
|
|
}
|