api: add sandbox release API

It disconnects the agent connection and removes the sandbox
from global sandbox list.

A new option `LongLiveConn` is also added to kata
agent's configuration. When set, the API caller is expected
to call sandbox.Release() to drop the agent connection explicitly.

`proxyBuiltIn` is moved out of agent state because we can always
retrieve it from sandbox config instead.

Fixes: #217

Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
Peng Tao 2018-04-19 18:54:08 +08:00
parent d189be8579
commit eb23771d5a
8 changed files with 59 additions and 18 deletions

View File

@ -133,6 +133,9 @@ type agent interface {
// supported by the agent.
capabilities() capabilities
// disconnect will disconnect the connection to the agent
disconnect() error
// createSandbox will tell the agent to perform necessary setup for a Sandbox.
createSandbox(sandbox *Sandbox) error

View File

@ -2273,3 +2273,16 @@ func TestFetchNonExistingSandbox(t *testing.T) {
_, err := FetchSandbox("some-non-existing-sandbox-name")
assert.NotNil(t, err, "fetch non-existing sandbox should fail")
}
func TestReleaseSandbox(t *testing.T) {
cleanUp()
config := newTestSandboxConfigNoop()
s, err := CreateSandbox(config)
if s == nil || err != nil {
t.Fatal(err)
}
err = s.Release()
assert.Nil(t, err, "sandbox release failed: %v", err)
}

View File

@ -715,13 +715,13 @@ func (h *hyper) connect() error {
return nil
}
func (h *hyper) disconnect() {
if h.client == nil {
return
func (h *hyper) disconnect() error {
if h.client != nil {
h.client.Close()
h.client = nil
}
h.client.Close()
h.client = nil
return nil
}
func (h *hyper) register() error {

View File

@ -45,6 +45,8 @@ type VCSandbox interface {
GetContainer(containerID string) VCContainer
ID() string
SetAnnotations(annotations map[string]string) error
Release() error
}
// VCContainer is the Container interface

View File

@ -21,8 +21,10 @@ import (
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
ns "github.com/kata-containers/runtime/virtcontainers/pkg/nsenter"
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
golangGrpc "google.golang.org/grpc"
)
var (
@ -47,7 +49,8 @@ var (
// KataAgentConfig is a structure storing information needed
// to reach the Kata Containers agent.
type KataAgentConfig struct {
GRPCSocket string
GRPCSocket string
LongLiveConn bool
}
type kataVSOCK struct {
@ -62,16 +65,17 @@ func (s *kataVSOCK) String() string {
// KataAgentState is the structure describing the data stored from this
// agent implementation.
type KataAgentState struct {
ProxyPid int
ProxyBuiltIn bool
URL string
ProxyPid int
URL string
}
type kataAgent struct {
shim shim
proxy proxy
client *kataclient.AgentClient
state KataAgentState
shim shim
proxy proxy
client *kataclient.AgentClient
state KataAgentState
keepConn bool
proxyBuiltIn bool
vmSocket interface{}
}
@ -128,6 +132,7 @@ func (k *kataAgent) init(sandbox *Sandbox, config interface{}) (err error) {
if err := k.generateVMSocket(*sandbox, c); err != nil {
return err
}
k.keepConn = c.LongLiveConn
default:
return fmt.Errorf("Invalid config type")
}
@ -142,6 +147,8 @@ func (k *kataAgent) init(sandbox *Sandbox, config interface{}) (err error) {
return err
}
k.proxyBuiltIn = isProxyBuiltIn(sandbox.config.ProxyType)
// Fetch agent runtime info.
if err := sandbox.storage.fetchAgentState(sandbox.id, &k.state); err != nil {
k.Logger().Debug("Could not retrieve anything from storage")
@ -418,7 +425,6 @@ func (k *kataAgent) startSandbox(sandbox Sandbox) error {
// Fill agent state with proxy information, and store them.
k.state.ProxyPid = pid
k.state.ProxyBuiltIn = isProxyBuiltIn(sandbox.config.ProxyType)
k.state.URL = uri
if err := sandbox.storage.storeAgentState(sandbox.id, k.state); err != nil {
return err
@ -905,7 +911,7 @@ func (k *kataAgent) connect() error {
return nil
}
client, err := kataclient.NewAgentClient(k.state.URL, k.state.ProxyBuiltIn)
client, err := kataclient.NewAgentClient(k.state.URL, k.proxyBuiltIn)
if err != nil {
return err
}
@ -920,10 +926,9 @@ func (k *kataAgent) disconnect() error {
return nil
}
if err := k.client.Close(); err != nil {
if err := k.client.Close(); err != nil && err != golangGrpc.ErrClientConnClosing {
return err
}
k.client = nil
return nil
@ -933,7 +938,9 @@ func (k *kataAgent) sendReq(request interface{}) (interface{}, error) {
if err := k.connect(); err != nil {
return nil, err
}
defer k.disconnect()
if !k.keepConn {
defer k.disconnect()
}
switch req := request.(type) {
case *grpc.ExecProcessRequest:

View File

@ -29,6 +29,11 @@ func (n *noopAgent) capabilities() capabilities {
return capabilities{}
}
// disconnect is the Noop agent connection closer. It does nothing.
func (n *noopAgent) disconnect() error {
return nil
}
// exec is the Noop agent command execution implementation. It does nothing.
func (n *noopAgent) exec(sandbox *Sandbox, c Container, cmd Cmd) (*Process, error) {
return nil, nil

View File

@ -49,3 +49,8 @@ func (p *Sandbox) GetContainer(containerID string) vc.VCContainer {
}
return &Container{}
}
// Release implements the VCSandbox function of the same name.
func (p *Sandbox) Release() error {
return nil
}

View File

@ -529,6 +529,12 @@ func (s *Sandbox) GetContainer(containerID string) VCContainer {
return nil
}
// Release closes the agent connection and removes sandbox from internal list.
func (s *Sandbox) Release() error {
globalSandboxList.removeSandbox(s.id)
return s.agent.disconnect()
}
func createAssets(sandboxConfig *SandboxConfig) error {
kernel, err := newAsset(sandboxConfig, kernelAsset)
if err != nil {