0b7348b35c
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>
132 lines
4.4 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|