diff --git a/cli/delete.go b/cli/delete.go index 19dc4fb7a2..c2ce52a468 100644 --- a/cli/delete.go +++ b/cli/delete.go @@ -112,7 +112,7 @@ func delete(ctx context.Context, containerID string, force bool) error { switch containerType { case vc.PodSandbox: - if err := deleteSandbox(ctx, sandboxID); err != nil { + if err := deleteSandbox(ctx, sandboxID, force); err != nil { return err } case vc.PodContainer: @@ -131,7 +131,7 @@ func delete(ctx context.Context, containerID string, force bool) error { 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") defer span.Finish() @@ -141,7 +141,7 @@ func deleteSandbox(ctx context.Context, sandboxID string) error { } 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 } } diff --git a/cli/kill.go b/cli/kill.go index 4c93ecf02f..60fa41e09e 100644 --- a/cli/kill.go +++ b/cli/kill.go @@ -152,7 +152,7 @@ func kill(ctx context.Context, containerID, signal string, all bool) error { switch containerType { case vc.PodSandbox: - _, err = vci.StopSandbox(ctx, sandboxID) + _, err = vci.StopSandbox(ctx, sandboxID, signum == syscall.SIGKILL) case vc.PodContainer: _, err = vci.StopContainer(ctx, sandboxID, containerID) default: diff --git a/containerd-shim-v2/utils.go b/containerd-shim-v2/utils.go index b704b17454..c9c7a15b5e 100644 --- a/containerd-shim-v2/utils.go +++ b/containerd-shim-v2/utils.go @@ -70,7 +70,7 @@ func cleanupContainer(ctx context.Context, sid, cid, bundlePath string) error { } if len(sandbox.GetAllContainers()) == 0 { - err = sandbox.Stop() + err = sandbox.Stop(true) if err != nil { logrus.WithError(err).WithField("sandbox", sid).Warn("failed to stop sandbox") return err diff --git a/containerd-shim-v2/wait.go b/containerd-shim-v2/wait.go index d36408dd5b..92cf23963b 100644 --- a/containerd-shim-v2/wait.go +++ b/containerd-shim-v2/wait.go @@ -51,7 +51,7 @@ func wait(s *service, c *container, execID string) (int32, error) { // sandbox. 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") } diff --git a/virtcontainers/api.go b/virtcontainers/api.go index 8605b978f4..76c2a96190 100644 --- a/virtcontainers/api.go +++ b/virtcontainers/api.go @@ -235,7 +235,7 @@ func StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { // 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. -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") defer span.Finish() @@ -257,7 +257,7 @@ func StopSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { defer s.releaseStatelessSandbox() // Stop it. - err = s.Stop() + err = s.Stop(force) if err != nil { return nil, err } @@ -596,7 +596,7 @@ func statusContainer(sandbox *Sandbox, containerID string) (ContainerStatus, err "state": container.state.State, "pid": container.process.Pid}). Info("container isn't running") - if err := container.stop(); err != nil { + if err := container.stop(true); err != nil { return ContainerStatus{}, err } } diff --git a/virtcontainers/api_test.go b/virtcontainers/api_test.go index 371900800d..68a2bc8803 100644 --- a/virtcontainers/api_test.go +++ b/virtcontainers/api_test.go @@ -332,7 +332,7 @@ func TestStopSandboxNoopAgentSuccessful(t *testing.T) { assert.NoError(err) assert.NotNil(p) - vp, err := StopSandbox(ctx, p.ID()) + vp, err := StopSandbox(ctx, p.ID(), false) assert.NoError(err) assert.NotNil(vp) } @@ -427,7 +427,7 @@ func TestStopSandboxKataAgentSuccessful(t *testing.T) { assert.NoError(err) assert.NotNil(p) - p, err = StopSandbox(ctx, p.ID()) + p, err = StopSandbox(ctx, p.ID(), false) assert.NoError(err) assert.NotNil(p) } @@ -438,7 +438,7 @@ func TestStopSandboxFailing(t *testing.T) { sandboxDir := store.SandboxConfigurationRootPath(testSandboxID) os.Remove(sandboxDir) - p, err := StopSandbox(context.Background(), testSandboxID) + p, err := StopSandbox(context.Background(), testSandboxID, false) assert.Error(t, err) assert.Nil(t, p) } @@ -1461,7 +1461,7 @@ func createStartStopDeleteSandbox(b *testing.B, sandboxConfig SandboxConfig) { } // Stop sandbox - _, err = StopSandbox(ctx, p.ID()) + _, err = StopSandbox(ctx, p.ID(), false) if err != nil { b.Fatalf("Could not stop sandbox: %s", err) } diff --git a/virtcontainers/container.go b/virtcontainers/container.go index a8e7dc91c4..4b25a0a472 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -946,7 +946,7 @@ func (c *Container) start() error { if err := c.sandbox.agent.startContainer(c.sandbox, c); err != nil { 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") } return err @@ -955,7 +955,7 @@ func (c *Container) start() error { return c.setContainerState(types.StateRunning) } -func (c *Container) stop() error { +func (c *Container) stop(force bool) error { span, _ := c.trace("stop") defer span.Finish() @@ -999,7 +999,7 @@ func (c *Container) stop() error { // return an error, but instead try to kill it forcefully. if err := waitForShim(c.process.Pid); err != nil { // 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 } @@ -1007,7 +1007,7 @@ func (c *Container) stop() error { // to succeed. Indeed, we have already given a second chance // to the container by trying to kill it with SIGKILL, there // 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 } } @@ -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 } - if err := c.detachDevices(); err != nil { + if err := c.detachDevices(); err != nil && !force { return err } - if err := c.removeDrive(); err != nil { + if err := c.removeDrive(); err != nil && !force { return err } diff --git a/virtcontainers/implementation.go b/virtcontainers/implementation.go index 865a84271d..fd91535444 100644 --- a/virtcontainers/implementation.go +++ b/virtcontainers/implementation.go @@ -52,8 +52,8 @@ func (impl *VCImpl) StartSandbox(ctx context.Context, sandboxID string) (VCSandb } // StopSandbox implements the VC function of the same name. -func (impl *VCImpl) StopSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { - return StopSandbox(ctx, sandboxID) +func (impl *VCImpl) StopSandbox(ctx context.Context, sandboxID string, force bool) (VCSandbox, error) { + return StopSandbox(ctx, sandboxID, force) } // RunSandbox implements the VC function of the same name. diff --git a/virtcontainers/interfaces.go b/virtcontainers/interfaces.go index 8ce0e22fa3..38dfc5f4ed 100644 --- a/virtcontainers/interfaces.go +++ b/virtcontainers/interfaces.go @@ -32,7 +32,7 @@ type VC interface { RunSandbox(ctx context.Context, sandboxConfig SandboxConfig) (VCSandbox, error) StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, 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) DeleteContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) @@ -68,7 +68,7 @@ type VCSandbox interface { SetAnnotations(annotations map[string]string) error Start() error - Stop() error + Stop(force bool) error Pause() error Resume() error Release() error diff --git a/virtcontainers/pkg/vcmock/sandbox.go b/virtcontainers/pkg/vcmock/sandbox.go index 2c00d23f82..3d770db8fd 100644 --- a/virtcontainers/pkg/vcmock/sandbox.go +++ b/virtcontainers/pkg/vcmock/sandbox.go @@ -74,7 +74,7 @@ func (s *Sandbox) Start() error { } // Stop implements the VCSandbox function of the same name. -func (s *Sandbox) Stop() error { +func (s *Sandbox) Stop(force bool) error { return nil } diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index 0d43a279d7..fc60c6ab94 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -1161,7 +1161,7 @@ func (s *Sandbox) StopContainer(containerID string) (VCContainer, error) { } // Stop it. - if err := c.stop(); err != nil { + if err := c.stop(false); err != nil { return nil, err } @@ -1427,7 +1427,8 @@ func (s *Sandbox) Start() error { // Stop stops a sandbox. The containers that are making the sandbox // 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") defer span.Finish() @@ -1441,12 +1442,12 @@ func (s *Sandbox) Stop() error { } for _, c := range s.containers { - if err := c.stop(); err != nil { + if err := c.stop(force); err != nil { return err } } - if err := s.stopVM(); err != nil { + if err := s.stopVM(); err != nil && !force { return err } @@ -1455,7 +1456,7 @@ func (s *Sandbox) Stop() error { } // Remove the network. - if err := s.removeNetwork(); err != nil { + if err := s.removeNetwork(); err != nil && !force { return err } diff --git a/virtcontainers/sandbox_test.go b/virtcontainers/sandbox_test.go index df731dcc9b..2450900023 100644 --- a/virtcontainers/sandbox_test.go +++ b/virtcontainers/sandbox_test.go @@ -1350,7 +1350,7 @@ func TestSandboxStopStopped(t *testing.T) { ctx: context.Background(), state: types.SandboxState{State: types.StateStopped}, } - err := s.Stop() + err := s.Stop(false) assert.Nil(t, err) }