2016-07-08 19:04:00 +00:00
|
|
|
package server
|
|
|
|
|
2016-07-29 22:35:10 +00:00
|
|
|
import (
|
2016-09-18 14:35:17 +00:00
|
|
|
"encoding/json"
|
2016-08-01 23:50:45 +00:00
|
|
|
"fmt"
|
2016-09-18 14:35:17 +00:00
|
|
|
"io/ioutil"
|
2017-06-03 16:17:57 +00:00
|
|
|
"net"
|
2017-08-03 00:23:08 +00:00
|
|
|
"net/http"
|
2016-08-04 14:34:30 +00:00
|
|
|
"os"
|
2017-08-13 01:35:55 +00:00
|
|
|
"path/filepath"
|
2017-08-23 17:35:06 +00:00
|
|
|
"runtime/debug"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2016-09-17 14:10:35 +00:00
|
|
|
"sync"
|
2016-08-01 23:50:45 +00:00
|
|
|
|
2017-09-05 20:10:42 +00:00
|
|
|
"github.com/cri-o/ocicni/pkg/ocicni"
|
2017-08-13 01:35:55 +00:00
|
|
|
"github.com/fsnotify/fsnotify"
|
2017-07-17 12:25:32 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/libkpod"
|
2017-07-19 19:03:22 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/libkpod/sandbox"
|
2016-09-26 23:55:12 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/oci"
|
2016-10-18 14:48:33 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/pkg/storage"
|
2016-11-29 12:34:15 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/server/apparmor"
|
2016-11-23 09:41:48 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/server/seccomp"
|
2017-08-02 15:17:45 +00:00
|
|
|
"github.com/pkg/errors"
|
2017-08-03 00:23:08 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2017-08-05 11:40:46 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2017-06-03 16:17:57 +00:00
|
|
|
knet "k8s.io/apimachinery/pkg/util/net"
|
2017-08-04 11:13:19 +00:00
|
|
|
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
2017-06-15 20:56:17 +00:00
|
|
|
"k8s.io/kubernetes/pkg/kubelet/network/hostport"
|
2017-02-08 13:56:20 +00:00
|
|
|
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
2017-06-16 21:22:20 +00:00
|
|
|
iptablesproxy "k8s.io/kubernetes/pkg/proxy/iptables"
|
|
|
|
utildbus "k8s.io/kubernetes/pkg/util/dbus"
|
|
|
|
utilexec "k8s.io/kubernetes/pkg/util/exec"
|
|
|
|
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
|
2016-07-29 22:35:10 +00:00
|
|
|
)
|
|
|
|
|
2016-07-19 18:53:57 +00:00
|
|
|
const (
|
|
|
|
runtimeAPIVersion = "v1alpha1"
|
2017-05-12 13:36:15 +00:00
|
|
|
shutdownFile = "/var/lib/crio/crio.shutdown"
|
2016-07-08 19:04:00 +00:00
|
|
|
)
|
|
|
|
|
2017-06-08 20:08:29 +00:00
|
|
|
func isTrue(annotaton string) bool {
|
|
|
|
return annotaton == "true"
|
|
|
|
}
|
|
|
|
|
2017-02-08 13:56:20 +00:00
|
|
|
// streamService implements streaming.Runtime.
|
|
|
|
type streamService struct {
|
2017-09-06 14:02:05 +00:00
|
|
|
runtimeServer *Server // needed by Exec() endpoint
|
|
|
|
streamServer streaming.Server
|
|
|
|
streamServerCloseCh chan struct{}
|
2017-02-08 13:56:20 +00:00
|
|
|
streaming.Runtime
|
|
|
|
}
|
|
|
|
|
2016-07-19 18:53:57 +00:00
|
|
|
// Server implements the RuntimeService and ImageService
|
|
|
|
type Server struct {
|
2017-07-31 18:38:45 +00:00
|
|
|
*libkpod.ContainerServer
|
2017-06-16 17:24:00 +00:00
|
|
|
config Config
|
|
|
|
|
2017-07-31 18:38:45 +00:00
|
|
|
updateLock sync.RWMutex
|
|
|
|
netPlugin ocicni.CNIPlugin
|
|
|
|
hostportManager hostport.HostPortManager
|
2016-11-23 09:41:48 +00:00
|
|
|
|
|
|
|
seccompEnabled bool
|
|
|
|
seccompProfile seccomp.Seccomp
|
2016-11-29 12:34:15 +00:00
|
|
|
|
|
|
|
appArmorEnabled bool
|
2016-11-30 08:19:36 +00:00
|
|
|
appArmorProfile string
|
2017-02-08 13:56:20 +00:00
|
|
|
|
2017-09-06 14:02:05 +00:00
|
|
|
bindAddress string
|
|
|
|
stream streamService
|
|
|
|
exitMonitorChan chan struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// StopStreamServer stops the stream server
|
|
|
|
func (s *Server) StopStreamServer() error {
|
|
|
|
return s.stream.streamServer.Stop()
|
|
|
|
}
|
2017-08-29 23:00:49 +00:00
|
|
|
|
2017-09-06 14:02:05 +00:00
|
|
|
// StreamingServerCloseChan returns the close channel for the streaming server
|
|
|
|
func (s *Server) StreamingServerCloseChan() chan struct{} {
|
|
|
|
return s.stream.streamServerCloseCh
|
2016-07-08 19:04:00 +00:00
|
|
|
}
|
|
|
|
|
2017-02-08 14:11:52 +00:00
|
|
|
// GetExec returns exec stream request
|
|
|
|
func (s *Server) GetExec(req *pb.ExecRequest) (*pb.ExecResponse, error) {
|
|
|
|
return s.stream.streamServer.GetExec(req)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetAttach returns attach stream request
|
|
|
|
func (s *Server) GetAttach(req *pb.AttachRequest) (*pb.AttachResponse, error) {
|
|
|
|
return s.stream.streamServer.GetAttach(req)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPortForward returns port forward stream request
|
|
|
|
func (s *Server) GetPortForward(req *pb.PortForwardRequest) (*pb.PortForwardResponse, error) {
|
|
|
|
return s.stream.streamServer.GetPortForward(req)
|
|
|
|
}
|
|
|
|
|
2016-10-07 14:20:04 +00:00
|
|
|
func (s *Server) restore() {
|
2017-07-17 12:25:32 +00:00
|
|
|
containers, err := s.Store().Containers()
|
2017-08-02 15:17:45 +00:00
|
|
|
if err != nil && !os.IsNotExist(errors.Cause(err)) {
|
2016-10-18 14:48:33 +00:00
|
|
|
logrus.Warnf("could not read containers and sandboxes: %v", err)
|
|
|
|
}
|
|
|
|
pods := map[string]*storage.RuntimeContainerMetadata{}
|
|
|
|
podContainers := map[string]*storage.RuntimeContainerMetadata{}
|
|
|
|
for _, container := range containers {
|
2017-07-31 18:38:45 +00:00
|
|
|
metadata, err2 := s.StorageRuntimeServer().GetContainerMetadata(container.ID)
|
2016-10-18 14:48:33 +00:00
|
|
|
if err2 != nil {
|
|
|
|
logrus.Warnf("error parsing metadata for %s: %v, ignoring", container.ID, err2)
|
2016-10-07 14:20:04 +00:00
|
|
|
continue
|
|
|
|
}
|
2016-10-18 14:48:33 +00:00
|
|
|
if metadata.Pod {
|
|
|
|
pods[container.ID] = &metadata
|
|
|
|
} else {
|
|
|
|
podContainers[container.ID] = &metadata
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for containerID, metadata := range pods {
|
2017-07-31 18:38:45 +00:00
|
|
|
if err = s.LoadSandbox(containerID); err != nil {
|
2016-10-18 14:48:33 +00:00
|
|
|
logrus.Warnf("could not restore sandbox %s container %s: %v", metadata.PodID, containerID, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for containerID := range podContainers {
|
2017-07-31 18:38:45 +00:00
|
|
|
if err := s.LoadContainer(containerID); err != nil {
|
2016-10-18 14:48:33 +00:00
|
|
|
logrus.Warnf("could not restore container %s: %v", containerID, err)
|
2016-10-07 14:20:04 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-18 14:48:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update makes changes to the server's state (lists of pods and containers) to
|
|
|
|
// reflect the list of pods and containers that are stored on disk, possibly
|
|
|
|
// having been modified by other parties
|
|
|
|
func (s *Server) Update() {
|
|
|
|
logrus.Debugf("updating sandbox and container information")
|
2017-07-31 18:38:45 +00:00
|
|
|
if err := s.ContainerServer.Update(); err != nil {
|
2016-10-18 14:48:33 +00:00
|
|
|
logrus.Errorf("error updating sandbox and container information: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-14 18:19:18 +00:00
|
|
|
// cleanupSandboxesOnShutdown Remove all running Sandboxes on system shutdown
|
|
|
|
func (s *Server) cleanupSandboxesOnShutdown() {
|
|
|
|
_, err := os.Stat(shutdownFile)
|
|
|
|
if err == nil || !os.IsNotExist(err) {
|
|
|
|
logrus.Debugf("shutting down all sandboxes, on shutdown")
|
2017-05-15 10:12:29 +00:00
|
|
|
s.StopAllPodSandboxes()
|
2017-03-14 18:19:18 +00:00
|
|
|
err = os.Remove(shutdownFile)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warnf("Failed to remove %q", shutdownFile)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-18 14:48:33 +00:00
|
|
|
// Shutdown attempts to shut down the server's storage cleanly
|
|
|
|
func (s *Server) Shutdown() error {
|
2017-07-11 23:19:18 +00:00
|
|
|
// why do this on clean shutdown! we want containers left running when crio
|
2017-05-15 13:50:41 +00:00
|
|
|
// is down for whatever reason no?!
|
|
|
|
// notice this won't trigger just on system halt but also on normal
|
2017-07-11 23:19:18 +00:00
|
|
|
// crio.service restart!!!
|
2017-03-14 18:19:18 +00:00
|
|
|
s.cleanupSandboxesOnShutdown()
|
2017-07-20 19:43:01 +00:00
|
|
|
return s.ContainerServer.Shutdown()
|
2016-10-18 14:48:33 +00:00
|
|
|
}
|
|
|
|
|
2017-08-23 17:35:06 +00:00
|
|
|
// configureMaxThreads sets the Go runtime max threads threshold
|
|
|
|
// which is 90% of the kernel setting from /proc/sys/kernel/threads-max
|
|
|
|
func configureMaxThreads() error {
|
|
|
|
mt, err := ioutil.ReadFile("/proc/sys/kernel/threads-max")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
mtint, err := strconv.Atoi(strings.TrimSpace(string(mt)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
maxThreads := (mtint / 100) * 90
|
|
|
|
debug.SetMaxThreads(maxThreads)
|
|
|
|
logrus.Debugf("Golang's threads limit set to %d", maxThreads)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-07-19 18:53:57 +00:00
|
|
|
// New creates a new Server with options provided
|
2016-10-10 09:57:40 +00:00
|
|
|
func New(config *Config) (*Server, error) {
|
2017-05-30 21:35:12 +00:00
|
|
|
if err := os.MkdirAll("/var/run/crio", 0755); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-08-13 01:35:55 +00:00
|
|
|
|
2017-10-02 13:38:55 +00:00
|
|
|
config.ContainerExitsDir = oci.ContainerExitsDir
|
2017-08-13 01:35:55 +00:00
|
|
|
|
|
|
|
// This is used to monitor container exits using inotify
|
|
|
|
if err := os.MkdirAll(config.ContainerExitsDir, 0755); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-07-25 19:16:43 +00:00
|
|
|
containerServer, err := libkpod.New(&config.Config)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-07-20 18:53:40 +00:00
|
|
|
|
2017-01-24 17:12:51 +00:00
|
|
|
netPlugin, err := ocicni.InitCNI(config.NetworkDir, config.PluginDir)
|
2016-09-02 19:38:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-06-16 21:22:20 +00:00
|
|
|
iptInterface := utiliptables.New(utilexec.New(), utildbus.New(), utiliptables.ProtocolIpv4)
|
|
|
|
iptInterface.EnsureChain(utiliptables.TableNAT, iptablesproxy.KubeMarkMasqChain)
|
2017-06-15 20:56:17 +00:00
|
|
|
hostportManager := hostport.NewHostportManager()
|
2017-07-17 12:25:32 +00:00
|
|
|
|
2016-09-18 14:35:17 +00:00
|
|
|
s := &Server{
|
2017-07-31 18:38:45 +00:00
|
|
|
ContainerServer: containerServer,
|
|
|
|
|
|
|
|
netPlugin: netPlugin,
|
|
|
|
hostportManager: hostportManager,
|
|
|
|
config: *config,
|
|
|
|
seccompEnabled: seccomp.IsEnabled(),
|
|
|
|
appArmorEnabled: apparmor.IsEnabled(),
|
|
|
|
appArmorProfile: config.ApparmorProfile,
|
2017-09-06 14:02:05 +00:00
|
|
|
exitMonitorChan: make(chan struct{}),
|
2016-11-23 09:41:48 +00:00
|
|
|
}
|
2017-07-20 18:43:41 +00:00
|
|
|
|
2017-02-22 00:21:04 +00:00
|
|
|
if s.seccompEnabled {
|
2017-03-27 10:02:26 +00:00
|
|
|
seccompProfile, fileErr := ioutil.ReadFile(config.SeccompProfile)
|
|
|
|
if fileErr != nil {
|
|
|
|
return nil, fmt.Errorf("opening seccomp profile (%s) failed: %v", config.SeccompProfile, fileErr)
|
2017-02-22 00:21:04 +00:00
|
|
|
}
|
|
|
|
var seccompConfig seccomp.Seccomp
|
2017-03-27 10:02:26 +00:00
|
|
|
if jsonErr := json.Unmarshal(seccompProfile, &seccompConfig); jsonErr != nil {
|
|
|
|
return nil, fmt.Errorf("decoding seccomp profile failed: %v", jsonErr)
|
2017-02-22 00:21:04 +00:00
|
|
|
}
|
|
|
|
s.seccompProfile = seccompConfig
|
2016-09-18 14:35:17 +00:00
|
|
|
}
|
2016-10-04 23:00:04 +00:00
|
|
|
|
2016-12-12 07:55:17 +00:00
|
|
|
if s.appArmorEnabled && s.appArmorProfile == apparmor.DefaultApparmorProfile {
|
2017-03-27 10:02:26 +00:00
|
|
|
if apparmorErr := apparmor.EnsureDefaultApparmorProfile(); apparmorErr != nil {
|
|
|
|
return nil, fmt.Errorf("ensuring the default apparmor profile is installed failed: %v", apparmorErr)
|
2016-12-12 07:55:17 +00:00
|
|
|
}
|
2016-11-29 12:34:15 +00:00
|
|
|
}
|
|
|
|
|
2017-08-23 17:35:06 +00:00
|
|
|
if err := configureMaxThreads(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-10-07 14:20:04 +00:00
|
|
|
s.restore()
|
2017-03-14 18:19:18 +00:00
|
|
|
s.cleanupSandboxesOnShutdown()
|
2016-10-07 14:20:04 +00:00
|
|
|
|
2017-06-12 22:31:16 +00:00
|
|
|
bindAddress := net.ParseIP(config.StreamAddress)
|
|
|
|
if bindAddress == nil {
|
|
|
|
bindAddress, err = knet.ChooseBindAddress(net.IP{0, 0, 0, 0})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2017-08-29 23:00:49 +00:00
|
|
|
s.bindAddress = bindAddress.String()
|
2017-06-12 22:31:16 +00:00
|
|
|
|
|
|
|
_, err = net.LookupPort("tcp", config.StreamPort)
|
2017-06-03 16:17:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-02-08 14:09:03 +00:00
|
|
|
// Prepare streaming server
|
|
|
|
streamServerConfig := streaming.DefaultConfig
|
2017-06-12 22:31:16 +00:00
|
|
|
streamServerConfig.Addr = net.JoinHostPort(bindAddress.String(), config.StreamPort)
|
2017-02-08 14:09:03 +00:00
|
|
|
s.stream.runtimeServer = s
|
|
|
|
s.stream.streamServer, err = streaming.NewServer(streamServerConfig, s.stream)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to create streaming server")
|
|
|
|
}
|
|
|
|
|
2017-09-06 14:02:05 +00:00
|
|
|
s.stream.streamServerCloseCh = make(chan struct{})
|
2017-02-08 14:09:03 +00:00
|
|
|
go func() {
|
2017-09-06 14:02:05 +00:00
|
|
|
defer close(s.stream.streamServerCloseCh)
|
|
|
|
if err := s.stream.streamServer.Start(true); err != nil {
|
|
|
|
logrus.Errorf("Failed to start streaming server: %v", err)
|
|
|
|
}
|
2017-02-08 14:09:03 +00:00
|
|
|
}()
|
|
|
|
|
2017-07-25 15:12:53 +00:00
|
|
|
logrus.Debugf("sandboxes: %v", s.ContainerServer.ListSandboxes())
|
2016-09-18 14:35:17 +00:00
|
|
|
return s, nil
|
2016-07-08 19:04:00 +00:00
|
|
|
}
|
2016-07-20 01:30:05 +00:00
|
|
|
|
2017-07-19 19:03:22 +00:00
|
|
|
func (s *Server) addSandbox(sb *sandbox.Sandbox) {
|
2017-07-25 15:12:53 +00:00
|
|
|
s.ContainerServer.AddSandbox(sb)
|
2016-09-17 14:10:35 +00:00
|
|
|
}
|
|
|
|
|
2017-07-19 19:03:22 +00:00
|
|
|
func (s *Server) getSandbox(id string) *sandbox.Sandbox {
|
2017-07-25 15:12:53 +00:00
|
|
|
return s.ContainerServer.GetSandbox(id)
|
2016-08-01 23:05:37 +00:00
|
|
|
}
|
2016-08-01 17:39:42 +00:00
|
|
|
|
2016-09-20 08:27:11 +00:00
|
|
|
func (s *Server) hasSandbox(id string) bool {
|
2017-07-25 15:12:53 +00:00
|
|
|
return s.ContainerServer.HasSandbox(id)
|
2016-08-01 17:39:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 08:40:08 +00:00
|
|
|
func (s *Server) removeSandbox(id string) {
|
2017-07-25 15:12:53 +00:00
|
|
|
s.ContainerServer.RemoveSandbox(id)
|
2016-09-27 08:40:08 +00:00
|
|
|
}
|
|
|
|
|
2016-08-01 17:39:42 +00:00
|
|
|
func (s *Server) addContainer(c *oci.Container) {
|
2017-07-18 15:01:08 +00:00
|
|
|
s.ContainerServer.AddContainer(c)
|
2016-09-17 14:10:35 +00:00
|
|
|
}
|
|
|
|
|
2017-09-01 15:49:08 +00:00
|
|
|
func (s *Server) addInfraContainer(c *oci.Container) {
|
|
|
|
s.ContainerServer.AddInfraContainer(c)
|
|
|
|
}
|
|
|
|
|
2016-10-04 23:50:29 +00:00
|
|
|
func (s *Server) getContainer(id string) *oci.Container {
|
2017-07-25 15:12:53 +00:00
|
|
|
return s.ContainerServer.GetContainer(id)
|
2016-08-01 17:39:42 +00:00
|
|
|
}
|
2016-08-25 19:14:59 +00:00
|
|
|
|
2017-09-01 15:49:08 +00:00
|
|
|
func (s *Server) getInfraContainer(id string) *oci.Container {
|
|
|
|
return s.ContainerServer.GetInfraContainer(id)
|
|
|
|
}
|
|
|
|
|
2017-08-29 23:00:49 +00:00
|
|
|
// BindAddress is used to retrieve host's IP
|
|
|
|
func (s *Server) BindAddress() string {
|
|
|
|
return s.bindAddress
|
|
|
|
}
|
|
|
|
|
server: fix PortForward panic
During "Port forwarding" e2e tests, the following panic happened:
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x64981d]
goroutine 52788 [running]:
panic(0x1830ee0, 0xc4200100c0)
/usr/lib/golang/src/runtime/panic.go:500 +0x1a1
github.com/kubernetes-incubator/cri-o/oci.(*Runtime).UpdateStatus(0xc4202afc00,
0x0, 0x0, 0x0)
/home/amurdaca/go/src/github.com/kubernetes-incubator/cri-o/oci/oci.go:549
+0x7d
github.com/kubernetes-incubator/cri-o/server.streamService.PortForward(0xc42026e000,
0x0, 0x0, 0x0, 0x0, 0xc420d9af40, 0x40, 0xc400000050, 0x7fe660659a28,
0xc4201cd0e0, ...)
```
The issue is `streamService.PortForward` assumed the first argument to
be the sandbox's infra container ID, thus trying to get it from memory
store using `.state.containers.Get`. Since that ID is of the sandbox
itself, it fails to get the container object from memory and panics in
`UpdateStatus`.
Fix it by looking for the sandbox's infra container ID starting from a
sandbox ID.
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
2017-05-28 15:22:46 +00:00
|
|
|
// GetSandboxContainer returns the infra container for a given sandbox
|
|
|
|
func (s *Server) GetSandboxContainer(id string) *oci.Container {
|
2017-07-25 15:12:53 +00:00
|
|
|
return s.ContainerServer.GetSandboxContainer(id)
|
server: fix PortForward panic
During "Port forwarding" e2e tests, the following panic happened:
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x64981d]
goroutine 52788 [running]:
panic(0x1830ee0, 0xc4200100c0)
/usr/lib/golang/src/runtime/panic.go:500 +0x1a1
github.com/kubernetes-incubator/cri-o/oci.(*Runtime).UpdateStatus(0xc4202afc00,
0x0, 0x0, 0x0)
/home/amurdaca/go/src/github.com/kubernetes-incubator/cri-o/oci/oci.go:549
+0x7d
github.com/kubernetes-incubator/cri-o/server.streamService.PortForward(0xc42026e000,
0x0, 0x0, 0x0, 0x0, 0xc420d9af40, 0x40, 0xc400000050, 0x7fe660659a28,
0xc4201cd0e0, ...)
```
The issue is `streamService.PortForward` assumed the first argument to
be the sandbox's infra container ID, thus trying to get it from memory
store using `.state.containers.Get`. Since that ID is of the sandbox
itself, it fails to get the container object from memory and panics in
`UpdateStatus`.
Fix it by looking for the sandbox's infra container ID starting from a
sandbox ID.
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
2017-05-28 15:22:46 +00:00
|
|
|
}
|
|
|
|
|
2017-05-29 11:16:27 +00:00
|
|
|
// GetContainer returns a container by its ID
|
|
|
|
func (s *Server) GetContainer(id string) *oci.Container {
|
|
|
|
return s.getContainer(id)
|
|
|
|
}
|
|
|
|
|
2016-08-25 19:14:59 +00:00
|
|
|
func (s *Server) removeContainer(c *oci.Container) {
|
2017-07-18 15:01:08 +00:00
|
|
|
s.ContainerServer.RemoveContainer(c)
|
2016-08-25 19:14:59 +00:00
|
|
|
}
|
2017-07-19 19:03:22 +00:00
|
|
|
|
2017-09-01 15:49:08 +00:00
|
|
|
func (s *Server) removeInfraContainer(c *oci.Container) {
|
|
|
|
s.ContainerServer.RemoveInfraContainer(c)
|
|
|
|
}
|
|
|
|
|
2017-07-19 19:03:22 +00:00
|
|
|
func (s *Server) getPodSandboxFromRequest(podSandboxID string) (*sandbox.Sandbox, error) {
|
|
|
|
if podSandboxID == "" {
|
|
|
|
return nil, sandbox.ErrIDEmpty
|
|
|
|
}
|
|
|
|
|
2017-07-25 15:36:33 +00:00
|
|
|
sandboxID, err := s.PodIDIndex().Get(podSandboxID)
|
2017-07-19 19:03:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("PodSandbox with ID starting with %s not found: %v", podSandboxID, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sb := s.getSandbox(sandboxID)
|
|
|
|
if sb == nil {
|
|
|
|
return nil, fmt.Errorf("specified pod sandbox not found: %s", sandboxID)
|
|
|
|
}
|
|
|
|
return sb, nil
|
|
|
|
}
|
2017-08-03 00:23:08 +00:00
|
|
|
|
|
|
|
// CreateMetricsEndpoint creates a /metrics endpoint
|
|
|
|
// for prometheus monitoring
|
|
|
|
func (s *Server) CreateMetricsEndpoint() (*http.ServeMux, error) {
|
|
|
|
mux := &http.ServeMux{}
|
|
|
|
mux.Handle("/metrics", prometheus.Handler())
|
|
|
|
return mux, nil
|
|
|
|
}
|
2017-08-13 01:35:55 +00:00
|
|
|
|
2017-09-06 14:02:05 +00:00
|
|
|
// StopExitMonitor stops the exit monitor
|
|
|
|
func (s *Server) StopExitMonitor() {
|
|
|
|
close(s.exitMonitorChan)
|
|
|
|
}
|
|
|
|
|
2017-09-06 15:04:18 +00:00
|
|
|
// ExitMonitorCloseChan returns the close chan for the exit monitor
|
2017-09-06 14:02:05 +00:00
|
|
|
func (s *Server) ExitMonitorCloseChan() chan struct{} {
|
|
|
|
return s.exitMonitorChan
|
|
|
|
}
|
|
|
|
|
2017-08-13 01:35:55 +00:00
|
|
|
// StartExitMonitor start a routine that monitors container exits
|
|
|
|
// and updates the container status
|
|
|
|
func (s *Server) StartExitMonitor() {
|
|
|
|
watcher, err := fsnotify.NewWatcher()
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatalf("Failed to create new watch: %v", err)
|
|
|
|
}
|
|
|
|
defer watcher.Close()
|
|
|
|
|
2017-09-06 14:02:05 +00:00
|
|
|
done := make(chan struct{})
|
2017-08-13 01:35:55 +00:00
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case event := <-watcher.Events:
|
|
|
|
logrus.Debugf("event: %v", event)
|
|
|
|
if event.Op&fsnotify.Create == fsnotify.Create {
|
|
|
|
containerID := filepath.Base(event.Name)
|
2017-08-14 23:33:10 +00:00
|
|
|
logrus.Debugf("container or sandbox exited: %v", containerID)
|
2017-08-13 01:35:55 +00:00
|
|
|
c := s.GetContainer(containerID)
|
|
|
|
if c != nil {
|
2017-08-14 23:33:10 +00:00
|
|
|
logrus.Debugf("container exited and found: %v", containerID)
|
2017-08-13 01:35:55 +00:00
|
|
|
err := s.Runtime().UpdateStatus(c)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warnf("Failed to update container status %s: %v", c, err)
|
|
|
|
} else {
|
|
|
|
s.ContainerStateToDisk(c)
|
|
|
|
}
|
2017-08-14 23:33:10 +00:00
|
|
|
} else {
|
|
|
|
sb := s.GetSandbox(containerID)
|
|
|
|
if sb != nil {
|
|
|
|
c := sb.InfraContainer()
|
|
|
|
logrus.Debugf("sandbox exited and found: %v", containerID)
|
|
|
|
err := s.Runtime().UpdateStatus(c)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warnf("Failed to update sandbox infra container status %s: %v", c, err)
|
|
|
|
} else {
|
|
|
|
s.ContainerStateToDisk(c)
|
|
|
|
}
|
|
|
|
}
|
2017-08-13 01:35:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case err := <-watcher.Errors:
|
|
|
|
logrus.Debugf("watch error: %v", err)
|
2017-09-06 14:02:05 +00:00
|
|
|
close(done)
|
|
|
|
return
|
|
|
|
case <-s.exitMonitorChan:
|
|
|
|
logrus.Debug("closing exit monitor...")
|
|
|
|
close(done)
|
|
|
|
return
|
2017-08-13 01:35:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
if err := watcher.Add(s.config.ContainerExitsDir); err != nil {
|
2017-09-06 14:02:05 +00:00
|
|
|
logrus.Errorf("watcher.Add(%q) failed: %s", s.config.ContainerExitsDir, err)
|
2017-08-13 01:35:55 +00:00
|
|
|
}
|
|
|
|
<-done
|
|
|
|
}
|