From d69fbcf17f91144140e24f30743a97c199e3014b Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 23 Jul 2018 09:54:02 +0800 Subject: [PATCH] sandbox: add stateful sandbox config When enabled, do not release in memory sandbox resources in VC APIs, and callers are expected to call sandbox.Release() to release the in memory resources. Signed-off-by: Peng Tao --- virtcontainers/api.go | 34 +++++++++++++++++----------------- virtcontainers/api_test.go | 22 +++++++++++++++++++--- virtcontainers/sandbox.go | 16 +++++++++++++++- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/virtcontainers/api.go b/virtcontainers/api.go index 8c75b095dc..52ceb55ca7 100644 --- a/virtcontainers/api.go +++ b/virtcontainers/api.go @@ -37,7 +37,7 @@ func SetLogger(logger logrus.FieldLogger) { func CreateSandbox(sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) { s, err := createSandboxFromConfig(sandboxConfig, factory) if err == nil { - s.Release() + s.releaseStatelessSandbox() } return s, err @@ -91,7 +91,7 @@ func DeleteSandbox(sandboxID string) (VCSandbox, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() // Delete it. if err := s.Delete(); err != nil { @@ -155,7 +155,7 @@ func StartSandbox(sandboxID string) (VCSandbox, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() return startSandbox(s) } @@ -193,7 +193,7 @@ func StopSandbox(sandboxID string) (VCSandbox, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() // Stop it. err = s.stop() @@ -221,7 +221,7 @@ func RunSandbox(sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() lockFile, err := rwLockSandbox(s.id) if err != nil { @@ -280,7 +280,7 @@ func StatusSandbox(sandboxID string) (SandboxStatus, error) { unlockSandbox(lockFile) return SandboxStatus{}, err } - defer s.Release() + defer s.releaseStatelessSandbox() // We need to potentially wait for a separate container.stop() routine // that needs to be terminated before we return from this function. @@ -332,7 +332,7 @@ func CreateContainer(sandboxID string, containerConfig ContainerConfig) (VCSandb if err != nil { return nil, nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() c, err := s.CreateContainer(containerConfig) if err != nil { @@ -364,7 +364,7 @@ func DeleteContainer(sandboxID, containerID string) (VCContainer, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() return s.DeleteContainer(containerID) } @@ -390,7 +390,7 @@ func StartContainer(sandboxID, containerID string) (VCContainer, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() c, err := s.StartContainer(containerID) if err != nil { @@ -421,7 +421,7 @@ func StopContainer(sandboxID, containerID string) (VCContainer, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() // Fetch the container. c, err := s.findContainer(containerID) @@ -459,7 +459,7 @@ func EnterContainer(sandboxID, containerID string, cmd Cmd) (VCSandbox, VCContai if err != nil { return nil, nil, nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() c, process, err := s.EnterContainer(containerID, cmd) if err != nil { @@ -490,7 +490,7 @@ func StatusContainer(sandboxID, containerID string) (ContainerStatus, error) { unlockSandbox(lockFile) return ContainerStatus{}, err } - defer s.Release() + defer s.releaseStatelessSandbox() // We need to potentially wait for a separate container.stop() routine // that needs to be terminated before we return from this function. @@ -577,7 +577,7 @@ func KillContainer(sandboxID, containerID string, signal syscall.Signal, all boo if err != nil { return err } - defer s.Release() + defer s.releaseStatelessSandbox() // Fetch the container. c, err := s.findContainer(containerID) @@ -627,7 +627,7 @@ func ProcessListContainer(sandboxID, containerID string, options ProcessListOpti if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() // Fetch the container. c, err := s.findContainer(containerID) @@ -659,7 +659,7 @@ func UpdateContainer(sandboxID, containerID string, resources specs.LinuxResourc if err != nil { return err } - defer s.Release() + defer s.releaseStatelessSandbox() return s.UpdateContainer(containerID, resources) } @@ -685,7 +685,7 @@ func StatsContainer(sandboxID, containerID string) (ContainerStats, error) { if err != nil { return ContainerStats{}, err } - defer s.Release() + defer s.releaseStatelessSandbox() return s.StatsContainer(containerID) } @@ -709,7 +709,7 @@ func togglePauseContainer(sandboxID, containerID string, pause bool) error { if err != nil { return err } - defer s.Release() + defer s.releaseStatelessSandbox() // Fetch the container. c, err := s.findContainer(containerID) diff --git a/virtcontainers/api_test.go b/virtcontainers/api_test.go index 40c1a92377..8cc929fd6a 100644 --- a/virtcontainers/api_test.go +++ b/virtcontainers/api_test.go @@ -1811,7 +1811,7 @@ func TestStatusContainerStateReady(t *testing.T) { if err != nil { t.Fatal(err) } - defer p2.Release() + defer p2.releaseStatelessSandbox() expectedStatus := ContainerStatus{ ID: contID, @@ -1885,7 +1885,7 @@ func TestStatusContainerStateRunning(t *testing.T) { if err != nil { t.Fatal(err) } - defer p2.Release() + defer p2.releaseStatelessSandbox() expectedStatus := ContainerStatus{ ID: contID, @@ -2335,7 +2335,23 @@ func TestFetchSandbox(t *testing.T) { fetched, err := FetchSandbox(s.ID()) assert.Nil(t, err, "%v", err) - assert.True(t, fetched == s, "fetched sandboxed do not match") + assert.True(t, fetched != s, "fetched stateless sandboxes should not match") +} + +func TestFetchStatefulSandbox(t *testing.T) { + cleanUp() + + config := newTestSandboxConfigNoop() + + config.Stateful = true + s, err := CreateSandbox(config, nil) + if s == nil || err != nil { + t.Fatal(err) + } + + fetched, err := FetchSandbox(s.ID()) + assert.Nil(t, err, "%v", err) + assert.Equal(t, fetched, s, "fetched stateful sandboxed should match") } func TestFetchNonExistingSandbox(t *testing.T) { diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index b175f2ef20..102e34a89f 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -350,6 +350,10 @@ type SandboxConfig struct { // SharePidNs sets all containers to share the same sandbox level pid namespace. SharePidNs bool + + // Stateful keeps sandbox resources in memory across APIs. Users will be responsible + // for calling Release() to release the memory resources. + Stateful bool } func (s *Sandbox) startProxy() error { @@ -468,6 +472,7 @@ type Sandbox struct { shmSize uint64 sharePidNs bool + stateful bool } // ID returns the sandbox identifier string. @@ -550,6 +555,14 @@ func (s *Sandbox) Release() error { return s.agent.disconnect() } +func (s *Sandbox) releaseStatelessSandbox() error { + if s.stateful { + return nil + } + + return s.Release() +} + // Status gets the status of the sandbox // TODO: update container status properly, see kata-containers/runtime#253 func (s *Sandbox) Status() SandboxStatus { @@ -752,6 +765,7 @@ func newSandbox(sandboxConfig SandboxConfig, factory Factory) (*Sandbox, error) wg: &sync.WaitGroup{}, shmSize: sandboxConfig.ShmSize, sharePidNs: sandboxConfig.SharePidNs, + stateful: sandboxConfig.Stateful, } if err = globalSandboxList.addSandbox(s); err != nil { @@ -1391,7 +1405,7 @@ func togglePauseSandbox(sandboxID string, pause bool) (*Sandbox, error) { if err != nil { return nil, err } - defer s.Release() + defer s.releaseStatelessSandbox() if pause { err = s.Pause()