mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-19 23:34:23 +01:00
runtime: move all code to src/runtime
To prepare for merging into kata-containers repository. Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
568
src/runtime/virtcontainers/qemu_arch_base_test.go
Normal file
568
src/runtime/virtcontainers/qemu_arch_base_test.go
Normal file
@@ -0,0 +1,568 @@
|
||||
// Copyright (c) 2018 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package virtcontainers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
govmmQemu "github.com/intel/govmm/qemu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
||||
"github.com/kata-containers/runtime/virtcontainers/persist/fs"
|
||||
"github.com/kata-containers/runtime/virtcontainers/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
qemuArchBaseMachineType = "pc"
|
||||
qemuArchBaseQemuPath = "/usr/bin/qemu-system-x86_64"
|
||||
)
|
||||
|
||||
var qemuArchBaseQemuPaths = map[string]string{
|
||||
qemuArchBaseMachineType: qemuArchBaseQemuPath,
|
||||
}
|
||||
|
||||
var qemuArchBaseKernelParamsNonDebug = []Param{
|
||||
{"quiet", ""},
|
||||
{"systemd.show_status", "false"},
|
||||
}
|
||||
|
||||
var qemuArchBaseKernelParamsDebug = []Param{
|
||||
{"debug", ""},
|
||||
{"systemd.show_status", "true"},
|
||||
{"systemd.log_level", "debug"},
|
||||
}
|
||||
|
||||
var qemuArchBaseKernelParams = []Param{
|
||||
{"root", "/dev/vda"},
|
||||
{"rootfstype", "ext4"},
|
||||
}
|
||||
|
||||
var qemuArchBaseSupportedQemuMachines = []govmmQemu.Machine{
|
||||
{
|
||||
Type: qemuArchBaseMachineType,
|
||||
},
|
||||
}
|
||||
|
||||
func newQemuArchBase() *qemuArchBase {
|
||||
return &qemuArchBase{
|
||||
machineType: qemuArchBaseMachineType,
|
||||
nestedRun: false,
|
||||
qemuPaths: qemuArchBaseQemuPaths,
|
||||
supportedQemuMachines: qemuArchBaseSupportedQemuMachines,
|
||||
kernelParamsNonDebug: qemuArchBaseKernelParamsNonDebug,
|
||||
kernelParamsDebug: qemuArchBaseKernelParamsDebug,
|
||||
kernelParams: qemuArchBaseKernelParams,
|
||||
}
|
||||
}
|
||||
|
||||
func TestQemuArchBaseEnableNestingChecks(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
qemuArchBase.enableNestingChecks()
|
||||
assert.True(qemuArchBase.nestedRun)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseDisableNestingChecks(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
qemuArchBase.disableNestingChecks()
|
||||
assert.False(qemuArchBase.nestedRun)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseMachine(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
m, err := qemuArchBase.machine()
|
||||
assert.NoError(err)
|
||||
assert.Equal(m.Type, qemuArchBaseMachineType)
|
||||
|
||||
machines := []govmmQemu.Machine{
|
||||
{
|
||||
Type: "bad",
|
||||
},
|
||||
}
|
||||
qemuArchBase.supportedQemuMachines = machines
|
||||
m, err = qemuArchBase.machine()
|
||||
assert.Error(err)
|
||||
assert.Equal("", m.Type)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseQemuPath(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
p, err := qemuArchBase.qemuPath()
|
||||
assert.NoError(err)
|
||||
assert.Equal(p, qemuArchBaseQemuPath)
|
||||
|
||||
paths := map[string]string{
|
||||
"bad": qemuArchBaseQemuPath,
|
||||
}
|
||||
qemuArchBase.qemuPaths = paths
|
||||
p, err = qemuArchBase.qemuPath()
|
||||
assert.Error(err)
|
||||
assert.Equal("", p)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseKernelParameters(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
// with debug params
|
||||
expectedParams := qemuArchBaseKernelParams
|
||||
debugParams := qemuArchBaseKernelParamsDebug
|
||||
expectedParams = append(expectedParams, debugParams...)
|
||||
p := qemuArchBase.kernelParameters(true)
|
||||
assert.Equal(expectedParams, p)
|
||||
|
||||
// with non-debug params
|
||||
expectedParams = qemuArchBaseKernelParams
|
||||
nonDebugParams := qemuArchBaseKernelParamsNonDebug
|
||||
expectedParams = append(expectedParams, nonDebugParams...)
|
||||
p = qemuArchBase.kernelParameters(false)
|
||||
assert.Equal(expectedParams, p)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseCapabilities(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
c := qemuArchBase.capabilities()
|
||||
assert.True(c.IsBlockDeviceHotplugSupported())
|
||||
}
|
||||
|
||||
func TestQemuArchBaseBridges(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
len := 5
|
||||
|
||||
qemuArchBase.bridges(uint32(len))
|
||||
bridges := qemuArchBase.getBridges()
|
||||
assert.Len(bridges, len)
|
||||
|
||||
for i, b := range bridges {
|
||||
id := fmt.Sprintf("%s-bridge-%d", types.PCI, i)
|
||||
assert.Equal(types.PCI, b.Type)
|
||||
assert.Equal(id, b.ID)
|
||||
assert.NotNil(b.Devices)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQemuAddDeviceToBridge(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// addDeviceToBridge successfully
|
||||
q := newQemuArchBase()
|
||||
q.machineType = QemuPC
|
||||
|
||||
q.bridges(1)
|
||||
for i := uint32(1); i <= types.PCIBridgeMaxCapacity; i++ {
|
||||
_, _, err := q.addDeviceToBridge(fmt.Sprintf("qemu-bridge-%d", i), types.PCI)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
// fail to add device to bridge cause no more available bridge slot
|
||||
_, _, err := q.addDeviceToBridge("qemu-bridge-31", types.PCI)
|
||||
exceptErr := errors.New("no more bridge slots available")
|
||||
assert.Equal(exceptErr.Error(), err.Error())
|
||||
|
||||
// addDeviceToBridge fails cause q.Bridges == 0
|
||||
q = newQemuArchBase()
|
||||
q.machineType = QemuPCLite
|
||||
q.bridges(0)
|
||||
_, _, err = q.addDeviceToBridge("qemu-bridge", types.PCI)
|
||||
if assert.Error(err) {
|
||||
exceptErr = errors.New("failed to get available address from bridges")
|
||||
assert.Equal(exceptErr.Error(), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestQemuArchBaseCPUTopology(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
vcpus := uint32(2)
|
||||
|
||||
expectedSMP := govmmQemu.SMP{
|
||||
CPUs: vcpus,
|
||||
Sockets: defaultMaxQemuVCPUs,
|
||||
Cores: defaultCores,
|
||||
Threads: defaultThreads,
|
||||
MaxCPUs: defaultMaxQemuVCPUs,
|
||||
}
|
||||
|
||||
smp := qemuArchBase.cpuTopology(vcpus, defaultMaxQemuVCPUs)
|
||||
assert.Equal(expectedSMP, smp)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseCPUModel(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
assert.Equal(defaultCPUModel, qemuArchBase.cpuModel())
|
||||
}
|
||||
|
||||
func TestQemuArchBaseMemoryTopology(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
hostMem := uint64(100)
|
||||
mem := uint64(120)
|
||||
slots := uint8(12)
|
||||
expectedMemory := govmmQemu.Memory{
|
||||
Size: fmt.Sprintf("%dM", mem),
|
||||
Slots: slots,
|
||||
MaxMem: fmt.Sprintf("%dM", hostMem),
|
||||
}
|
||||
|
||||
m := qemuArchBase.memoryTopology(mem, hostMem, slots)
|
||||
assert.Equal(expectedMemory, m)
|
||||
}
|
||||
|
||||
func testQemuArchBaseAppend(t *testing.T, structure interface{}, expected []govmmQemu.Device) {
|
||||
var devices []govmmQemu.Device
|
||||
var err error
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
switch s := structure.(type) {
|
||||
case types.Volume:
|
||||
devices, err = qemuArchBase.append9PVolume(devices, s)
|
||||
case types.Socket:
|
||||
devices = qemuArchBase.appendSocket(devices, s)
|
||||
case config.BlockDrive:
|
||||
devices, err = qemuArchBase.appendBlockDevice(devices, s)
|
||||
case config.VFIODev:
|
||||
devices = qemuArchBase.appendVFIODevice(devices, s)
|
||||
case config.VhostUserDeviceAttrs:
|
||||
devices, err = qemuArchBase.appendVhostUserDevice(devices, s)
|
||||
}
|
||||
|
||||
assert.NoError(err)
|
||||
assert.Equal(devices, expected)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendConsoles(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
var err error
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
path := filepath.Join(filepath.Join(fs.MockRunStoragePath(), sandboxID), consoleSocket)
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.SerialDevice{
|
||||
Driver: govmmQemu.VirtioSerial,
|
||||
ID: "serial0",
|
||||
},
|
||||
govmmQemu.CharDevice{
|
||||
Driver: govmmQemu.Console,
|
||||
Backend: govmmQemu.Socket,
|
||||
DeviceID: "console0",
|
||||
ID: "charconsole0",
|
||||
Path: path,
|
||||
},
|
||||
}
|
||||
|
||||
devices, err = qemuArchBase.appendConsole(devices, path)
|
||||
assert.NoError(err)
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendImage(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
image, err := ioutil.TempFile("", "img")
|
||||
assert.NoError(err)
|
||||
defer os.Remove(image.Name())
|
||||
err = image.Close()
|
||||
assert.NoError(err)
|
||||
|
||||
devices, err = qemuArchBase.appendImage(devices, image.Name())
|
||||
assert.NoError(err)
|
||||
assert.Len(devices, 1)
|
||||
|
||||
drive, ok := devices[0].(govmmQemu.BlockDevice)
|
||||
assert.True(ok)
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.BlockDevice{
|
||||
Driver: govmmQemu.VirtioBlock,
|
||||
ID: drive.ID,
|
||||
File: image.Name(),
|
||||
AIO: govmmQemu.Threads,
|
||||
Format: "raw",
|
||||
Interface: "none",
|
||||
ShareRW: true,
|
||||
ReadOnly: true,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendBridges(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
qemuArchBase.bridges(1)
|
||||
bridges := qemuArchBase.getBridges()
|
||||
assert.Len(bridges, 1)
|
||||
|
||||
devices = qemuArchBase.appendBridges(devices)
|
||||
assert.Len(devices, 1)
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.BridgeDevice{
|
||||
Type: govmmQemu.PCIBridge,
|
||||
Bus: defaultBridgeBus,
|
||||
ID: bridges[0].ID,
|
||||
Chassis: 1,
|
||||
SHPC: true,
|
||||
Addr: "2",
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppend9PVolume(t *testing.T) {
|
||||
mountTag := "testMountTag"
|
||||
hostPath := "testHostPath"
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.FSDevice{
|
||||
Driver: govmmQemu.Virtio9P,
|
||||
FSDriver: govmmQemu.Local,
|
||||
ID: fmt.Sprintf("extra-9p-%s", mountTag),
|
||||
Path: hostPath,
|
||||
MountTag: mountTag,
|
||||
SecurityModel: govmmQemu.None,
|
||||
},
|
||||
}
|
||||
|
||||
volume := types.Volume{
|
||||
MountTag: mountTag,
|
||||
HostPath: hostPath,
|
||||
}
|
||||
|
||||
testQemuArchBaseAppend(t, volume, expectedOut)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendSocket(t *testing.T) {
|
||||
deviceID := "channelTest"
|
||||
id := "charchTest"
|
||||
hostPath := "/tmp/hyper_test.sock"
|
||||
name := "sh.hyper.channel.test"
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.CharDevice{
|
||||
Driver: govmmQemu.VirtioSerialPort,
|
||||
Backend: govmmQemu.Socket,
|
||||
DeviceID: deviceID,
|
||||
ID: id,
|
||||
Path: hostPath,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
|
||||
socket := types.Socket{
|
||||
DeviceID: deviceID,
|
||||
ID: id,
|
||||
HostPath: hostPath,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
testQemuArchBaseAppend(t, socket, expectedOut)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendBlockDevice(t *testing.T) {
|
||||
id := "blockDevTest"
|
||||
file := "/root"
|
||||
format := "raw"
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.BlockDevice{
|
||||
Driver: govmmQemu.VirtioBlock,
|
||||
ID: id,
|
||||
File: "/root",
|
||||
AIO: govmmQemu.Threads,
|
||||
Format: govmmQemu.BlockDeviceFormat(format),
|
||||
Interface: "none",
|
||||
},
|
||||
}
|
||||
|
||||
drive := config.BlockDrive{
|
||||
File: file,
|
||||
Format: format,
|
||||
ID: id,
|
||||
}
|
||||
|
||||
testQemuArchBaseAppend(t, drive, expectedOut)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendVhostUserDevice(t *testing.T) {
|
||||
socketPath := "nonexistentpath.sock"
|
||||
macAddress := "00:11:22:33:44:55:66"
|
||||
id := "deadbeef"
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.VhostUserDevice{
|
||||
SocketPath: socketPath,
|
||||
CharDevID: fmt.Sprintf("char-%s", id),
|
||||
TypeDevID: fmt.Sprintf("net-%s", id),
|
||||
Address: macAddress,
|
||||
VhostUserType: govmmQemu.VhostUserNet,
|
||||
},
|
||||
}
|
||||
|
||||
vhostUserDevice := config.VhostUserDeviceAttrs{
|
||||
Type: config.VhostUserNet,
|
||||
MacAddress: macAddress,
|
||||
}
|
||||
vhostUserDevice.DevID = id
|
||||
vhostUserDevice.SocketPath = socketPath
|
||||
|
||||
testQemuArchBaseAppend(t, vhostUserDevice, expectedOut)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendVFIODevice(t *testing.T) {
|
||||
bdf := "02:10.1"
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.VFIODevice{
|
||||
BDF: bdf,
|
||||
},
|
||||
}
|
||||
|
||||
vfDevice := config.VFIODev{
|
||||
BDF: bdf,
|
||||
}
|
||||
|
||||
testQemuArchBaseAppend(t, vfDevice, expectedOut)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendVFIODeviceWithVendorDeviceID(t *testing.T) {
|
||||
bdf := "02:10.1"
|
||||
vendorID := "0x1234"
|
||||
deviceID := "0x5678"
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.VFIODevice{
|
||||
BDF: bdf,
|
||||
VendorID: vendorID,
|
||||
DeviceID: deviceID,
|
||||
},
|
||||
}
|
||||
|
||||
vfDevice := config.VFIODev{
|
||||
BDF: bdf,
|
||||
VendorID: vendorID,
|
||||
DeviceID: deviceID,
|
||||
}
|
||||
|
||||
testQemuArchBaseAppend(t, vfDevice, expectedOut)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendSCSIController(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.SCSIController{
|
||||
ID: scsiControllerID,
|
||||
},
|
||||
}
|
||||
|
||||
devices, ioThread, err := qemuArchBase.appendSCSIController(devices, false)
|
||||
assert.Equal(expectedOut, devices)
|
||||
assert.Nil(ioThread)
|
||||
assert.NoError(err)
|
||||
|
||||
_, ioThread, err = qemuArchBase.appendSCSIController(devices, true)
|
||||
assert.NotNil(ioThread)
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
func TestQemuArchBaseAppendNetwork(t *testing.T) {
|
||||
var devices []govmmQemu.Device
|
||||
var err error
|
||||
assert := assert.New(t)
|
||||
qemuArchBase := newQemuArchBase()
|
||||
|
||||
macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x04}
|
||||
|
||||
macvlanEp := &BridgedMacvlanEndpoint{
|
||||
NetPair: NetworkInterfacePair{
|
||||
TapInterface: TapInterface{
|
||||
ID: "uniqueTestID-4",
|
||||
Name: "br4_kata",
|
||||
TAPIface: NetworkInterface{
|
||||
Name: "tap4_kata",
|
||||
},
|
||||
},
|
||||
VirtIface: NetworkInterface{
|
||||
Name: "eth4",
|
||||
HardAddr: macAddr.String(),
|
||||
},
|
||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||
},
|
||||
EndpointType: BridgedMacvlanEndpointType,
|
||||
}
|
||||
|
||||
macvtapEp := &MacvtapEndpoint{
|
||||
EndpointType: MacvtapEndpointType,
|
||||
EndpointProperties: NetworkInfo{
|
||||
Iface: NetlinkIface{
|
||||
Type: "macvtap",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedOut := []govmmQemu.Device{
|
||||
govmmQemu.NetDevice{
|
||||
Type: networkModelToQemuType(macvlanEp.NetPair.NetInterworkingModel),
|
||||
Driver: govmmQemu.VirtioNet,
|
||||
ID: fmt.Sprintf("network-%d", 0),
|
||||
IFName: macvlanEp.NetPair.TAPIface.Name,
|
||||
MACAddress: macvlanEp.NetPair.TAPIface.HardAddr,
|
||||
DownScript: "no",
|
||||
Script: "no",
|
||||
FDs: macvlanEp.NetPair.VMFds,
|
||||
VhostFDs: macvlanEp.NetPair.VhostFds,
|
||||
},
|
||||
govmmQemu.NetDevice{
|
||||
Type: govmmQemu.MACVTAP,
|
||||
Driver: govmmQemu.VirtioNet,
|
||||
ID: fmt.Sprintf("network-%d", 1),
|
||||
IFName: macvtapEp.Name(),
|
||||
MACAddress: macvtapEp.HardwareAddr(),
|
||||
DownScript: "no",
|
||||
Script: "no",
|
||||
FDs: macvtapEp.VMFds,
|
||||
VhostFDs: macvtapEp.VhostFds,
|
||||
},
|
||||
}
|
||||
|
||||
devices, err = qemuArchBase.appendNetwork(devices, macvlanEp)
|
||||
assert.NoError(err)
|
||||
devices, err = qemuArchBase.appendNetwork(devices, macvtapEp)
|
||||
assert.NoError(err)
|
||||
assert.Equal(expectedOut, devices)
|
||||
}
|
||||
Reference in New Issue
Block a user