mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-01 17:52:40 +00:00
agent: prepare for vm factory
There are a few changes we need on kata agent to introduce vm factory support: 1. decouple agent creation from sandbox config 2. setup agent without creating a sandbox 3. expose vm storage path and share mount point Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
parent
7f20dd89a3
commit
057214f0fe
@ -96,20 +96,20 @@ func newAgent(agentType AgentType) agent {
|
||||
}
|
||||
|
||||
// newAgentConfig returns an agent config from a generic SandboxConfig interface.
|
||||
func newAgentConfig(config SandboxConfig) interface{} {
|
||||
switch config.AgentType {
|
||||
func newAgentConfig(agentType AgentType, agentConfig interface{}) interface{} {
|
||||
switch agentType {
|
||||
case NoopAgentType:
|
||||
return nil
|
||||
case HyperstartAgent:
|
||||
var hyperConfig HyperConfig
|
||||
err := mapstructure.Decode(config.AgentConfig, &hyperConfig)
|
||||
err := mapstructure.Decode(agentConfig, &hyperConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return hyperConfig
|
||||
case KataContainersAgent:
|
||||
var kataAgentConfig KataAgentConfig
|
||||
err := mapstructure.Decode(config.AgentConfig, &kataAgentConfig)
|
||||
err := mapstructure.Decode(agentConfig, &kataAgentConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -209,4 +209,13 @@ type agent interface {
|
||||
|
||||
// resumeContainer will resume a paused container
|
||||
resumeContainer(sandbox *Sandbox, c Container) error
|
||||
|
||||
// configure will update agent settings based on provided arguments
|
||||
configure(h hypervisor, id, sharePath string, builtin bool, config interface{}) error
|
||||
|
||||
// getVMPath will return the agent vm socket's directory path
|
||||
getVMPath(id string) string
|
||||
|
||||
// getSharePath will return the agent 9pfs share mount path
|
||||
getSharePath(id string) string
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ func TestNewAgentFromUnknownAgentType(t *testing.T) {
|
||||
}
|
||||
|
||||
func testNewAgentConfig(t *testing.T, config SandboxConfig, expected interface{}) {
|
||||
agentConfig := newAgentConfig(config)
|
||||
agentConfig := newAgentConfig(config.AgentType, config.AgentConfig)
|
||||
if reflect.DeepEqual(agentConfig, expected) == false {
|
||||
t.Fatal()
|
||||
}
|
||||
|
@ -85,17 +85,27 @@ const dirMode = os.FileMode(0750) | os.ModeDir
|
||||
|
||||
// storagePathSuffix is the suffix used for all storage paths
|
||||
//
|
||||
// Note: this very brief path represents "virtcontainers sandboxes". It is as
|
||||
// Note: this very brief path represents "virtcontainers". It is as
|
||||
// terse as possible to minimise path length.
|
||||
const storagePathSuffix = "/vc/sbs"
|
||||
const storagePathSuffix = "vc"
|
||||
|
||||
// sandboxPathSuffix is the suffix used for sandbox storage
|
||||
const sandboxPathSuffix = "sbs"
|
||||
|
||||
// vmPathSuffix is the suffix used for guest VMs.
|
||||
const vmPathSuffix = "vm"
|
||||
|
||||
// configStoragePath is the sandbox configuration directory.
|
||||
// It will contain one config.json file for each created sandbox.
|
||||
var configStoragePath = filepath.Join("/var/lib", storagePathSuffix)
|
||||
var configStoragePath = filepath.Join("/var/lib", storagePathSuffix, sandboxPathSuffix)
|
||||
|
||||
// runStoragePath is the sandbox runtime directory.
|
||||
// It will contain one state.json and one lock file for each created sandbox.
|
||||
var runStoragePath = filepath.Join("/run", storagePathSuffix)
|
||||
var runStoragePath = filepath.Join("/run", storagePathSuffix, sandboxPathSuffix)
|
||||
|
||||
// RunVMStoragePath is the vm directory.
|
||||
// It will contain all guest vm sockets and shared mountpoints.
|
||||
var RunVMStoragePath = filepath.Join("/run", storagePathSuffix, vmPathSuffix)
|
||||
|
||||
// resourceStorage is the virtcontainers resources (configuration, state, etc...)
|
||||
// storage interface.
|
||||
|
@ -262,9 +262,17 @@ func (h *hyper) init(sandbox *Sandbox, config interface{}) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *hyper) createSandbox(sandbox *Sandbox) (err error) {
|
||||
func (h *hyper) getVMPath(id string) string {
|
||||
return filepath.Join(runStoragePath, id)
|
||||
}
|
||||
|
||||
func (h *hyper) getSharePath(id string) string {
|
||||
return filepath.Join(defaultSharedDir, id)
|
||||
}
|
||||
|
||||
func (h *hyper) configure(hv hypervisor, id, sharePath string, builtin bool, config interface{}) error {
|
||||
for _, socket := range h.sockets {
|
||||
err := sandbox.hypervisor.addDevice(socket, serialPortDev)
|
||||
err := hv.addDevice(socket, serialPortDev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -274,14 +282,18 @@ func (h *hyper) createSandbox(sandbox *Sandbox) (err error) {
|
||||
// This volume contains all bind mounted container bundles.
|
||||
sharedVolume := Volume{
|
||||
MountTag: mountTag,
|
||||
HostPath: filepath.Join(defaultSharedDir, sandbox.id),
|
||||
HostPath: sharePath,
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(sharedVolume.HostPath, dirMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sandbox.hypervisor.addDevice(sharedVolume, fsDev)
|
||||
return hv.addDevice(sharedVolume, fsDev)
|
||||
}
|
||||
|
||||
func (h *hyper) createSandbox(sandbox *Sandbox) (err error) {
|
||||
return h.configure(sandbox.hypervisor, "", h.getSharePath(sandbox.id), false, nil)
|
||||
}
|
||||
|
||||
func (h *hyper) capabilities() capabilities {
|
||||
|
@ -7,11 +7,13 @@ package virtcontainers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/hyperstart"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
@ -156,3 +158,43 @@ func TestProcessHyperRouteDestIPv6Failure(t *testing.T) {
|
||||
|
||||
testProcessHyperRoute(t, route, testRouteDeviceName, nil)
|
||||
}
|
||||
|
||||
func TestHyperPathAPI(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
h1 := &hyper{}
|
||||
h2 := &hyper{}
|
||||
id := "foobar"
|
||||
|
||||
// getVMPath
|
||||
path1 := h1.getVMPath(id)
|
||||
path2 := h2.getVMPath(id)
|
||||
assert.Equal(path1, path2)
|
||||
|
||||
// getSharePath
|
||||
path1 = h1.getSharePath(id)
|
||||
path2 = h2.getSharePath(id)
|
||||
assert.Equal(path1, path2)
|
||||
}
|
||||
|
||||
func TestHyperConfigure(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "hyperstart-test")
|
||||
assert.Nil(err)
|
||||
|
||||
h := &hyper{}
|
||||
m := &mockHypervisor{}
|
||||
c := HyperConfig{}
|
||||
id := "foobar"
|
||||
|
||||
invalidAgent := KataAgentConfig{}
|
||||
err = h.configure(m, id, dir, true, invalidAgent)
|
||||
assert.Nil(err)
|
||||
|
||||
err = h.configure(m, id, dir, true, c)
|
||||
assert.Nil(err)
|
||||
|
||||
err = h.configure(m, id, dir, false, c)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
@ -119,11 +119,19 @@ func parseVSOCKAddr(sock string) (uint32, uint32, error) {
|
||||
return uint32(cid), uint32(port), nil
|
||||
}
|
||||
|
||||
func (k *kataAgent) generateVMSocket(sandbox *Sandbox, c KataAgentConfig) error {
|
||||
func (k *kataAgent) getVMPath(id string) string {
|
||||
return filepath.Join(RunVMStoragePath, id)
|
||||
}
|
||||
|
||||
func (k *kataAgent) getSharePath(id string) string {
|
||||
return filepath.Join(kataHostSharedDir, id)
|
||||
}
|
||||
|
||||
func (k *kataAgent) generateVMSocket(id string, c KataAgentConfig) error {
|
||||
cid, port, err := parseVSOCKAddr(c.GRPCSocket)
|
||||
if err != nil {
|
||||
// We need to generate a host UNIX socket path for the emulated serial port.
|
||||
kataSock, err := utils.BuildSocketPath(runStoragePath, sandbox.id, defaultKataSocketName)
|
||||
kataSock, err := utils.BuildSocketPath(k.getVMPath(id), defaultKataSocketName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -148,7 +156,7 @@ func (k *kataAgent) generateVMSocket(sandbox *Sandbox, c KataAgentConfig) error
|
||||
func (k *kataAgent) init(sandbox *Sandbox, config interface{}) (err error) {
|
||||
switch c := config.(type) {
|
||||
case KataAgentConfig:
|
||||
if err := k.generateVMSocket(sandbox, c); err != nil {
|
||||
if err := k.generateVMSocket(sandbox.id, c); err != nil {
|
||||
return err
|
||||
}
|
||||
k.keepConn = c.LongLiveConn
|
||||
@ -196,10 +204,22 @@ func (k *kataAgent) capabilities() capabilities {
|
||||
return caps
|
||||
}
|
||||
|
||||
func (k *kataAgent) createSandbox(sandbox *Sandbox) error {
|
||||
func (k *kataAgent) configure(h hypervisor, id, sharePath string, builtin bool, config interface{}) error {
|
||||
if config != nil {
|
||||
switch c := config.(type) {
|
||||
case KataAgentConfig:
|
||||
if err := k.generateVMSocket(id, c); err != nil {
|
||||
return err
|
||||
}
|
||||
k.keepConn = c.LongLiveConn
|
||||
default:
|
||||
return fmt.Errorf("Invalid config type")
|
||||
}
|
||||
}
|
||||
|
||||
switch s := k.vmSocket.(type) {
|
||||
case Socket:
|
||||
err := sandbox.hypervisor.addDevice(s, serialPortDev)
|
||||
err := h.addDevice(s, serialPortDev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -209,18 +229,27 @@ func (k *kataAgent) createSandbox(sandbox *Sandbox) error {
|
||||
return fmt.Errorf("Invalid config type")
|
||||
}
|
||||
|
||||
if builtin {
|
||||
k.proxyBuiltIn = true
|
||||
k.state.URL, _ = k.agentURL()
|
||||
}
|
||||
|
||||
// Adding the shared volume.
|
||||
// This volume contains all bind mounted container bundles.
|
||||
sharedVolume := Volume{
|
||||
MountTag: mountGuest9pTag,
|
||||
HostPath: filepath.Join(kataHostSharedDir, sandbox.id),
|
||||
HostPath: sharePath,
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(sharedVolume.HostPath, dirMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sandbox.hypervisor.addDevice(sharedVolume, fsDev)
|
||||
return h.addDevice(sharedVolume, fsDev)
|
||||
}
|
||||
|
||||
func (k *kataAgent) createSandbox(sandbox *Sandbox) error {
|
||||
return k.configure(sandbox.hypervisor, sandbox.id, k.getSharePath(sandbox.id), k.proxyBuiltIn, nil)
|
||||
}
|
||||
|
||||
func cmdToKataProcess(cmd Cmd) (process *grpc.Process, err error) {
|
||||
@ -719,35 +748,15 @@ func (k *kataAgent) rollbackFailingContainerCreation(c *Container) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process, err error) {
|
||||
ociSpecJSON, ok := c.config.Annotations[vcAnnotations.ConfigJSONKey]
|
||||
if !ok {
|
||||
return nil, errorMissingOCISpec
|
||||
}
|
||||
|
||||
var ctrStorages []*grpc.Storage
|
||||
var ctrDevices []*grpc.Device
|
||||
|
||||
// The rootfs storage volume represents the container rootfs
|
||||
// mount point inside the guest.
|
||||
// It can be a block based device (when using block based container
|
||||
// overlay on the host) mount or a 9pfs one (for all other overlay
|
||||
// implementations).
|
||||
rootfs := &grpc.Storage{}
|
||||
|
||||
// This is the guest absolute root path for that container.
|
||||
rootPathParent := filepath.Join(kataGuestSharedDir, c.id)
|
||||
rootPath := filepath.Join(rootPathParent, rootfsDir)
|
||||
|
||||
// In case the container creation fails, the following defer statement
|
||||
// takes care of rolling back actions previously performed.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
k.rollbackFailingContainerCreation(c)
|
||||
}
|
||||
}()
|
||||
|
||||
func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPathParent string) (*grpc.Storage, error) {
|
||||
if c.state.Fstype != "" {
|
||||
// The rootfs storage volume represents the container rootfs
|
||||
// mount point inside the guest.
|
||||
// It can be a block based device (when using block based container
|
||||
// overlay on the host) mount or a 9pfs one (for all other overlay
|
||||
// implementations).
|
||||
rootfs := &grpc.Storage{}
|
||||
|
||||
// This is a block based device rootfs.
|
||||
|
||||
// Pass a drive name only in case of virtio-blk driver.
|
||||
@ -773,24 +782,53 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
||||
rootfs.Options = []string{"nouuid"}
|
||||
}
|
||||
|
||||
return rootfs, nil
|
||||
}
|
||||
// This is not a block based device rootfs.
|
||||
// We are going to bind mount it into the 9pfs
|
||||
// shared drive between the host and the guest.
|
||||
// With 9pfs we don't need to ask the agent to
|
||||
// mount the rootfs as the shared directory
|
||||
// (kataGuestSharedDir) is already mounted in the
|
||||
// guest. We only need to mount the rootfs from
|
||||
// the host and it will show up in the guest.
|
||||
if err := bindMountContainerRootfs(kataHostSharedDir, sandbox.id, c.id, c.rootFs, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process, err error) {
|
||||
ociSpecJSON, ok := c.config.Annotations[vcAnnotations.ConfigJSONKey]
|
||||
if !ok {
|
||||
return nil, errorMissingOCISpec
|
||||
}
|
||||
|
||||
var ctrStorages []*grpc.Storage
|
||||
var ctrDevices []*grpc.Device
|
||||
var rootfs *grpc.Storage
|
||||
|
||||
// This is the guest absolute root path for that container.
|
||||
rootPathParent := filepath.Join(kataGuestSharedDir, c.id)
|
||||
rootPath := filepath.Join(rootPathParent, rootfsDir)
|
||||
|
||||
// In case the container creation fails, the following defer statement
|
||||
// takes care of rolling back actions previously performed.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
k.rollbackFailingContainerCreation(c)
|
||||
}
|
||||
}()
|
||||
|
||||
if rootfs, err = k.buildContainerRootfs(sandbox, c, rootPathParent); err != nil {
|
||||
return nil, err
|
||||
} else if rootfs != nil {
|
||||
// Add rootfs to the list of container storage.
|
||||
// We only need to do this for block based rootfs, as we
|
||||
// want the agent to mount it into the right location
|
||||
// (kataGuestSharedDir/ctrID/
|
||||
ctrStorages = append(ctrStorages, rootfs)
|
||||
|
||||
} else {
|
||||
// This is not a block based device rootfs.
|
||||
// We are going to bind mount it into the 9pfs
|
||||
// shared drive between the host and the guest.
|
||||
// With 9pfs we don't need to ask the agent to
|
||||
// mount the rootfs as the shared directory
|
||||
// (kataGuestSharedDir) is already mounted in the
|
||||
// guest. We only need to mount the rootfs from
|
||||
// the host and it will show up in the guest.
|
||||
if err = bindMountContainerRootfs(kataHostSharedDir, sandbox.id, c.id, c.rootFs, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ociSpec := &specs.Spec{}
|
||||
@ -861,11 +899,12 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
||||
|
||||
createNSList := []ns.NSType{ns.NSTypePID}
|
||||
|
||||
enterNSList := []ns.Namespace{
|
||||
{
|
||||
enterNSList := []ns.Namespace{}
|
||||
if sandbox.networkNS.NetNsPath != "" {
|
||||
enterNSList = append(enterNSList, ns.Namespace{
|
||||
Path: sandbox.networkNS.NetNsPath,
|
||||
Type: ns.NSTypeNet,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return prepareAndStartShim(sandbox, k.shim, c.id, req.ExecId,
|
||||
|
@ -6,12 +6,15 @@
|
||||
package virtcontainers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
gpb "github.com/gogo/protobuf/types"
|
||||
@ -25,6 +28,7 @@ import (
|
||||
"github.com/kata-containers/runtime/virtcontainers/device/api"
|
||||
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
||||
"github.com/kata-containers/runtime/virtcontainers/device/drivers"
|
||||
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
|
||||
"github.com/kata-containers/runtime/virtcontainers/pkg/mock"
|
||||
)
|
||||
|
||||
@ -243,6 +247,8 @@ var reqList = []interface{}{
|
||||
}
|
||||
|
||||
func TestKataAgentSendReq(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
impl := &gRPCProxy{}
|
||||
|
||||
proxy := mock.ProxyGRPCMock{
|
||||
@ -251,15 +257,12 @@ func TestKataAgentSendReq(t *testing.T) {
|
||||
}
|
||||
|
||||
sockDir, err := testGenerateKataProxySockDir()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Nil(err)
|
||||
defer os.RemoveAll(sockDir)
|
||||
|
||||
testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
|
||||
if err := proxy.Start(testKataProxyURL); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = proxy.Start(testKataProxyURL)
|
||||
assert.Nil(err)
|
||||
defer proxy.Stop()
|
||||
|
||||
k := &kataAgent{
|
||||
@ -269,10 +272,58 @@ func TestKataAgentSendReq(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, req := range reqList {
|
||||
if _, err := k.sendReq(req); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = k.sendReq(req)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
sandbox := &Sandbox{}
|
||||
container := &Container{}
|
||||
execid := "processFooBar"
|
||||
|
||||
err = k.startContainer(sandbox, container)
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.signalProcess(container, execid, syscall.SIGKILL, true)
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.winsizeProcess(container, execid, 100, 200)
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = k.processListContainer(sandbox, Container{}, ProcessListOptions{})
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.updateContainer(sandbox, Container{}, specs.LinuxResources{})
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.pauseContainer(sandbox, Container{})
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.resumeContainer(sandbox, Container{})
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.onlineCPUMem(1)
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = k.statsContainer(sandbox, Container{})
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.check()
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = k.waitProcess(container, execid)
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = k.writeProcessStdin(container, execid, []byte{'c'})
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.closeProcessStdin(container, execid)
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = k.readProcessStdout(container, execid, []byte{})
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = k.readProcessStderr(container, execid, []byte{})
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
||||
@ -594,3 +645,207 @@ func TestHandlePidNamespace(t *testing.T) {
|
||||
_, err = k.handlePidNamespace(g, sandbox)
|
||||
assert.NotNil(err)
|
||||
}
|
||||
|
||||
func TestAgentPathAPI(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
k1 := &kataAgent{}
|
||||
k2 := &kataAgent{}
|
||||
id := "foobar"
|
||||
|
||||
// getVMPath
|
||||
path1 := k1.getVMPath(id)
|
||||
path2 := k2.getVMPath(id)
|
||||
assert.Equal(path1, path2)
|
||||
|
||||
// getSharePath
|
||||
path1 = k1.getSharePath(id)
|
||||
path2 = k2.getSharePath(id)
|
||||
assert.Equal(path1, path2)
|
||||
|
||||
// generateVMSocket
|
||||
c := KataAgentConfig{}
|
||||
err := k1.generateVMSocket(id, c)
|
||||
assert.Nil(err)
|
||||
err = k2.generateVMSocket(id, c)
|
||||
assert.Nil(err)
|
||||
assert.Equal(k1, k2)
|
||||
|
||||
c.GRPCSocket = "unixsocket"
|
||||
err = k1.generateVMSocket(id, c)
|
||||
assert.Nil(err)
|
||||
_, ok := k1.vmSocket.(Socket)
|
||||
assert.True(ok)
|
||||
|
||||
c.GRPCSocket = "vsock:100:200"
|
||||
err = k2.generateVMSocket(id, c)
|
||||
assert.Nil(err)
|
||||
_, ok = k2.vmSocket.(kataVSOCK)
|
||||
assert.True(ok)
|
||||
}
|
||||
|
||||
func TestAgentConfigure(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "kata-agent-test")
|
||||
assert.Nil(err)
|
||||
|
||||
k := &kataAgent{}
|
||||
h := &mockHypervisor{}
|
||||
c := KataAgentConfig{GRPCSocket: "vsock:100:200"}
|
||||
id := "foobar"
|
||||
|
||||
invalidAgent := HyperConfig{}
|
||||
err = k.configure(h, id, dir, true, invalidAgent)
|
||||
assert.Error(err)
|
||||
|
||||
err = k.configure(h, id, dir, true, c)
|
||||
assert.Nil(err)
|
||||
|
||||
c.GRPCSocket = "foobarfoobar"
|
||||
err = k.configure(h, id, dir, true, c)
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.configure(h, id, dir, false, c)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestParseVSOCKAddr(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
sock := "randomfoobar"
|
||||
_, _, err := parseVSOCKAddr(sock)
|
||||
assert.Error(err)
|
||||
|
||||
sock = "vsock://1:2"
|
||||
_, _, err = parseVSOCKAddr(sock)
|
||||
assert.Error(err)
|
||||
|
||||
sock = "unix:1:2"
|
||||
_, _, err = parseVSOCKAddr(sock)
|
||||
assert.Error(err)
|
||||
|
||||
sock = "vsock:foo:2"
|
||||
_, _, err = parseVSOCKAddr(sock)
|
||||
assert.Error(err)
|
||||
|
||||
sock = "vsock:1:bar"
|
||||
_, _, err = parseVSOCKAddr(sock)
|
||||
assert.Error(err)
|
||||
|
||||
sock = "vsock:1:2"
|
||||
cid, port, err := parseVSOCKAddr(sock)
|
||||
assert.Nil(err)
|
||||
assert.Equal(cid, uint32(1))
|
||||
assert.Equal(port, uint32(2))
|
||||
}
|
||||
|
||||
func TestCmdToKataProcess(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cmd := Cmd{
|
||||
Args: strings.Split("foo", " "),
|
||||
Envs: []EnvVar{},
|
||||
WorkDir: "/",
|
||||
User: "1000",
|
||||
PrimaryGroup: "1000",
|
||||
}
|
||||
_, err := cmdToKataProcess(cmd)
|
||||
assert.Nil(err)
|
||||
|
||||
cmd1 := cmd
|
||||
cmd1.User = "foobar"
|
||||
_, err = cmdToKataProcess(cmd1)
|
||||
assert.Error(err)
|
||||
|
||||
cmd1 = cmd
|
||||
cmd1.PrimaryGroup = "foobar"
|
||||
_, err = cmdToKataProcess(cmd1)
|
||||
assert.Error(err)
|
||||
|
||||
cmd1 = cmd
|
||||
cmd1.User = "foobar:1000"
|
||||
_, err = cmdToKataProcess(cmd1)
|
||||
assert.Error(err)
|
||||
|
||||
cmd1 = cmd
|
||||
cmd1.User = "1000:2000"
|
||||
_, err = cmdToKataProcess(cmd1)
|
||||
assert.Nil(err)
|
||||
|
||||
cmd1 = cmd
|
||||
cmd1.SupplementaryGroups = []string{"foo"}
|
||||
_, err = cmdToKataProcess(cmd1)
|
||||
assert.Error(err)
|
||||
|
||||
cmd1 = cmd
|
||||
cmd1.SupplementaryGroups = []string{"4000"}
|
||||
_, err = cmdToKataProcess(cmd1)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestAgentCreateContainer(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
sandbox := &Sandbox{
|
||||
id: "foobar",
|
||||
config: &SandboxConfig{
|
||||
ID: "foobar",
|
||||
HypervisorType: MockHypervisor,
|
||||
HypervisorConfig: HypervisorConfig{
|
||||
KernelPath: "foo",
|
||||
ImagePath: "bar",
|
||||
},
|
||||
},
|
||||
hypervisor: &mockHypervisor{},
|
||||
storage: &filesystem{},
|
||||
}
|
||||
|
||||
container := &Container{
|
||||
id: "barfoo",
|
||||
sandboxID: "foobar",
|
||||
sandbox: sandbox,
|
||||
state: State{
|
||||
Fstype: "xfs",
|
||||
},
|
||||
config: &ContainerConfig{
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
}
|
||||
|
||||
ociSpec, err := json.Marshal(&specs.Spec{})
|
||||
assert.Nil(err)
|
||||
container.config.Annotations[vcAnnotations.ConfigJSONKey] = string(ociSpec[:])
|
||||
|
||||
impl := &gRPCProxy{}
|
||||
|
||||
proxy := mock.ProxyGRPCMock{
|
||||
GRPCImplementer: impl,
|
||||
GRPCRegister: gRPCRegister,
|
||||
}
|
||||
|
||||
sockDir, err := testGenerateKataProxySockDir()
|
||||
assert.Nil(err)
|
||||
defer os.RemoveAll(sockDir)
|
||||
|
||||
testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
|
||||
err = proxy.Start(testKataProxyURL)
|
||||
assert.Nil(err)
|
||||
defer proxy.Stop()
|
||||
|
||||
k := &kataAgent{
|
||||
state: KataAgentState{
|
||||
URL: testKataProxyURL,
|
||||
},
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "kata-agent-test")
|
||||
assert.Nil(err)
|
||||
|
||||
err = k.configure(&mockHypervisor{}, sandbox.id, dir, true, KataAgentConfig{})
|
||||
assert.Nil(err)
|
||||
|
||||
// We'll fail on container metadata file creation, but it helps increasing coverage...
|
||||
_, err = k.createContainer(sandbox, container)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
@ -145,3 +145,18 @@ func (n *noopAgent) pauseContainer(sandbox *Sandbox, c Container) error {
|
||||
func (n *noopAgent) resumeContainer(sandbox *Sandbox, c Container) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// configHypervisor is the Noop agent hypervisor configuration implementation. It does nothing.
|
||||
func (n *noopAgent) configure(h hypervisor, id, sharePath string, builtin bool, config interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// getVMPath is the Noop agent vm path getter. It does nothing.
|
||||
func (n *noopAgent) getVMPath(id string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// getVMPath is the Noop agent share path getter. It does nothing.
|
||||
func (n *noopAgent) getSharePath(id string) string {
|
||||
return ""
|
||||
}
|
||||
|
@ -156,3 +156,56 @@ func TestNoopAgentResumeContainer(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoopAgentConfigure(t *testing.T) {
|
||||
n := &noopAgent{}
|
||||
h := &mockHypervisor{}
|
||||
id := "foobar"
|
||||
sharePath := "foobarDir"
|
||||
err := n.configure(h, id, sharePath, true, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoopAgentGetVMPath(t *testing.T) {
|
||||
n := &noopAgent{}
|
||||
path := n.getVMPath("")
|
||||
if path != "" {
|
||||
t.Fatal("getSharePath returns non empty path")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoopAgentGetSharePath(t *testing.T) {
|
||||
n := &noopAgent{}
|
||||
path := n.getSharePath("")
|
||||
if path != "" {
|
||||
t.Fatal("getSharePath returns non empty path")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoopAgentStartProxy(t *testing.T) {
|
||||
n := &noopAgent{}
|
||||
sandbox, _, err := testCreateNoopContainer()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanUp()
|
||||
err = n.startProxy(sandbox)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoopAgentProcessListContainer(t *testing.T) {
|
||||
n := &noopAgent{}
|
||||
sandbox, container, err := testCreateNoopContainer()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanUp()
|
||||
_, err = n.processListContainer(sandbox, *container, ProcessListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ func newSandbox(sandboxConfig SandboxConfig) (*Sandbox, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
agentConfig := newAgentConfig(sandboxConfig)
|
||||
agentConfig := newAgentConfig(sandboxConfig.AgentType, sandboxConfig.AgentConfig)
|
||||
if err = s.agent.init(s, agentConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user