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 {
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
}
}

View File

@ -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:

View File

@ -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

View File

@ -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")
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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
}

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.
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.

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}