Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
Merge pull request #218 from bergwolf/sandbox_api
Browse files Browse the repository at this point in the history
api: add sandbox operation APIs
  • Loading branch information
Sebastien Boeuf authored Apr 24, 2018
2 parents 76af465 + 29ce01f commit d931d29
Show file tree
Hide file tree
Showing 15 changed files with 467 additions and 93 deletions.
3 changes: 3 additions & 0 deletions virtcontainers/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
97 changes: 29 additions & 68 deletions virtcontainers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,31 @@ func DeleteSandbox(sandboxID string) (VCSandbox, error) {
}

// Delete it.
if err := p.delete(); err != nil {
if err := p.Delete(); err != nil {
return nil, err
}

return p, nil
}

// FetchSandbox is the virtcontainers sandbox fetching entry point.
// FetchSandbox will find out and connect to an existing sandbox and
// return the sandbox structure.
func FetchSandbox(sandboxID string) (VCSandbox, error) {
if sandboxID == "" {
return nil, errNeedSandboxID
}

lockFile, err := rwLockSandbox(sandboxID)
if err != nil {
return nil, err
}
defer unlockSandbox(lockFile)

// Fetch the sandbox from storage and create it.
return fetchSandbox(sandboxID)
}

// StartSandbox is the virtcontainers sandbox starting entry point.
// StartSandbox will talk to the given hypervisor to start an existing
// sandbox and all its containers.
Expand Down Expand Up @@ -281,36 +299,17 @@ func CreateContainer(sandboxID string, containerConfig ContainerConfig) (VCSandb
}
defer unlockSandbox(lockFile)

p, err := fetchSandbox(sandboxID)
s, err := fetchSandbox(sandboxID)
if err != nil {
return nil, nil, err
}

// Create the container.
c, err := createContainer(p, containerConfig)
c, err := s.CreateContainer(containerConfig)
if err != nil {
return nil, nil, err
}

// Add the container to the containers list in the sandbox.
if err := p.addContainer(c); err != nil {
return nil, nil, err
}

// Store it.
err = c.storeContainer()
if err != nil {
return nil, nil, err
}

// Update sandbox config.
p.config.Containers = append(p.config.Containers, containerConfig)
err = p.storage.storeSandboxResource(sandboxID, configFileType, *(p.config))
if err != nil {
return nil, nil, err
}

return p, c, nil
return s, c, nil
}

// DeleteContainer is the virtcontainers container deletion entry point.
Expand All @@ -331,36 +330,12 @@ func DeleteContainer(sandboxID, containerID string) (VCContainer, error) {
}
defer unlockSandbox(lockFile)

p, err := fetchSandbox(sandboxID)
if err != nil {
return nil, err
}

// Fetch the container.
c, err := p.findContainer(containerID)
if err != nil {
return nil, err
}

// Delete it.
err = c.delete()
s, err := fetchSandbox(sandboxID)
if err != nil {
return nil, err
}

// Update sandbox config
for idx, contConfig := range p.config.Containers {
if contConfig.ID == containerID {
p.config.Containers = append(p.config.Containers[:idx], p.config.Containers[idx+1:]...)
break
}
}
err = p.storage.storeSandboxResource(sandboxID, configFileType, *(p.config))
if err != nil {
return nil, err
}

return c, nil
return s.DeleteContainer(containerID)
}

// StartContainer is the virtcontainers container starting entry point.
Expand All @@ -380,19 +355,12 @@ func StartContainer(sandboxID, containerID string) (VCContainer, error) {
}
defer unlockSandbox(lockFile)

p, err := fetchSandbox(sandboxID)
if err != nil {
return nil, err
}

// Fetch the container.
c, err := p.findContainer(containerID)
s, err := fetchSandbox(sandboxID)
if err != nil {
return nil, err
}

// Start it.
err = c.start()
c, err := s.StartContainer(containerID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -454,24 +422,17 @@ func EnterContainer(sandboxID, containerID string, cmd Cmd) (VCSandbox, VCContai
}
defer unlockSandbox(lockFile)

p, err := fetchSandbox(sandboxID)
if err != nil {
return nil, nil, nil, err
}

// Fetch the container.
c, err := p.findContainer(containerID)
s, err := fetchSandbox(sandboxID)
if err != nil {
return nil, nil, nil, err
}

// Enter it.
process, err := c.enter(cmd)
c, process, err := s.EnterContainer(containerID, cmd)
if err != nil {
return nil, nil, nil, err
}

return p, c, process, nil
return s, c, process, nil
}

// StatusContainer is the virtcontainers container status entry point.
Expand Down
35 changes: 35 additions & 0 deletions virtcontainers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2251,3 +2251,38 @@ func BenchmarkStartStop10ContainerQemuHypervisorHyperstartAgentNetworkNoop(b *te
createStartStopDeleteContainers(b, sandboxConfig, contConfigs)
}
}

func TestFetchSandbox(t *testing.T) {
cleanUp()

config := newTestSandboxConfigNoop()

s, err := CreateSandbox(config)
if s == nil || err != nil {
t.Fatal(err)
}

fetched, err := FetchSandbox(s.ID())
assert.Nil(t, err, "%v", err)
assert.True(t, fetched == s, "fetched sandboxed do not match")
}

func TestFetchNonExistingSandbox(t *testing.T) {
cleanUp()

_, 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)
}
1 change: 1 addition & 0 deletions virtcontainers/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ var (
errNeedFile = errors.New("File cannot be empty")
errNeedState = errors.New("State cannot be empty")
errInvalidResource = errors.New("Invalid sandbox resource")
errNoSuchContainer = errors.New("Container does not exist")
)
10 changes: 5 additions & 5 deletions virtcontainers/hyperstart_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions virtcontainers/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ func (impl *VCImpl) ListSandbox() ([]SandboxStatus, error) {
return ListSandbox()
}

// FetchSandbox will find out and connect to an existing sandbox and
// return the sandbox structure.
func (impl *VCImpl) FetchSandbox(sandboxID string) (VCSandbox, error) {
return FetchSandbox(sandboxID)
}

// StatusSandbox implements the VC function of the same name.
func (impl *VCImpl) StatusSandbox(sandboxID string) (SandboxStatus, error) {
return StatusSandbox(sandboxID)
Expand Down
12 changes: 12 additions & 0 deletions virtcontainers/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type VC interface {

CreateSandbox(sandboxConfig SandboxConfig) (VCSandbox, error)
DeleteSandbox(sandboxID string) (VCSandbox, error)
FetchSandbox(sandboxID string) (VCSandbox, error)
ListSandbox() ([]SandboxStatus, error)
PauseSandbox(sandboxID string) (VCSandbox, error)
ResumeSandbox(sandboxID string) (VCSandbox, error)
Expand Down Expand Up @@ -44,6 +45,17 @@ type VCSandbox interface {
GetContainer(containerID string) VCContainer
ID() string
SetAnnotations(annotations map[string]string) error

Pause() error
Resume() error
Release() error
Delete() error
Status() SandboxStatus
CreateContainer(contConfig ContainerConfig) (VCContainer, error)
DeleteContainer(contID string) (VCContainer, error)
StartContainer(containerID string) (VCContainer, error)
StatusContainer(containerID string) (ContainerStatus, error)
EnterContainer(containerID string, cmd Cmd) (VCContainer, *Process, error)
}

// VCContainer is the Container interface
Expand Down
33 changes: 20 additions & 13 deletions virtcontainers/kata_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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 {
Expand All @@ -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{}
}
Expand Down Expand Up @@ -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")
}
Expand All @@ -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")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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
Expand All @@ -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:
Expand Down
5 changes: 5 additions & 0 deletions virtcontainers/noop_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit d931d29

Please sign in to comment.