sandbox: support force stop

When force is true, ignore any guest related errors. This can
be used to stop a sandbox when hypervisor process is dead.

Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
Peng Tao 2019-07-19 00:40:34 -07:00
parent 4130913ed7
commit bc4460e12f
12 changed files with 32 additions and 31 deletions

View File

@ -112,7 +112,7 @@ func delete(ctx context.Context, containerID string, force bool) error {
switch containerType { switch containerType {
case vc.PodSandbox: case vc.PodSandbox:
if err := deleteSandbox(ctx, sandboxID); err != nil { if err := deleteSandbox(ctx, sandboxID, force); err != nil {
return err return err
} }
case vc.PodContainer: case vc.PodContainer:
@ -131,7 +131,7 @@ func delete(ctx context.Context, containerID string, force bool) error {
return katautils.DelContainerIDMapping(ctx, containerID) return katautils.DelContainerIDMapping(ctx, containerID)
} }
func deleteSandbox(ctx context.Context, sandboxID string) error { func deleteSandbox(ctx context.Context, sandboxID string, force bool) error {
span, _ := katautils.Trace(ctx, "deleteSandbox") span, _ := katautils.Trace(ctx, "deleteSandbox")
defer span.Finish() defer span.Finish()
@ -141,7 +141,7 @@ func deleteSandbox(ctx context.Context, sandboxID string) error {
} }
if oci.StateToOCIState(status.State.State) != oci.StateStopped { if oci.StateToOCIState(status.State.State) != oci.StateStopped {
if _, err := vci.StopSandbox(ctx, sandboxID); err != nil { if _, err := vci.StopSandbox(ctx, sandboxID, force); err != nil {
return err return err
} }
} }

View File

@ -152,7 +152,7 @@ func kill(ctx context.Context, containerID, signal string, all bool) error {
switch containerType { switch containerType {
case vc.PodSandbox: case vc.PodSandbox:
_, err = vci.StopSandbox(ctx, sandboxID) _, err = vci.StopSandbox(ctx, sandboxID, signum == syscall.SIGKILL)
case vc.PodContainer: case vc.PodContainer:
_, err = vci.StopContainer(ctx, sandboxID, containerID) _, err = vci.StopContainer(ctx, sandboxID, containerID)
default: default:

View File

@ -70,7 +70,7 @@ func cleanupContainer(ctx context.Context, sid, cid, bundlePath string) error {
} }
if len(sandbox.GetAllContainers()) == 0 { if len(sandbox.GetAllContainers()) == 0 {
err = sandbox.Stop() err = sandbox.Stop(true)
if err != nil { if err != nil {
logrus.WithError(err).WithField("sandbox", sid).Warn("failed to stop sandbox") logrus.WithError(err).WithField("sandbox", sid).Warn("failed to stop sandbox")
return err return err

View File

@ -51,7 +51,7 @@ func wait(s *service, c *container, execID string) (int32, error) {
// sandbox. // sandbox.
if c.cType.IsSandbox() { if c.cType.IsSandbox() {
if err = s.sandbox.Stop(); err != nil { if err = s.sandbox.Stop(true); err != nil {
logrus.WithField("sandbox", s.sandbox.ID()).Error("failed to stop sandbox") logrus.WithField("sandbox", s.sandbox.ID()).Error("failed to stop sandbox")
} }

View File

@ -235,7 +235,7 @@ func StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) {
// StopSandbox is the virtcontainers sandbox stopping entry point. // StopSandbox is the virtcontainers sandbox stopping entry point.
// StopSandbox will talk to the given agent to stop an existing sandbox and destroy all containers within that sandbox. // StopSandbox will talk to the given agent to stop an existing sandbox and destroy all containers within that sandbox.
func StopSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { func StopSandbox(ctx context.Context, sandboxID string, force bool) (VCSandbox, error) {
span, ctx := trace(ctx, "StopSandbox") span, ctx := trace(ctx, "StopSandbox")
defer span.Finish() defer span.Finish()
@ -257,7 +257,7 @@ func StopSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) {
defer s.releaseStatelessSandbox() defer s.releaseStatelessSandbox()
// Stop it. // Stop it.
err = s.Stop() err = s.Stop(force)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -596,7 +596,7 @@ func statusContainer(sandbox *Sandbox, containerID string) (ContainerStatus, err
"state": container.state.State, "state": container.state.State,
"pid": container.process.Pid}). "pid": container.process.Pid}).
Info("container isn't running") Info("container isn't running")
if err := container.stop(); err != nil { if err := container.stop(true); err != nil {
return ContainerStatus{}, err return ContainerStatus{}, err
} }
} }

View File

@ -332,7 +332,7 @@ func TestStopSandboxNoopAgentSuccessful(t *testing.T) {
assert.NoError(err) assert.NoError(err)
assert.NotNil(p) assert.NotNil(p)
vp, err := StopSandbox(ctx, p.ID()) vp, err := StopSandbox(ctx, p.ID(), false)
assert.NoError(err) assert.NoError(err)
assert.NotNil(vp) assert.NotNil(vp)
} }
@ -427,7 +427,7 @@ func TestStopSandboxKataAgentSuccessful(t *testing.T) {
assert.NoError(err) assert.NoError(err)
assert.NotNil(p) assert.NotNil(p)
p, err = StopSandbox(ctx, p.ID()) p, err = StopSandbox(ctx, p.ID(), false)
assert.NoError(err) assert.NoError(err)
assert.NotNil(p) assert.NotNil(p)
} }
@ -438,7 +438,7 @@ func TestStopSandboxFailing(t *testing.T) {
sandboxDir := store.SandboxConfigurationRootPath(testSandboxID) sandboxDir := store.SandboxConfigurationRootPath(testSandboxID)
os.Remove(sandboxDir) os.Remove(sandboxDir)
p, err := StopSandbox(context.Background(), testSandboxID) p, err := StopSandbox(context.Background(), testSandboxID, false)
assert.Error(t, err) assert.Error(t, err)
assert.Nil(t, p) assert.Nil(t, p)
} }
@ -1461,7 +1461,7 @@ func createStartStopDeleteSandbox(b *testing.B, sandboxConfig SandboxConfig) {
} }
// Stop sandbox // Stop sandbox
_, err = StopSandbox(ctx, p.ID()) _, err = StopSandbox(ctx, p.ID(), false)
if err != nil { if err != nil {
b.Fatalf("Could not stop sandbox: %s", err) b.Fatalf("Could not stop sandbox: %s", err)
} }

View File

@ -946,7 +946,7 @@ func (c *Container) start() error {
if err := c.sandbox.agent.startContainer(c.sandbox, c); err != nil { if err := c.sandbox.agent.startContainer(c.sandbox, c); err != nil {
c.Logger().WithError(err).Error("Failed to start container") c.Logger().WithError(err).Error("Failed to start container")
if err := c.stop(); err != nil { if err := c.stop(true); err != nil {
c.Logger().WithError(err).Warn("Failed to stop container") c.Logger().WithError(err).Warn("Failed to stop container")
} }
return err return err
@ -955,7 +955,7 @@ func (c *Container) start() error {
return c.setContainerState(types.StateRunning) return c.setContainerState(types.StateRunning)
} }
func (c *Container) stop() error { func (c *Container) stop(force bool) error {
span, _ := c.trace("stop") span, _ := c.trace("stop")
defer span.Finish() defer span.Finish()
@ -999,7 +999,7 @@ func (c *Container) stop() error {
// return an error, but instead try to kill it forcefully. // return an error, but instead try to kill it forcefully.
if err := waitForShim(c.process.Pid); err != nil { if err := waitForShim(c.process.Pid); err != nil {
// Force the container to be killed. // Force the container to be killed.
if err := c.kill(syscall.SIGKILL, true); err != nil { if err := c.kill(syscall.SIGKILL, true); err != nil && !force {
return err return err
} }
@ -1007,7 +1007,7 @@ func (c *Container) stop() error {
// to succeed. Indeed, we have already given a second chance // to succeed. Indeed, we have already given a second chance
// to the container by trying to kill it with SIGKILL, there // to the container by trying to kill it with SIGKILL, there
// is no reason to try to go further if we got an error. // is no reason to try to go further if we got an error.
if err := waitForShim(c.process.Pid); err != nil { if err := waitForShim(c.process.Pid); err != nil && !force {
return err return err
} }
} }
@ -1045,15 +1045,15 @@ func (c *Container) stop() error {
} }
}() }()
if err := c.sandbox.agent.stopContainer(c.sandbox, *c); err != nil { if err := c.sandbox.agent.stopContainer(c.sandbox, *c); err != nil && !force {
return err return err
} }
if err := c.detachDevices(); err != nil { if err := c.detachDevices(); err != nil && !force {
return err return err
} }
if err := c.removeDrive(); err != nil { if err := c.removeDrive(); err != nil && !force {
return err return err
} }

View File

@ -52,8 +52,8 @@ func (impl *VCImpl) StartSandbox(ctx context.Context, sandboxID string) (VCSandb
} }
// StopSandbox implements the VC function of the same name. // StopSandbox implements the VC function of the same name.
func (impl *VCImpl) StopSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { func (impl *VCImpl) StopSandbox(ctx context.Context, sandboxID string, force bool) (VCSandbox, error) {
return StopSandbox(ctx, sandboxID) return StopSandbox(ctx, sandboxID, force)
} }
// RunSandbox implements the VC function of the same name. // RunSandbox implements the VC function of the same name.

View File

@ -32,7 +32,7 @@ type VC interface {
RunSandbox(ctx context.Context, sandboxConfig SandboxConfig) (VCSandbox, error) RunSandbox(ctx context.Context, sandboxConfig SandboxConfig) (VCSandbox, error)
StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, error)
StatusSandbox(ctx context.Context, sandboxID string) (SandboxStatus, error) StatusSandbox(ctx context.Context, sandboxID string) (SandboxStatus, error)
StopSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) StopSandbox(ctx context.Context, sandboxID string, force bool) (VCSandbox, error)
CreateContainer(ctx context.Context, sandboxID string, containerConfig ContainerConfig) (VCSandbox, VCContainer, error) CreateContainer(ctx context.Context, sandboxID string, containerConfig ContainerConfig) (VCSandbox, VCContainer, error)
DeleteContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) DeleteContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error)
@ -68,7 +68,7 @@ type VCSandbox interface {
SetAnnotations(annotations map[string]string) error SetAnnotations(annotations map[string]string) error
Start() error Start() error
Stop() error Stop(force bool) error
Pause() error Pause() error
Resume() error Resume() error
Release() error Release() error

View File

@ -74,7 +74,7 @@ func (s *Sandbox) Start() error {
} }
// Stop implements the VCSandbox function of the same name. // Stop implements the VCSandbox function of the same name.
func (s *Sandbox) Stop() error { func (s *Sandbox) Stop(force bool) error {
return nil return nil
} }

View File

@ -1161,7 +1161,7 @@ func (s *Sandbox) StopContainer(containerID string) (VCContainer, error) {
} }
// Stop it. // Stop it.
if err := c.stop(); err != nil { if err := c.stop(false); err != nil {
return nil, err return nil, err
} }
@ -1427,7 +1427,8 @@ func (s *Sandbox) Start() error {
// Stop stops a sandbox. The containers that are making the sandbox // Stop stops a sandbox. The containers that are making the sandbox
// will be destroyed. // will be destroyed.
func (s *Sandbox) Stop() error { // When force is true, ignore guest related stop failures.
func (s *Sandbox) Stop(force bool) error {
span, _ := s.trace("stop") span, _ := s.trace("stop")
defer span.Finish() defer span.Finish()
@ -1441,12 +1442,12 @@ func (s *Sandbox) Stop() error {
} }
for _, c := range s.containers { for _, c := range s.containers {
if err := c.stop(); err != nil { if err := c.stop(force); err != nil {
return err return err
} }
} }
if err := s.stopVM(); err != nil { if err := s.stopVM(); err != nil && !force {
return err return err
} }
@ -1455,7 +1456,7 @@ func (s *Sandbox) Stop() error {
} }
// Remove the network. // Remove the network.
if err := s.removeNetwork(); err != nil { if err := s.removeNetwork(); err != nil && !force {
return err return err
} }

View File

@ -1350,7 +1350,7 @@ func TestSandboxStopStopped(t *testing.T) {
ctx: context.Background(), ctx: context.Background(),
state: types.SandboxState{State: types.StateStopped}, state: types.SandboxState{State: types.StateStopped},
} }
err := s.Stop() err := s.Stop(false)
assert.Nil(t, err) assert.Nil(t, err)
} }