diff --git a/virtcontainers/agent.go b/virtcontainers/agent.go index c273c46db3..0409c2cbe4 100644 --- a/virtcontainers/agent.go +++ b/virtcontainers/agent.go @@ -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 diff --git a/virtcontainers/api_test.go b/virtcontainers/api_test.go index df76d4c2e8..962de6f5d0 100644 --- a/virtcontainers/api_test.go +++ b/virtcontainers/api_test.go @@ -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) +} diff --git a/virtcontainers/hyperstart_agent.go b/virtcontainers/hyperstart_agent.go index 53481d0b9d..eabb103a9d 100644 --- a/virtcontainers/hyperstart_agent.go +++ b/virtcontainers/hyperstart_agent.go @@ -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 { diff --git a/virtcontainers/interfaces.go b/virtcontainers/interfaces.go index 3c4dd618b9..024f1fe287 100644 --- a/virtcontainers/interfaces.go +++ b/virtcontainers/interfaces.go @@ -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 diff --git a/virtcontainers/kata_agent.go b/virtcontainers/kata_agent.go index e896f80edd..f2a482b1f5 100644 --- a/virtcontainers/kata_agent.go +++ b/virtcontainers/kata_agent.go @@ -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: diff --git a/virtcontainers/noop_agent.go b/virtcontainers/noop_agent.go index eff024cc89..fa6a07779c 100644 --- a/virtcontainers/noop_agent.go +++ b/virtcontainers/noop_agent.go @@ -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 diff --git a/virtcontainers/pkg/vcmock/sandbox.go b/virtcontainers/pkg/vcmock/sandbox.go index 873b66a5e4..4d951edfcd 100644 --- a/virtcontainers/pkg/vcmock/sandbox.go +++ b/virtcontainers/pkg/vcmock/sandbox.go @@ -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 +} diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index 4195db6741..3228e52e23 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -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 {