mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-09-28 20:15:51 +00:00
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>
190 lines
4.5 KiB
Go
190 lines
4.5 KiB
Go
// Copyright (c) 2014,2015,2016 Docker, Inc.
|
|
// Copyright (c) 2017 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/kata-containers/runtime/pkg/katautils"
|
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
|
vcAnnot "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
|
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
var deleteCLICommand = cli.Command{
|
|
Name: "delete",
|
|
Usage: "Delete any resources held by one or more containers",
|
|
ArgsUsage: `<container-id> [container-id...]
|
|
|
|
<container-id> is the name for the instance of the container.
|
|
|
|
EXAMPLE:
|
|
If the container id is "ubuntu01" and ` + name + ` list currently shows the
|
|
status of "ubuntu01" as "stopped" the following will delete resources held
|
|
for "ubuntu01" removing "ubuntu01" from the ` + name + ` list of containers:
|
|
|
|
# ` + name + ` delete ubuntu01`,
|
|
Flags: []cli.Flag{
|
|
cli.BoolFlag{
|
|
Name: "force, f",
|
|
Usage: "Forcibly deletes the container if it is still running (uses SIGKILL)",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
ctx, err := cliContextToContext(context)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
args := context.Args()
|
|
if !args.Present() {
|
|
return fmt.Errorf("Missing container ID, should at least provide one")
|
|
}
|
|
|
|
force := context.Bool("force")
|
|
for _, cID := range []string(args) {
|
|
if err := delete(ctx, cID, force); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func delete(ctx context.Context, containerID string, force bool) error {
|
|
span, ctx := katautils.Trace(ctx, "delete")
|
|
defer span.Finish()
|
|
|
|
kataLog = kataLog.WithField("container", containerID)
|
|
setExternalLoggers(ctx, kataLog)
|
|
span.SetTag("container", containerID)
|
|
|
|
// Checks the MUST and MUST NOT from OCI runtime specification
|
|
status, sandboxID, err := getExistingContainerInfo(ctx, containerID)
|
|
if err != nil {
|
|
if force {
|
|
kataLog.Warnf("Failed to get container, force will not fail: %s", err)
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
containerID = status.ID
|
|
|
|
kataLog = kataLog.WithFields(logrus.Fields{
|
|
"container": containerID,
|
|
"sandbox": sandboxID,
|
|
})
|
|
|
|
setExternalLoggers(ctx, kataLog)
|
|
|
|
span.SetTag("container", containerID)
|
|
span.SetTag("sandbox", sandboxID)
|
|
|
|
containerType, err := oci.GetContainerType(status.Annotations)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Retrieve OCI spec configuration.
|
|
ociSpec, err := oci.GetOCIConfig(status)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
forceStop := false
|
|
if oci.StateToOCIState(status.State.State) == oci.StateRunning {
|
|
if !force {
|
|
return fmt.Errorf("Container still running, should be stopped")
|
|
}
|
|
|
|
forceStop = true
|
|
}
|
|
|
|
switch containerType {
|
|
case vc.PodSandbox:
|
|
if err := deleteSandbox(ctx, sandboxID, force); err != nil {
|
|
return err
|
|
}
|
|
case vc.PodContainer:
|
|
if err := deleteContainer(ctx, sandboxID, containerID, forceStop); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return fmt.Errorf("Invalid container type found")
|
|
}
|
|
|
|
// Run post-stop OCI hooks.
|
|
if err := katautils.PostStopHooks(ctx, ociSpec, sandboxID, status.Annotations[vcAnnot.BundlePathKey]); err != nil {
|
|
return err
|
|
}
|
|
|
|
return katautils.DelContainerIDMapping(ctx, containerID)
|
|
}
|
|
|
|
func deleteSandbox(ctx context.Context, sandboxID string, force bool) error {
|
|
span, _ := katautils.Trace(ctx, "deleteSandbox")
|
|
defer span.Finish()
|
|
|
|
status, err := vci.StatusSandbox(ctx, sandboxID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if oci.StateToOCIState(status.State.State) != oci.StateStopped {
|
|
if _, err := vci.StopSandbox(ctx, sandboxID, force); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if _, err := vci.DeleteSandbox(ctx, sandboxID); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func deleteContainer(ctx context.Context, sandboxID, containerID string, forceStop bool) error {
|
|
span, _ := katautils.Trace(ctx, "deleteContainer")
|
|
defer span.Finish()
|
|
|
|
if forceStop {
|
|
if _, err := vci.StopContainer(ctx, sandboxID, containerID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if _, err := vci.DeleteContainer(ctx, sandboxID, containerID); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func removeCgroupsPath(ctx context.Context, containerID string, cgroupsPathList []string) error {
|
|
span, _ := katautils.Trace(ctx, "removeCgroupsPath")
|
|
defer span.Finish()
|
|
|
|
if len(cgroupsPathList) == 0 {
|
|
kataLog.WithField("container", containerID).Info("Cgroups files not removed because cgroupsPath was empty")
|
|
return nil
|
|
}
|
|
|
|
for _, cgroupsPath := range cgroupsPathList {
|
|
if err := os.RemoveAll(cgroupsPath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|