cri-o/server/sandbox_stop.go
Nalin Dahyabhai 0b7348b35c Use errors.Cause() when looking at storage errors
The storage library uses github.com/pkg/errors to wrap errors that it
returns from many of its functions, so when passing them to
os.IsNotExist() or comparing them to specific errors defined in the
storage library, unwrap them using errors.Cause().

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-08-03 15:40:54 -04:00

132 lines
4.4 KiB
Go

package server
import (
"fmt"
"os"
"github.com/Sirupsen/logrus"
"github.com/containers/storage"
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/symlink"
"github.com/kubernetes-incubator/cri-o/libkpod/sandbox"
"github.com/kubernetes-incubator/cri-o/oci"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"golang.org/x/net/context"
"golang.org/x/sys/unix"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"k8s.io/kubernetes/pkg/kubelet/network/hostport"
)
// StopPodSandbox stops the sandbox. If there are any running containers in the
// sandbox, they should be force terminated.
func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxRequest) (*pb.StopPodSandboxResponse, error) {
logrus.Debugf("StopPodSandboxRequest %+v", req)
sb, err := s.getPodSandboxFromRequest(req.PodSandboxId)
if err != nil {
if err == sandbox.ErrIDEmpty {
return nil, err
}
// If the sandbox isn't found we just return an empty response to adhere
// the the CRI interface which expects to not error out in not found
// cases.
resp := &pb.StopPodSandboxResponse{}
logrus.Warnf("could not get sandbox %s, it's probably been stopped already: %v", req.PodSandboxId, err)
return resp, nil
}
podInfraContainer := sb.InfraContainer()
netnsPath, err := podInfraContainer.NetNsPath()
if err != nil {
return nil, err
}
if _, err := os.Stat(netnsPath); err == nil {
if err2 := s.hostportManager.Remove(sb.ID(), &hostport.PodPortMapping{
Name: sb.Name(),
PortMappings: sb.PortMappings(),
HostNetwork: false,
}); err2 != nil {
logrus.Warnf("failed to remove hostport for container %s in sandbox %s: %v",
podInfraContainer.Name(), sb.ID(), err2)
}
if err2 := s.netPlugin.TearDownPod(netnsPath, sb.Namespace(), sb.KubeName(), sb.ID()); err2 != nil {
logrus.Warnf("failed to destroy network for container %s in sandbox %s: %v",
podInfraContainer.Name(), sb.ID(), err2)
}
} else if !os.IsNotExist(err) { // it's ok for netnsPath to *not* exist
return nil, fmt.Errorf("failed to stat netns path for container %s in sandbox %s before tearing down the network: %v",
sb.Name(), sb.ID(), err)
}
// Close the sandbox networking namespace.
if err := sb.NetNsRemove(); err != nil {
return nil, err
}
containers := sb.Containers().List()
containers = append(containers, podInfraContainer)
for _, c := range containers {
if err := s.Runtime().UpdateStatus(c); err != nil {
return nil, err
}
cStatus := s.Runtime().ContainerStatus(c)
if cStatus.Status != oci.ContainerStateStopped {
if err := s.Runtime().StopContainer(c, -1); err != nil {
return nil, fmt.Errorf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err)
}
if c.ID() == podInfraContainer.ID() {
continue
}
if err := s.StorageRuntimeServer().StopContainer(c.ID()); err != nil && errors.Cause(err) != storage.ErrContainerUnknown {
// assume container already umounted
logrus.Warnf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err)
}
}
s.ContainerStateToDisk(c)
}
if err := label.ReleaseLabel(sb.ProcessLabel()); err != nil {
return nil, err
}
// unmount the shm for the pod
if sb.ShmPath() != "/dev/shm" {
// we got namespaces in the form of
// /var/run/containers/storage/overlay-containers/CID/userdata/shm
// but /var/run on most system is symlinked to /run so we first resolve
// the symlink and then try and see if it's mounted
fp, err := symlink.FollowSymlinkInScope(sb.ShmPath(), "/")
if err != nil {
return nil, err
}
if mounted, err := mount.Mounted(fp); err == nil && mounted {
if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil {
return nil, err
}
}
}
if err := s.StorageRuntimeServer().StopContainer(sb.ID()); err != nil && errors.Cause(err) != storage.ErrContainerUnknown {
logrus.Warnf("failed to stop sandbox container in pod sandbox %s: %v", sb.ID(), err)
}
resp := &pb.StopPodSandboxResponse{}
logrus.Debugf("StopPodSandboxResponse: %+v", resp)
return resp, nil
}
// StopAllPodSandboxes removes all pod sandboxes
func (s *Server) StopAllPodSandboxes() {
logrus.Debugf("StopAllPodSandboxes")
for _, sb := range s.ContainerServer.ListSandboxes() {
pod := &pb.StopPodSandboxRequest{
PodSandboxId: sb.ID(),
}
if _, err := s.StopPodSandbox(nil, pod); err != nil {
logrus.Warnf("could not StopPodSandbox %s: %v", sb.ID(), err)
}
}
}