mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-26 07:22:20 +00:00
clh: test: add unit test
Add unit test for clh. - Check endpoint has valid values for CH. - Add unit tests - Add force flag to ignore cleanup errors. - Add unit tests. - Fail if hypervisor ID is empty. - Add createSandbox uni test Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
This commit is contained in:
parent
8a439eab9d
commit
6a10cd960d
@ -446,7 +446,9 @@ func (clh *cloudHypervisor) addDevice(devInfo interface{}, devType deviceType) e
|
|||||||
|
|
||||||
switch v := devInfo.(type) {
|
switch v := devInfo.(type) {
|
||||||
case Endpoint:
|
case Endpoint:
|
||||||
clh.addNet(v)
|
if err := clh.addNet(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case types.HybridVSock:
|
case types.HybridVSock:
|
||||||
clh.addVSock(defaultGuestVSockCID, v.UdsPath)
|
clh.addVSock(defaultGuestVSockCID, v.UdsPath)
|
||||||
case types.Volume:
|
case types.Volume:
|
||||||
@ -522,7 +524,7 @@ func (clh *cloudHypervisor) terminate() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clh.cleanupVM()
|
_ = clh.cleanupVM(true)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pid := clh.state.PID
|
pid := clh.state.PID
|
||||||
@ -1049,16 +1051,29 @@ func (clh *cloudHypervisor) addVSock(cid int64, path string) {
|
|||||||
clh.vmconfig.Vsock = append(clh.vmconfig.Vsock, chclient.VsockConfig{Cid: cid, Sock: path})
|
clh.vmconfig.Vsock = append(clh.vmconfig.Vsock, chclient.VsockConfig{Cid: cid, Sock: path})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clh *cloudHypervisor) addNet(e Endpoint) {
|
func (clh *cloudHypervisor) addNet(e Endpoint) error {
|
||||||
clh.Logger().WithField("endpoint-type", e).Debugf("Adding Endpoint of type %v", e)
|
clh.Logger().WithField("endpoint-type", e).Debugf("Adding Endpoint of type %v", e)
|
||||||
|
|
||||||
mac := e.HardwareAddr()
|
mac := e.HardwareAddr()
|
||||||
tapPath := e.NetworkPair().TapInterface.TAPIface.Name
|
netPair := e.NetworkPair()
|
||||||
|
|
||||||
|
if netPair == nil {
|
||||||
|
return errors.New("net Pair to be added is nil, needed to get TAP path")
|
||||||
|
}
|
||||||
|
|
||||||
|
tapPath := netPair.TapInterface.TAPIface.Name
|
||||||
|
|
||||||
|
if tapPath == "" {
|
||||||
|
return errors.New("TAP path in network pair is empty")
|
||||||
|
}
|
||||||
|
|
||||||
clh.Logger().WithFields(log.Fields{
|
clh.Logger().WithFields(log.Fields{
|
||||||
"mac": mac,
|
"mac": mac,
|
||||||
"tap": tapPath,
|
"tap": tapPath,
|
||||||
}).Info("Adding Net")
|
}).Info("Adding Net")
|
||||||
|
|
||||||
clh.vmconfig.Net = append(clh.vmconfig.Net, chclient.NetConfig{Mac: mac, Tap: tapPath})
|
clh.vmconfig.Net = append(clh.vmconfig.Net, chclient.NetConfig{Mac: mac, Tap: tapPath})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add shared Volume using virtiofs
|
// Add shared Volume using virtiofs
|
||||||
@ -1095,25 +1110,37 @@ func (clh *cloudHypervisor) addVolume(volume types.Volume) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanupVM will remove generated files and directories related with the virtual machine
|
// cleanupVM will remove generated files and directories related with the virtual machine
|
||||||
func (clh *cloudHypervisor) cleanupVM() error {
|
func (clh *cloudHypervisor) cleanupVM(force bool) error {
|
||||||
|
|
||||||
|
if clh.id == "" {
|
||||||
|
return errors.New("Hypervisor ID is empty")
|
||||||
|
}
|
||||||
|
|
||||||
// cleanup vm path
|
// cleanup vm path
|
||||||
dir := filepath.Join(store.RunVMStoragePath(), clh.id)
|
dir := filepath.Join(store.RunVMStoragePath(), clh.id)
|
||||||
|
|
||||||
// If it's a symlink, remove both dir and the target.
|
// If it's a symlink, remove both dir and the target.
|
||||||
// This can happen when vm template links a sandbox to a vm.
|
|
||||||
link, err := filepath.EvalSymlinks(dir)
|
link, err := filepath.EvalSymlinks(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Well, it's just cleanup failure. Let's ignore it.
|
|
||||||
clh.Logger().WithError(err).WithField("dir", dir).Warn("failed to resolve vm path")
|
clh.Logger().WithError(err).WithField("dir", dir).Warn("failed to resolve vm path")
|
||||||
}
|
}
|
||||||
clh.Logger().WithField("link", link).WithField("dir", dir).Infof("cleanup vm path")
|
|
||||||
|
clh.Logger().WithFields(log.Fields{
|
||||||
|
"link": link,
|
||||||
|
"dir": dir,
|
||||||
|
}).Infof("cleanup vm path")
|
||||||
|
|
||||||
if err := os.RemoveAll(dir); err != nil {
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
if !force {
|
||||||
|
return err
|
||||||
|
}
|
||||||
clh.Logger().WithError(err).Warnf("failed to remove vm path %s", dir)
|
clh.Logger().WithError(err).Warnf("failed to remove vm path %s", dir)
|
||||||
}
|
}
|
||||||
if link != dir && link != "" {
|
if link != dir && link != "" {
|
||||||
if err := os.RemoveAll(link); err != nil {
|
if err := os.RemoveAll(link); err != nil {
|
||||||
|
if !force {
|
||||||
|
return err
|
||||||
|
}
|
||||||
clh.Logger().WithError(err).WithField("link", link).Warn("failed to remove resolved vm path")
|
clh.Logger().WithError(err).WithField("link", link).Warn("failed to remove resolved vm path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1121,10 +1148,16 @@ func (clh *cloudHypervisor) cleanupVM() error {
|
|||||||
if clh.config.VMid != "" {
|
if clh.config.VMid != "" {
|
||||||
dir = store.SandboxConfigurationRootPath(clh.config.VMid)
|
dir = store.SandboxConfigurationRootPath(clh.config.VMid)
|
||||||
if err := os.RemoveAll(dir); err != nil {
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
if !force {
|
||||||
|
return err
|
||||||
|
}
|
||||||
clh.Logger().WithError(err).WithField("path", dir).Warnf("failed to remove vm path")
|
clh.Logger().WithError(err).WithField("path", dir).Warnf("failed to remove vm path")
|
||||||
}
|
}
|
||||||
dir = store.SandboxRuntimeRootPath(clh.config.VMid)
|
dir = store.SandboxRuntimeRootPath(clh.config.VMid)
|
||||||
if err := os.RemoveAll(dir); err != nil {
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
if !force {
|
||||||
|
return err
|
||||||
|
}
|
||||||
clh.Logger().WithError(err).WithField("path", dir).Warnf("failed to remove vm path")
|
clh.Logger().WithError(err).WithField("path", dir).Warnf("failed to remove vm path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,52 @@ package virtcontainers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
||||||
chclient "github.com/kata-containers/runtime/virtcontainers/pkg/cloud-hypervisor/client"
|
chclient "github.com/kata-containers/runtime/virtcontainers/pkg/cloud-hypervisor/client"
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/store"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func newClhConfig() (HypervisorConfig, error) {
|
||||||
|
|
||||||
|
setupClh()
|
||||||
|
|
||||||
|
if testClhPath == "" {
|
||||||
|
return HypervisorConfig{}, errors.New("hypervisor fake path is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if testVirtiofsdPath == "" {
|
||||||
|
return HypervisorConfig{}, errors.New("hypervisor fake path is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(testClhPath); os.IsNotExist(err) {
|
||||||
|
return HypervisorConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(testVirtiofsdPath); os.IsNotExist(err) {
|
||||||
|
return HypervisorConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return HypervisorConfig{
|
||||||
|
KernelPath: testClhKernelPath,
|
||||||
|
ImagePath: testClhImagePath,
|
||||||
|
HypervisorPath: testClhPath,
|
||||||
|
NumVCPUs: defaultVCPUs,
|
||||||
|
BlockDeviceDriver: config.VirtioBlock,
|
||||||
|
MemorySize: defaultMemSzMiB,
|
||||||
|
DefaultBridges: defaultBridges,
|
||||||
|
DefaultMaxVCPUs: MaxClhVCPUs(),
|
||||||
|
SharedFS: config.VirtioFS,
|
||||||
|
VirtioFSCache: virtioFsCacheAlways,
|
||||||
|
VirtioFSDaemon: testVirtiofsdPath,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type clhClientMock struct {
|
type clhClientMock struct {
|
||||||
vmInfo chclient.VmInfo
|
vmInfo chclient.VmInfo
|
||||||
}
|
}
|
||||||
@ -54,6 +94,74 @@ func TestCloudHypervisorAddVSock(t *testing.T) {
|
|||||||
assert.Equal(clh.vmconfig.Vsock[1].Sock, "path2")
|
assert.Equal(clh.vmconfig.Vsock[1].Sock, "path2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check addNet appends to the network config list new configurations.
|
||||||
|
// Check that the elements in the list has the correct values
|
||||||
|
func TestCloudHypervisorAddNetCheckNetConfigListValues(t *testing.T) {
|
||||||
|
macTest := "00:00:00:00:00"
|
||||||
|
tapPath := "/path/to/tap"
|
||||||
|
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
clh := cloudHypervisor{}
|
||||||
|
|
||||||
|
e := &VethEndpoint{}
|
||||||
|
e.NetPair.TAPIface.HardAddr = macTest
|
||||||
|
e.NetPair.TapInterface.TAPIface.Name = tapPath
|
||||||
|
|
||||||
|
err := clh.addNet(e)
|
||||||
|
assert.Nil(err)
|
||||||
|
|
||||||
|
assert.Equal(len(clh.vmconfig.Net), 1)
|
||||||
|
if err == nil {
|
||||||
|
assert.Equal(clh.vmconfig.Net[0].Mac, macTest)
|
||||||
|
assert.Equal(clh.vmconfig.Net[0].Tap, tapPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clh.addNet(e)
|
||||||
|
assert.Nil(err)
|
||||||
|
|
||||||
|
assert.Equal(len(clh.vmconfig.Net), 2)
|
||||||
|
if err == nil {
|
||||||
|
assert.Equal(clh.vmconfig.Net[1].Mac, macTest)
|
||||||
|
assert.Equal(clh.vmconfig.Net[1].Tap, tapPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check addNet with valid values, and fail with invalid values
|
||||||
|
// For Cloud Hypervisor only tap is be required
|
||||||
|
func TestCloudHypervisorAddNetCheckEnpointTypes(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
tapPath := "/path/to/tap"
|
||||||
|
|
||||||
|
validVeth := &VethEndpoint{}
|
||||||
|
validVeth.NetPair.TapInterface.TAPIface.Name = tapPath
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
e Endpoint
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"TapEndpoint", args{e: &TapEndpoint{}}, true},
|
||||||
|
{"Empty VethEndpoint", args{e: &VethEndpoint{}}, true},
|
||||||
|
{"Valid VethEndpoint", args{e: validVeth}, false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
clh := &cloudHypervisor{}
|
||||||
|
if err := clh.addNet(tt.args.e); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("cloudHypervisor.addNet() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
|
||||||
|
} else if err == nil {
|
||||||
|
assert.Equal(clh.vmconfig.Net[0].Tap, tapPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCloudHypervisorBootVM(t *testing.T) {
|
func TestCloudHypervisorBootVM(t *testing.T) {
|
||||||
clh := &cloudHypervisor{}
|
clh := &cloudHypervisor{}
|
||||||
clh.APIClient = &clhClientMock{}
|
clh.APIClient = &clhClientMock{}
|
||||||
@ -62,3 +170,66 @@ func TestCloudHypervisorBootVM(t *testing.T) {
|
|||||||
t.Errorf("cloudHypervisor.bootVM() error = %v", err)
|
t.Errorf("cloudHypervisor.bootVM() error = %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCloudHypervisorCleanupVM(t *testing.T) {
|
||||||
|
clh := &cloudHypervisor{}
|
||||||
|
|
||||||
|
if err := clh.cleanupVM(true); err == nil {
|
||||||
|
t.Errorf("cloudHypervisor.cleanupVM() expected error != %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clh.id = "cleanVMID"
|
||||||
|
|
||||||
|
if err := clh.cleanupVM(true); err != nil {
|
||||||
|
t.Errorf("cloudHypervisor.cleanupVM() expected error != %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := filepath.Join(store.RunVMStoragePath(), clh.id)
|
||||||
|
os.MkdirAll(dir, os.ModePerm)
|
||||||
|
|
||||||
|
if err := clh.cleanupVM(false); err != nil {
|
||||||
|
t.Errorf("cloudHypervisor.cleanupVM() expected error != %v", err)
|
||||||
|
}
|
||||||
|
_, err := os.Stat(dir)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("dir should not exist %s", dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
t.Errorf("Unexpected error = %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClhCreateSandbox(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
clhConfig, err := newClhConfig()
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
clh := &cloudHypervisor{
|
||||||
|
config: clhConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
sandbox := &Sandbox{
|
||||||
|
ctx: context.Background(),
|
||||||
|
id: "testSandbox",
|
||||||
|
config: &SandboxConfig{
|
||||||
|
HypervisorConfig: clhConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vcStore, err := store.NewVCSandboxStore(sandbox.ctx, sandbox.id)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
sandbox.store = vcStore
|
||||||
|
|
||||||
|
// Create parent dir path for hypervisor.json
|
||||||
|
parentDir := store.SandboxConfigurationRootPath(sandbox.id)
|
||||||
|
assert.NoError(os.MkdirAll(parentDir, store.DirMode))
|
||||||
|
|
||||||
|
err = clh.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store, false)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.NoError(os.RemoveAll(parentDir))
|
||||||
|
assert.Exactly(clhConfig, clh.config)
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@ const testKernel = "kernel"
|
|||||||
const testInitrd = "initrd"
|
const testInitrd = "initrd"
|
||||||
const testImage = "image"
|
const testImage = "image"
|
||||||
const testHypervisor = "hypervisor"
|
const testHypervisor = "hypervisor"
|
||||||
|
const testVirtiofsd = "virtiofsd"
|
||||||
const testHypervisorCtl = "hypervisorctl"
|
const testHypervisorCtl = "hypervisorctl"
|
||||||
const testBundle = "bundle"
|
const testBundle = "bundle"
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ var testAcrnKernelPath = ""
|
|||||||
var testAcrnImagePath = ""
|
var testAcrnImagePath = ""
|
||||||
var testAcrnPath = ""
|
var testAcrnPath = ""
|
||||||
var testAcrnCtlPath = ""
|
var testAcrnCtlPath = ""
|
||||||
|
var testVirtiofsdPath = ""
|
||||||
|
|
||||||
var testHyperstartCtlSocket = ""
|
var testHyperstartCtlSocket = ""
|
||||||
var testHyperstartTtySocket = ""
|
var testHyperstartTtySocket = ""
|
||||||
@ -91,7 +93,7 @@ func setupAcrn() {
|
|||||||
func setupClh() {
|
func setupClh() {
|
||||||
os.Mkdir(filepath.Join(testDir, testBundle), store.DirMode)
|
os.Mkdir(filepath.Join(testDir, testBundle), store.DirMode)
|
||||||
|
|
||||||
for _, filename := range []string{testClhKernelPath, testClhImagePath, testClhPath} {
|
for _, filename := range []string{testClhKernelPath, testClhImagePath, testClhPath, testVirtiofsdPath} {
|
||||||
_, err := os.Create(filename)
|
_, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Could not recreate %s:%v", filename, err)
|
fmt.Printf("Could not recreate %s:%v", filename, err)
|
||||||
@ -142,9 +144,10 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
setupAcrn()
|
setupAcrn()
|
||||||
|
|
||||||
testClhKernelPath = filepath.Join(testDir, testKernel)
|
testVirtiofsdPath = filepath.Join(testDir, testBundle, testVirtiofsd)
|
||||||
testClhImagePath = filepath.Join(testDir, testImage)
|
testClhKernelPath = filepath.Join(testDir, testBundle, testKernel)
|
||||||
testClhPath = filepath.Join(testDir, testHypervisor)
|
testClhImagePath = filepath.Join(testDir, testBundle, testImage)
|
||||||
|
testClhPath = filepath.Join(testDir, testBundle, testHypervisor)
|
||||||
|
|
||||||
setupClh()
|
setupClh()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user