mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-02 02:02:24 +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.
|
// newAgentConfig returns an agent config from a generic SandboxConfig interface.
|
||||||
func newAgentConfig(config SandboxConfig) interface{} {
|
func newAgentConfig(agentType AgentType, agentConfig interface{}) interface{} {
|
||||||
switch config.AgentType {
|
switch agentType {
|
||||||
case NoopAgentType:
|
case NoopAgentType:
|
||||||
return nil
|
return nil
|
||||||
case HyperstartAgent:
|
case HyperstartAgent:
|
||||||
var hyperConfig HyperConfig
|
var hyperConfig HyperConfig
|
||||||
err := mapstructure.Decode(config.AgentConfig, &hyperConfig)
|
err := mapstructure.Decode(agentConfig, &hyperConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hyperConfig
|
return hyperConfig
|
||||||
case KataContainersAgent:
|
case KataContainersAgent:
|
||||||
var kataAgentConfig KataAgentConfig
|
var kataAgentConfig KataAgentConfig
|
||||||
err := mapstructure.Decode(config.AgentConfig, &kataAgentConfig)
|
err := mapstructure.Decode(agentConfig, &kataAgentConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -209,4 +209,13 @@ type agent interface {
|
|||||||
|
|
||||||
// resumeContainer will resume a paused container
|
// resumeContainer will resume a paused container
|
||||||
resumeContainer(sandbox *Sandbox, c Container) error
|
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{}) {
|
func testNewAgentConfig(t *testing.T, config SandboxConfig, expected interface{}) {
|
||||||
agentConfig := newAgentConfig(config)
|
agentConfig := newAgentConfig(config.AgentType, config.AgentConfig)
|
||||||
if reflect.DeepEqual(agentConfig, expected) == false {
|
if reflect.DeepEqual(agentConfig, expected) == false {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
@ -85,17 +85,27 @@ const dirMode = os.FileMode(0750) | os.ModeDir
|
|||||||
|
|
||||||
// storagePathSuffix is the suffix used for all storage paths
|
// 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.
|
// 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.
|
// configStoragePath is the sandbox configuration directory.
|
||||||
// It will contain one config.json file for each created sandbox.
|
// 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.
|
// runStoragePath is the sandbox runtime directory.
|
||||||
// It will contain one state.json and one lock file for each created sandbox.
|
// 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...)
|
// resourceStorage is the virtcontainers resources (configuration, state, etc...)
|
||||||
// storage interface.
|
// storage interface.
|
||||||
|
@ -262,9 +262,17 @@ func (h *hyper) init(sandbox *Sandbox, config interface{}) (err error) {
|
|||||||
return nil
|
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 {
|
for _, socket := range h.sockets {
|
||||||
err := sandbox.hypervisor.addDevice(socket, serialPortDev)
|
err := hv.addDevice(socket, serialPortDev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -274,14 +282,18 @@ func (h *hyper) createSandbox(sandbox *Sandbox) (err error) {
|
|||||||
// This volume contains all bind mounted container bundles.
|
// This volume contains all bind mounted container bundles.
|
||||||
sharedVolume := Volume{
|
sharedVolume := Volume{
|
||||||
MountTag: mountTag,
|
MountTag: mountTag,
|
||||||
HostPath: filepath.Join(defaultSharedDir, sandbox.id),
|
HostPath: sharePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(sharedVolume.HostPath, dirMode); err != nil {
|
if err := os.MkdirAll(sharedVolume.HostPath, dirMode); err != nil {
|
||||||
return err
|
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 {
|
func (h *hyper) capabilities() capabilities {
|
||||||
|
@ -7,11 +7,13 @@ package virtcontainers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kata-containers/runtime/virtcontainers/pkg/hyperstart"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/hyperstart"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -156,3 +158,43 @@ func TestProcessHyperRouteDestIPv6Failure(t *testing.T) {
|
|||||||
|
|
||||||
testProcessHyperRoute(t, route, testRouteDeviceName, nil)
|
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
|
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)
|
cid, port, err := parseVSOCKAddr(c.GRPCSocket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We need to generate a host UNIX socket path for the emulated serial port.
|
// 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 {
|
if err != nil {
|
||||||
return err
|
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) {
|
func (k *kataAgent) init(sandbox *Sandbox, config interface{}) (err error) {
|
||||||
switch c := config.(type) {
|
switch c := config.(type) {
|
||||||
case KataAgentConfig:
|
case KataAgentConfig:
|
||||||
if err := k.generateVMSocket(sandbox, c); err != nil {
|
if err := k.generateVMSocket(sandbox.id, c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
k.keepConn = c.LongLiveConn
|
k.keepConn = c.LongLiveConn
|
||||||
@ -196,10 +204,22 @@ func (k *kataAgent) capabilities() capabilities {
|
|||||||
return caps
|
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) {
|
switch s := k.vmSocket.(type) {
|
||||||
case Socket:
|
case Socket:
|
||||||
err := sandbox.hypervisor.addDevice(s, serialPortDev)
|
err := h.addDevice(s, serialPortDev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -209,18 +229,27 @@ func (k *kataAgent) createSandbox(sandbox *Sandbox) error {
|
|||||||
return fmt.Errorf("Invalid config type")
|
return fmt.Errorf("Invalid config type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if builtin {
|
||||||
|
k.proxyBuiltIn = true
|
||||||
|
k.state.URL, _ = k.agentURL()
|
||||||
|
}
|
||||||
|
|
||||||
// Adding the shared volume.
|
// Adding the shared volume.
|
||||||
// This volume contains all bind mounted container bundles.
|
// This volume contains all bind mounted container bundles.
|
||||||
sharedVolume := Volume{
|
sharedVolume := Volume{
|
||||||
MountTag: mountGuest9pTag,
|
MountTag: mountGuest9pTag,
|
||||||
HostPath: filepath.Join(kataHostSharedDir, sandbox.id),
|
HostPath: sharePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(sharedVolume.HostPath, dirMode); err != nil {
|
if err := os.MkdirAll(sharedVolume.HostPath, dirMode); err != nil {
|
||||||
return err
|
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) {
|
func cmdToKataProcess(cmd Cmd) (process *grpc.Process, err error) {
|
||||||
@ -719,15 +748,8 @@ func (k *kataAgent) rollbackFailingContainerCreation(c *Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process, err error) {
|
func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPathParent string) (*grpc.Storage, error) {
|
||||||
ociSpecJSON, ok := c.config.Annotations[vcAnnotations.ConfigJSONKey]
|
if c.state.Fstype != "" {
|
||||||
if !ok {
|
|
||||||
return nil, errorMissingOCISpec
|
|
||||||
}
|
|
||||||
|
|
||||||
var ctrStorages []*grpc.Storage
|
|
||||||
var ctrDevices []*grpc.Device
|
|
||||||
|
|
||||||
// The rootfs storage volume represents the container rootfs
|
// The rootfs storage volume represents the container rootfs
|
||||||
// mount point inside the guest.
|
// mount point inside the guest.
|
||||||
// It can be a block based device (when using block based container
|
// It can be a block based device (when using block based container
|
||||||
@ -735,19 +757,6 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
|||||||
// implementations).
|
// implementations).
|
||||||
rootfs := &grpc.Storage{}
|
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 c.state.Fstype != "" {
|
|
||||||
// This is a block based device rootfs.
|
// This is a block based device rootfs.
|
||||||
|
|
||||||
// Pass a drive name only in case of virtio-blk driver.
|
// Pass a drive name only in case of virtio-blk driver.
|
||||||
@ -773,13 +782,8 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
|||||||
rootfs.Options = []string{"nouuid"}
|
rootfs.Options = []string{"nouuid"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add rootfs to the list of container storage.
|
return rootfs, nil
|
||||||
// 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.
|
// This is not a block based device rootfs.
|
||||||
// We are going to bind mount it into the 9pfs
|
// We are going to bind mount it into the 9pfs
|
||||||
// shared drive between the host and the guest.
|
// shared drive between the host and the guest.
|
||||||
@ -788,9 +792,43 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
|||||||
// (kataGuestSharedDir) is already mounted in the
|
// (kataGuestSharedDir) is already mounted in the
|
||||||
// guest. We only need to mount the rootfs from
|
// guest. We only need to mount the rootfs from
|
||||||
// the host and it will show up in the guest.
|
// the host and it will show up in the guest.
|
||||||
if err = bindMountContainerRootfs(kataHostSharedDir, sandbox.id, c.id, c.rootFs, false); err != nil {
|
if err := bindMountContainerRootfs(kataHostSharedDir, sandbox.id, c.id, c.rootFs, false); err != nil {
|
||||||
return nil, err
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
ociSpec := &specs.Spec{}
|
ociSpec := &specs.Spec{}
|
||||||
@ -861,11 +899,12 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
|||||||
|
|
||||||
createNSList := []ns.NSType{ns.NSTypePID}
|
createNSList := []ns.NSType{ns.NSTypePID}
|
||||||
|
|
||||||
enterNSList := []ns.Namespace{
|
enterNSList := []ns.Namespace{}
|
||||||
{
|
if sandbox.networkNS.NetNsPath != "" {
|
||||||
|
enterNSList = append(enterNSList, ns.Namespace{
|
||||||
Path: sandbox.networkNS.NetNsPath,
|
Path: sandbox.networkNS.NetNsPath,
|
||||||
Type: ns.NSTypeNet,
|
Type: ns.NSTypeNet,
|
||||||
},
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return prepareAndStartShim(sandbox, k.shim, c.id, req.ExecId,
|
return prepareAndStartShim(sandbox, k.shim, c.id, req.ExecId,
|
||||||
|
@ -6,12 +6,15 @@
|
|||||||
package virtcontainers
|
package virtcontainers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
gpb "github.com/gogo/protobuf/types"
|
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/api"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/device/drivers"
|
"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"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -243,6 +247,8 @@ var reqList = []interface{}{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestKataAgentSendReq(t *testing.T) {
|
func TestKataAgentSendReq(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
impl := &gRPCProxy{}
|
impl := &gRPCProxy{}
|
||||||
|
|
||||||
proxy := mock.ProxyGRPCMock{
|
proxy := mock.ProxyGRPCMock{
|
||||||
@ -251,15 +257,12 @@ func TestKataAgentSendReq(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sockDir, err := testGenerateKataProxySockDir()
|
sockDir, err := testGenerateKataProxySockDir()
|
||||||
if err != nil {
|
assert.Nil(err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(sockDir)
|
defer os.RemoveAll(sockDir)
|
||||||
|
|
||||||
testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
|
testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
|
||||||
if err := proxy.Start(testKataProxyURL); err != nil {
|
err = proxy.Start(testKataProxyURL)
|
||||||
t.Fatal(err)
|
assert.Nil(err)
|
||||||
}
|
|
||||||
defer proxy.Stop()
|
defer proxy.Stop()
|
||||||
|
|
||||||
k := &kataAgent{
|
k := &kataAgent{
|
||||||
@ -269,10 +272,58 @@ func TestKataAgentSendReq(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, req := range reqList {
|
for _, req := range reqList {
|
||||||
if _, err := k.sendReq(req); err != nil {
|
_, err = k.sendReq(req)
|
||||||
t.Fatal(err)
|
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) {
|
func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
||||||
@ -594,3 +645,207 @@ func TestHandlePidNamespace(t *testing.T) {
|
|||||||
_, err = k.handlePidNamespace(g, sandbox)
|
_, err = k.handlePidNamespace(g, sandbox)
|
||||||
assert.NotNil(err)
|
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 {
|
func (n *noopAgent) resumeContainer(sandbox *Sandbox, c Container) error {
|
||||||
return nil
|
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)
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
agentConfig := newAgentConfig(sandboxConfig)
|
agentConfig := newAgentConfig(sandboxConfig.AgentType, sandboxConfig.AgentConfig)
|
||||||
if err = s.agent.init(s, agentConfig); err != nil {
|
if err = s.agent.init(s, agentConfig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user