mirror of
https://github.com/rancher/os.git
synced 2025-09-01 14:48:55 +00:00
Bump libcompose and sync dependencies
This commit is contained in:
43
vendor/github.com/docker/containerd/supervisor/add_process.go
generated
vendored
43
vendor/github.com/docker/containerd/supervisor/add_process.go
generated
vendored
@@ -1,43 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
"github.com/docker/containerd/specs"
|
||||
)
|
||||
|
||||
type AddProcessTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
PID string
|
||||
Stdout string
|
||||
Stderr string
|
||||
Stdin string
|
||||
ProcessSpec *specs.ProcessSpec
|
||||
StartResponse chan StartResponse
|
||||
}
|
||||
|
||||
func (s *Supervisor) addProcess(t *AddProcessTask) error {
|
||||
start := time.Now()
|
||||
ci, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
process, err := ci.container.Exec(t.PID, *t.ProcessSpec, runtime.NewStdio(t.Stdin, t.Stdout, t.Stderr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.monitorProcess(process); err != nil {
|
||||
return err
|
||||
}
|
||||
ExecProcessTimer.UpdateSince(start)
|
||||
t.StartResponse <- StartResponse{}
|
||||
s.notifySubscribers(Event{
|
||||
Timestamp: time.Now(),
|
||||
Type: StateStartProcess,
|
||||
PID: t.PID,
|
||||
ID: t.ID,
|
||||
})
|
||||
return nil
|
||||
}
|
33
vendor/github.com/docker/containerd/supervisor/checkpoint.go
generated
vendored
33
vendor/github.com/docker/containerd/supervisor/checkpoint.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package supervisor
|
||||
|
||||
import "github.com/docker/containerd/runtime"
|
||||
|
||||
type CreateCheckpointTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
Checkpoint *runtime.Checkpoint
|
||||
}
|
||||
|
||||
func (s *Supervisor) createCheckpoint(t *CreateCheckpointTask) error {
|
||||
i, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
return i.container.Checkpoint(*t.Checkpoint)
|
||||
}
|
||||
|
||||
type DeleteCheckpointTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
Checkpoint *runtime.Checkpoint
|
||||
}
|
||||
|
||||
func (s *Supervisor) deleteCheckpoint(t *DeleteCheckpointTask) error {
|
||||
i, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
return i.container.DeleteCheckpoint(t.Checkpoint.Name)
|
||||
}
|
57
vendor/github.com/docker/containerd/supervisor/create.go
generated
vendored
57
vendor/github.com/docker/containerd/supervisor/create.go
generated
vendored
@@ -1,57 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
type StartTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
BundlePath string
|
||||
Stdout string
|
||||
Stderr string
|
||||
Stdin string
|
||||
StartResponse chan StartResponse
|
||||
Labels []string
|
||||
NoPivotRoot bool
|
||||
Checkpoint *runtime.Checkpoint
|
||||
}
|
||||
|
||||
func (s *Supervisor) start(t *StartTask) error {
|
||||
start := time.Now()
|
||||
container, err := runtime.New(runtime.ContainerOpts{
|
||||
Root: s.stateDir,
|
||||
ID: t.ID,
|
||||
Bundle: t.BundlePath,
|
||||
Runtime: s.runtime,
|
||||
RuntimeArgs: s.runtimeArgs,
|
||||
Shim: s.shim,
|
||||
Labels: t.Labels,
|
||||
NoPivotRoot: t.NoPivotRoot,
|
||||
Timeout: s.timeout,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.containers[t.ID] = &containerInfo{
|
||||
container: container,
|
||||
}
|
||||
ContainersCounter.Inc(1)
|
||||
task := &startTask{
|
||||
Err: t.ErrorCh(),
|
||||
Container: container,
|
||||
StartResponse: t.StartResponse,
|
||||
Stdin: t.Stdin,
|
||||
Stdout: t.Stdout,
|
||||
Stderr: t.Stderr,
|
||||
}
|
||||
if t.Checkpoint != nil {
|
||||
task.Checkpoint = t.Checkpoint.Name
|
||||
}
|
||||
|
||||
s.startTasks <- task
|
||||
ContainerCreateTimer.UpdateSince(start)
|
||||
return errDeferredResponse
|
||||
}
|
8
vendor/github.com/docker/containerd/supervisor/create_solaris.go
generated
vendored
8
vendor/github.com/docker/containerd/supervisor/create_solaris.go
generated
vendored
@@ -1,8 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
type platformStartTask struct {
|
||||
}
|
||||
|
||||
// Checkpoint not supported on Solaris
|
||||
func (task *startTask) setTaskCheckpoint(t *StartTask) {
|
||||
}
|
42
vendor/github.com/docker/containerd/supervisor/delete.go
generated
vendored
42
vendor/github.com/docker/containerd/supervisor/delete.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
type DeleteTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
Status int
|
||||
PID string
|
||||
NoEvent bool
|
||||
}
|
||||
|
||||
func (s *Supervisor) delete(t *DeleteTask) error {
|
||||
if i, ok := s.containers[t.ID]; ok {
|
||||
start := time.Now()
|
||||
if err := s.deleteContainer(i.container); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: deleting container")
|
||||
}
|
||||
if !t.NoEvent {
|
||||
s.notifySubscribers(Event{
|
||||
Type: StateExit,
|
||||
Timestamp: time.Now(),
|
||||
ID: t.ID,
|
||||
Status: t.Status,
|
||||
PID: t.PID,
|
||||
})
|
||||
}
|
||||
ContainersCounter.Dec(1)
|
||||
ContainerDeleteTimer.UpdateSince(start)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Supervisor) deleteContainer(container runtime.Container) error {
|
||||
delete(s.containers, container.ID())
|
||||
return container.Delete()
|
||||
}
|
24
vendor/github.com/docker/containerd/supervisor/errors.go
generated
vendored
24
vendor/github.com/docker/containerd/supervisor/errors.go
generated
vendored
@@ -1,24 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// External errors
|
||||
ErrTaskChanNil = errors.New("containerd: task channel is nil")
|
||||
ErrBundleNotFound = errors.New("containerd: bundle not found")
|
||||
ErrContainerNotFound = errors.New("containerd: container not found")
|
||||
ErrContainerExists = errors.New("containerd: container already exists")
|
||||
ErrProcessNotFound = errors.New("containerd: processs not found for container")
|
||||
ErrUnknownContainerStatus = errors.New("containerd: unknown container status ")
|
||||
ErrUnknownTask = errors.New("containerd: unknown task type")
|
||||
|
||||
// Internal errors
|
||||
errShutdown = errors.New("containerd: supervisor is shutdown")
|
||||
errRootNotAbs = errors.New("containerd: rootfs path is not an absolute path")
|
||||
errNoContainerForPid = errors.New("containerd: pid not registered for any container")
|
||||
// internal error where the handler will defer to another for the final response
|
||||
//
|
||||
// TODO: we could probably do a typed error with another error channel for this to make it
|
||||
// less like magic
|
||||
errDeferredResponse = errors.New("containerd: deferred response")
|
||||
)
|
81
vendor/github.com/docker/containerd/supervisor/exit.go
generated
vendored
81
vendor/github.com/docker/containerd/supervisor/exit.go
generated
vendored
@@ -1,81 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
type ExitTask struct {
|
||||
baseTask
|
||||
Process runtime.Process
|
||||
}
|
||||
|
||||
func (s *Supervisor) exit(t *ExitTask) error {
|
||||
start := time.Now()
|
||||
proc := t.Process
|
||||
status, err := proc.ExitStatus()
|
||||
if err != nil {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"error": err,
|
||||
"pid": proc.ID(),
|
||||
"id": proc.Container().ID(),
|
||||
"systemPid": proc.SystemPid(),
|
||||
}).Error("containerd: get exit status")
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"pid": proc.ID(),
|
||||
"status": status,
|
||||
"id": proc.Container().ID(),
|
||||
"systemPid": proc.SystemPid(),
|
||||
}).Debug("containerd: process exited")
|
||||
|
||||
// if the process is the the init process of the container then
|
||||
// fire a separate event for this process
|
||||
if proc.ID() != runtime.InitProcessID {
|
||||
ne := &ExecExitTask{
|
||||
ID: proc.Container().ID(),
|
||||
PID: proc.ID(),
|
||||
Status: status,
|
||||
Process: proc,
|
||||
}
|
||||
s.SendTask(ne)
|
||||
return nil
|
||||
}
|
||||
container := proc.Container()
|
||||
ne := &DeleteTask{
|
||||
ID: container.ID(),
|
||||
Status: status,
|
||||
PID: proc.ID(),
|
||||
}
|
||||
s.SendTask(ne)
|
||||
|
||||
ExitProcessTimer.UpdateSince(start)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExecExitTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
PID string
|
||||
Status int
|
||||
Process runtime.Process
|
||||
}
|
||||
|
||||
func (s *Supervisor) execExit(t *ExecExitTask) error {
|
||||
container := t.Process.Container()
|
||||
// exec process: we remove this process without notifying the main event loop
|
||||
if err := container.RemoveProcess(t.PID); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: find container for pid")
|
||||
}
|
||||
s.notifySubscribers(Event{
|
||||
Timestamp: time.Now(),
|
||||
ID: t.ID,
|
||||
Type: StateExit,
|
||||
PID: t.PID,
|
||||
Status: t.Status,
|
||||
})
|
||||
return nil
|
||||
}
|
28
vendor/github.com/docker/containerd/supervisor/get_containers.go
generated
vendored
28
vendor/github.com/docker/containerd/supervisor/get_containers.go
generated
vendored
@@ -1,28 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import "github.com/docker/containerd/runtime"
|
||||
|
||||
type GetContainersTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
Containers []runtime.Container
|
||||
}
|
||||
|
||||
func (s *Supervisor) getContainers(t *GetContainersTask) error {
|
||||
|
||||
if t.ID != "" {
|
||||
ci, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
t.Containers = append(t.Containers, ci.container)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ci := range s.containers {
|
||||
t.Containers = append(t.Containers, ci.container)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
25
vendor/github.com/docker/containerd/supervisor/machine.go
generated
vendored
25
vendor/github.com/docker/containerd/supervisor/machine.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
// +build !solaris
|
||||
|
||||
package supervisor
|
||||
|
||||
import "github.com/cloudfoundry/gosigar"
|
||||
|
||||
type Machine struct {
|
||||
Cpus int
|
||||
Memory int64
|
||||
}
|
||||
|
||||
func CollectMachineInformation() (Machine, error) {
|
||||
m := Machine{}
|
||||
cpu := sigar.CpuList{}
|
||||
if err := cpu.Get(); err != nil {
|
||||
return m, err
|
||||
}
|
||||
m.Cpus = len(cpu.List)
|
||||
mem := sigar.Mem{}
|
||||
if err := mem.Get(); err != nil {
|
||||
return m, err
|
||||
}
|
||||
m.Memory = int64(mem.Total / 1024 / 1024)
|
||||
return m, nil
|
||||
}
|
15
vendor/github.com/docker/containerd/supervisor/machine_solaris.go
generated
vendored
15
vendor/github.com/docker/containerd/supervisor/machine_solaris.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Machine struct {
|
||||
Cpus int
|
||||
Memory int64
|
||||
}
|
||||
|
||||
func CollectMachineInformation() (Machine, error) {
|
||||
m := Machine{}
|
||||
return m, errors.New("supervisor CollectMachineInformation not implemented on Solaris")
|
||||
}
|
31
vendor/github.com/docker/containerd/supervisor/metrics.go
generated
vendored
31
vendor/github.com/docker/containerd/supervisor/metrics.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import "github.com/rcrowley/go-metrics"
|
||||
|
||||
var (
|
||||
ContainerCreateTimer = metrics.NewTimer()
|
||||
ContainerDeleteTimer = metrics.NewTimer()
|
||||
ContainerStartTimer = metrics.NewTimer()
|
||||
ContainerStatsTimer = metrics.NewTimer()
|
||||
ContainersCounter = metrics.NewCounter()
|
||||
EventSubscriberCounter = metrics.NewCounter()
|
||||
TasksCounter = metrics.NewCounter()
|
||||
ExecProcessTimer = metrics.NewTimer()
|
||||
ExitProcessTimer = metrics.NewTimer()
|
||||
EpollFdCounter = metrics.NewCounter()
|
||||
)
|
||||
|
||||
func Metrics() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"container-create-time": ContainerCreateTimer,
|
||||
"container-delete-time": ContainerDeleteTimer,
|
||||
"container-start-time": ContainerStartTimer,
|
||||
"container-stats-time": ContainerStatsTimer,
|
||||
"containers": ContainersCounter,
|
||||
"event-subscribers": EventSubscriberCounter,
|
||||
"tasks": TasksCounter,
|
||||
"exec-process-time": ExecProcessTimer,
|
||||
"exit-process-time": ExitProcessTimer,
|
||||
"epoll-fds": EpollFdCounter,
|
||||
}
|
||||
}
|
129
vendor/github.com/docker/containerd/supervisor/monitor_linux.go
generated
vendored
129
vendor/github.com/docker/containerd/supervisor/monitor_linux.go
generated
vendored
@@ -1,129 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/containerd/archutils"
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
func NewMonitor() (*Monitor, error) {
|
||||
m := &Monitor{
|
||||
receivers: make(map[int]interface{}),
|
||||
exits: make(chan runtime.Process, 1024),
|
||||
ooms: make(chan string, 1024),
|
||||
}
|
||||
fd, err := archutils.EpollCreate1(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.epollFd = fd
|
||||
go m.start()
|
||||
return m, nil
|
||||
}
|
||||
|
||||
type Monitor struct {
|
||||
m sync.Mutex
|
||||
receivers map[int]interface{}
|
||||
exits chan runtime.Process
|
||||
ooms chan string
|
||||
epollFd int
|
||||
}
|
||||
|
||||
func (m *Monitor) Exits() chan runtime.Process {
|
||||
return m.exits
|
||||
}
|
||||
|
||||
func (m *Monitor) OOMs() chan string {
|
||||
return m.ooms
|
||||
}
|
||||
|
||||
func (m *Monitor) Monitor(p runtime.Process) error {
|
||||
m.m.Lock()
|
||||
defer m.m.Unlock()
|
||||
fd := p.ExitFD()
|
||||
event := syscall.EpollEvent{
|
||||
Fd: int32(fd),
|
||||
Events: syscall.EPOLLHUP,
|
||||
}
|
||||
if err := archutils.EpollCtl(m.epollFd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
|
||||
return err
|
||||
}
|
||||
EpollFdCounter.Inc(1)
|
||||
m.receivers[fd] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Monitor) MonitorOOM(c runtime.Container) error {
|
||||
m.m.Lock()
|
||||
defer m.m.Unlock()
|
||||
o, err := c.OOM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fd := o.FD()
|
||||
event := syscall.EpollEvent{
|
||||
Fd: int32(fd),
|
||||
Events: syscall.EPOLLHUP | syscall.EPOLLIN,
|
||||
}
|
||||
if err := archutils.EpollCtl(m.epollFd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
|
||||
return err
|
||||
}
|
||||
EpollFdCounter.Inc(1)
|
||||
m.receivers[fd] = o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Close() error {
|
||||
return syscall.Close(m.epollFd)
|
||||
}
|
||||
|
||||
func (m *Monitor) start() {
|
||||
var events [128]syscall.EpollEvent
|
||||
for {
|
||||
n, err := archutils.EpollWait(m.epollFd, events[:], -1)
|
||||
if err != nil {
|
||||
if err == syscall.EINTR {
|
||||
continue
|
||||
}
|
||||
logrus.WithField("error", err).Fatal("containerd: epoll wait")
|
||||
}
|
||||
// process events
|
||||
for i := 0; i < n; i++ {
|
||||
fd := int(events[i].Fd)
|
||||
m.m.Lock()
|
||||
r := m.receivers[fd]
|
||||
switch t := r.(type) {
|
||||
case runtime.Process:
|
||||
if events[i].Events == syscall.EPOLLHUP {
|
||||
delete(m.receivers, fd)
|
||||
if err = syscall.EpollCtl(m.epollFd, syscall.EPOLL_CTL_DEL, fd, &syscall.EpollEvent{
|
||||
Events: syscall.EPOLLHUP,
|
||||
Fd: int32(fd),
|
||||
}); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: epoll remove fd")
|
||||
}
|
||||
if err := t.Close(); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: close process IO")
|
||||
}
|
||||
EpollFdCounter.Dec(1)
|
||||
m.exits <- t
|
||||
}
|
||||
case runtime.OOM:
|
||||
// always flush the event fd
|
||||
t.Flush()
|
||||
if t.Removed() {
|
||||
delete(m.receivers, fd)
|
||||
// epoll will remove the fd from its set after it has been closed
|
||||
t.Close()
|
||||
EpollFdCounter.Dec(1)
|
||||
} else {
|
||||
m.ooms <- t.ContainerID()
|
||||
}
|
||||
}
|
||||
m.m.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
38
vendor/github.com/docker/containerd/supervisor/monitor_solaris.go
generated
vendored
38
vendor/github.com/docker/containerd/supervisor/monitor_solaris.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
func NewMonitor() (*Monitor, error) {
|
||||
return &Monitor{}, errors.New("Monitor NewMonitor() not implemented on Solaris")
|
||||
}
|
||||
|
||||
type Monitor struct {
|
||||
ooms chan string
|
||||
}
|
||||
|
||||
func (m *Monitor) Exits() chan runtime.Process {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Monitor) OOMs() chan string {
|
||||
return m.ooms
|
||||
}
|
||||
|
||||
func (m *Monitor) Monitor(p runtime.Process) error {
|
||||
return errors.New("Monitor Monitor() not implemented on Solaris")
|
||||
}
|
||||
|
||||
func (m *Monitor) MonitorOOM(c runtime.Container) error {
|
||||
return errors.New("Monitor MonitorOOM() not implemented on Solaris")
|
||||
}
|
||||
|
||||
func (m *Monitor) Close() error {
|
||||
return errors.New("Monitor Close() not implemented on Solaris")
|
||||
}
|
||||
|
||||
func (m *Monitor) start() {
|
||||
}
|
22
vendor/github.com/docker/containerd/supervisor/oom.go
generated
vendored
22
vendor/github.com/docker/containerd/supervisor/oom.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
type OOMTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
}
|
||||
|
||||
func (s *Supervisor) oom(t *OOMTask) error {
|
||||
logrus.WithField("id", t.ID).Debug("containerd: container oom")
|
||||
s.notifySubscribers(Event{
|
||||
Timestamp: time.Now(),
|
||||
ID: t.ID,
|
||||
Type: StateOOM,
|
||||
})
|
||||
return nil
|
||||
}
|
27
vendor/github.com/docker/containerd/supervisor/signal.go
generated
vendored
27
vendor/github.com/docker/containerd/supervisor/signal.go
generated
vendored
@@ -1,27 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import "os"
|
||||
|
||||
type SignalTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
PID string
|
||||
Signal os.Signal
|
||||
}
|
||||
|
||||
func (s *Supervisor) signal(t *SignalTask) error {
|
||||
i, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
processes, err := i.container.Processes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range processes {
|
||||
if p.ID() == t.PID {
|
||||
return p.Signal(t.Signal)
|
||||
}
|
||||
}
|
||||
return ErrProcessNotFound
|
||||
}
|
27
vendor/github.com/docker/containerd/supervisor/sort.go
generated
vendored
27
vendor/github.com/docker/containerd/supervisor/sort.go
generated
vendored
@@ -1,27 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
func sortProcesses(p []runtime.Process) {
|
||||
sort.Sort(&processSorter{p})
|
||||
}
|
||||
|
||||
type processSorter struct {
|
||||
processes []runtime.Process
|
||||
}
|
||||
|
||||
func (s *processSorter) Len() int {
|
||||
return len(s.processes)
|
||||
}
|
||||
|
||||
func (s *processSorter) Swap(i, j int) {
|
||||
s.processes[i], s.processes[j] = s.processes[j], s.processes[i]
|
||||
}
|
||||
|
||||
func (s *processSorter) Less(i, j int) bool {
|
||||
return s.processes[j].ID() == "init"
|
||||
}
|
33
vendor/github.com/docker/containerd/supervisor/stats.go
generated
vendored
33
vendor/github.com/docker/containerd/supervisor/stats.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
type StatsTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
Stat chan *runtime.Stat
|
||||
}
|
||||
|
||||
func (s *Supervisor) stats(t *StatsTask) error {
|
||||
start := time.Now()
|
||||
i, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
// TODO: use workers for this
|
||||
go func() {
|
||||
s, err := i.container.Stats()
|
||||
if err != nil {
|
||||
t.ErrorCh() <- err
|
||||
return
|
||||
}
|
||||
t.ErrorCh() <- nil
|
||||
t.Stat <- s
|
||||
ContainerStatsTimer.UpdateSince(start)
|
||||
}()
|
||||
return errDeferredResponse
|
||||
}
|
385
vendor/github.com/docker/containerd/supervisor/supervisor.go
generated
vendored
385
vendor/github.com/docker/containerd/supervisor/supervisor.go
generated
vendored
@@ -1,385 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBufferSize = 2048 // size of queue in eventloop
|
||||
)
|
||||
|
||||
// New returns an initialized Process supervisor.
|
||||
func New(stateDir string, runtimeName, shimName string, runtimeArgs []string, timeout time.Duration, retainCount int) (*Supervisor, error) {
|
||||
startTasks := make(chan *startTask, 10)
|
||||
if err := os.MkdirAll(stateDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
machine, err := CollectMachineInformation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
monitor, err := NewMonitor()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &Supervisor{
|
||||
stateDir: stateDir,
|
||||
containers: make(map[string]*containerInfo),
|
||||
startTasks: startTasks,
|
||||
machine: machine,
|
||||
subscribers: make(map[chan Event]struct{}),
|
||||
tasks: make(chan Task, defaultBufferSize),
|
||||
monitor: monitor,
|
||||
runtime: runtimeName,
|
||||
runtimeArgs: runtimeArgs,
|
||||
shim: shimName,
|
||||
timeout: timeout,
|
||||
}
|
||||
if err := setupEventLog(s, retainCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go s.exitHandler()
|
||||
go s.oomHandler()
|
||||
if err := s.restore(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type containerInfo struct {
|
||||
container runtime.Container
|
||||
}
|
||||
|
||||
func setupEventLog(s *Supervisor, retainCount int) error {
|
||||
if err := readEventLog(s); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.WithField("count", len(s.eventLog)).Debug("containerd: read past events")
|
||||
events := s.Events(time.Time{})
|
||||
return eventLogger(s, filepath.Join(s.stateDir, "events.log"), events, retainCount)
|
||||
}
|
||||
|
||||
func eventLogger(s *Supervisor, path string, events chan Event, retainCount int) error {
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_TRUNC, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
var (
|
||||
count = len(s.eventLog)
|
||||
enc = json.NewEncoder(f)
|
||||
)
|
||||
for e := range events {
|
||||
// if we have a specified retain count make sure the truncate the event
|
||||
// log if it grows past the specified number of events to keep.
|
||||
if retainCount > 0 {
|
||||
if count > retainCount {
|
||||
logrus.Debug("truncating event log")
|
||||
// close the log file
|
||||
if f != nil {
|
||||
f.Close()
|
||||
}
|
||||
slice := retainCount - 1
|
||||
l := len(s.eventLog)
|
||||
if slice >= l {
|
||||
slice = l
|
||||
}
|
||||
s.eventLock.Lock()
|
||||
s.eventLog = s.eventLog[len(s.eventLog)-slice:]
|
||||
s.eventLock.Unlock()
|
||||
if f, err = os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_TRUNC, 0755); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: open event to journal")
|
||||
continue
|
||||
}
|
||||
enc = json.NewEncoder(f)
|
||||
count = 0
|
||||
for _, le := range s.eventLog {
|
||||
if err := enc.Encode(le); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: write event to journal")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s.eventLock.Lock()
|
||||
s.eventLog = append(s.eventLog, e)
|
||||
s.eventLock.Unlock()
|
||||
count++
|
||||
if err := enc.Encode(e); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: write event to journal")
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func readEventLog(s *Supervisor) error {
|
||||
f, err := os.Open(filepath.Join(s.stateDir, "events.log"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
dec := json.NewDecoder(f)
|
||||
for {
|
||||
var e Event
|
||||
if err := dec.Decode(&e); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
s.eventLog = append(s.eventLog, e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Supervisor struct {
|
||||
// stateDir is the directory on the system to store container runtime state information.
|
||||
stateDir string
|
||||
// name of the OCI compatible runtime used to execute containers
|
||||
runtime string
|
||||
runtimeArgs []string
|
||||
shim string
|
||||
containers map[string]*containerInfo
|
||||
startTasks chan *startTask
|
||||
// we need a lock around the subscribers map only because additions and deletions from
|
||||
// the map are via the API so we cannot really control the concurrency
|
||||
subscriberLock sync.RWMutex
|
||||
subscribers map[chan Event]struct{}
|
||||
machine Machine
|
||||
tasks chan Task
|
||||
monitor *Monitor
|
||||
eventLog []Event
|
||||
eventLock sync.Mutex
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// Stop closes all startTasks and sends a SIGTERM to each container's pid1 then waits for they to
|
||||
// terminate. After it has handled all the SIGCHILD events it will close the signals chan
|
||||
// and exit. Stop is a non-blocking call and will return after the containers have been signaled
|
||||
func (s *Supervisor) Stop() {
|
||||
// Close the startTasks channel so that no new containers get started
|
||||
close(s.startTasks)
|
||||
}
|
||||
|
||||
// Close closes any open files in the supervisor but expects that Stop has been
|
||||
// callsed so that no more containers are started.
|
||||
func (s *Supervisor) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
PID string `json:"pid,omitempty"`
|
||||
Status int `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// Events returns an event channel that external consumers can use to receive updates
|
||||
// on container events
|
||||
func (s *Supervisor) Events(from time.Time) chan Event {
|
||||
s.subscriberLock.Lock()
|
||||
defer s.subscriberLock.Unlock()
|
||||
c := make(chan Event, defaultBufferSize)
|
||||
EventSubscriberCounter.Inc(1)
|
||||
s.subscribers[c] = struct{}{}
|
||||
if !from.IsZero() {
|
||||
// replay old event
|
||||
s.eventLock.Lock()
|
||||
past := s.eventLog[:]
|
||||
s.eventLock.Unlock()
|
||||
for _, e := range past {
|
||||
if e.Timestamp.After(from) {
|
||||
c <- e
|
||||
}
|
||||
}
|
||||
// Notify the client that from now on it's live events
|
||||
c <- Event{
|
||||
Type: StateLive,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Unsubscribe removes the provided channel from receiving any more events
|
||||
func (s *Supervisor) Unsubscribe(sub chan Event) {
|
||||
s.subscriberLock.Lock()
|
||||
defer s.subscriberLock.Unlock()
|
||||
delete(s.subscribers, sub)
|
||||
close(sub)
|
||||
EventSubscriberCounter.Dec(1)
|
||||
}
|
||||
|
||||
// notifySubscribers will send the provided event to the external subscribers
|
||||
// of the events channel
|
||||
func (s *Supervisor) notifySubscribers(e Event) {
|
||||
s.subscriberLock.RLock()
|
||||
defer s.subscriberLock.RUnlock()
|
||||
for sub := range s.subscribers {
|
||||
// do a non-blocking send for the channel
|
||||
select {
|
||||
case sub <- e:
|
||||
default:
|
||||
logrus.WithField("event", e.Type).Warn("containerd: event not sent to subscriber")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start is a non-blocking call that runs the supervisor for monitoring contianer processes and
|
||||
// executing new containers.
|
||||
//
|
||||
// This event loop is the only thing that is allowed to modify state of containers and processes
|
||||
// therefore it is save to do operations in the handlers that modify state of the system or
|
||||
// state of the Supervisor
|
||||
func (s *Supervisor) Start() error {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"stateDir": s.stateDir,
|
||||
"runtime": s.runtime,
|
||||
"runtimeArgs": s.runtimeArgs,
|
||||
"memory": s.machine.Memory,
|
||||
"cpus": s.machine.Cpus,
|
||||
}).Debug("containerd: supervisor running")
|
||||
go func() {
|
||||
for i := range s.tasks {
|
||||
s.handleTask(i)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Machine returns the machine information for which the
|
||||
// supervisor is executing on.
|
||||
func (s *Supervisor) Machine() Machine {
|
||||
return s.machine
|
||||
}
|
||||
|
||||
// SendTask sends the provided event the the supervisors main event loop
|
||||
func (s *Supervisor) SendTask(evt Task) {
|
||||
TasksCounter.Inc(1)
|
||||
s.tasks <- evt
|
||||
}
|
||||
|
||||
func (s *Supervisor) exitHandler() {
|
||||
for p := range s.monitor.Exits() {
|
||||
e := &ExitTask{
|
||||
Process: p,
|
||||
}
|
||||
s.SendTask(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Supervisor) oomHandler() {
|
||||
for id := range s.monitor.OOMs() {
|
||||
e := &OOMTask{
|
||||
ID: id,
|
||||
}
|
||||
s.SendTask(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Supervisor) monitorProcess(p runtime.Process) error {
|
||||
return s.monitor.Monitor(p)
|
||||
}
|
||||
|
||||
func (s *Supervisor) restore() error {
|
||||
dirs, err := ioutil.ReadDir(s.stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, d := range dirs {
|
||||
if !d.IsDir() {
|
||||
continue
|
||||
}
|
||||
id := d.Name()
|
||||
container, err := runtime.Load(s.stateDir, id, s.timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
processes, err := container.Processes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ContainersCounter.Inc(1)
|
||||
s.containers[id] = &containerInfo{
|
||||
container: container,
|
||||
}
|
||||
if err := s.monitor.MonitorOOM(container); err != nil && err != runtime.ErrContainerExited {
|
||||
logrus.WithField("error", err).Error("containerd: notify OOM events")
|
||||
}
|
||||
logrus.WithField("id", id).Debug("containerd: container restored")
|
||||
var exitedProcesses []runtime.Process
|
||||
for _, p := range processes {
|
||||
if p.State() == runtime.Running {
|
||||
if err := s.monitorProcess(p); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
exitedProcesses = append(exitedProcesses, p)
|
||||
}
|
||||
}
|
||||
if len(exitedProcesses) > 0 {
|
||||
// sort processes so that init is fired last because that is how the kernel sends the
|
||||
// exit events
|
||||
sortProcesses(exitedProcesses)
|
||||
for _, p := range exitedProcesses {
|
||||
e := &ExitTask{
|
||||
Process: p,
|
||||
}
|
||||
s.SendTask(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Supervisor) handleTask(i Task) {
|
||||
var err error
|
||||
switch t := i.(type) {
|
||||
case *AddProcessTask:
|
||||
err = s.addProcess(t)
|
||||
case *CreateCheckpointTask:
|
||||
err = s.createCheckpoint(t)
|
||||
case *DeleteCheckpointTask:
|
||||
err = s.deleteCheckpoint(t)
|
||||
case *StartTask:
|
||||
err = s.start(t)
|
||||
case *DeleteTask:
|
||||
err = s.delete(t)
|
||||
case *ExitTask:
|
||||
err = s.exit(t)
|
||||
case *ExecExitTask:
|
||||
err = s.execExit(t)
|
||||
case *GetContainersTask:
|
||||
err = s.getContainers(t)
|
||||
case *SignalTask:
|
||||
err = s.signal(t)
|
||||
case *StatsTask:
|
||||
err = s.stats(t)
|
||||
case *UpdateTask:
|
||||
err = s.updateContainer(t)
|
||||
case *UpdateProcessTask:
|
||||
err = s.updateProcess(t)
|
||||
case *OOMTask:
|
||||
err = s.oom(t)
|
||||
default:
|
||||
err = ErrUnknownTask
|
||||
}
|
||||
if err != errDeferredResponse {
|
||||
i.ErrorCh() <- err
|
||||
close(i.ErrorCh())
|
||||
}
|
||||
}
|
33
vendor/github.com/docker/containerd/supervisor/task.go
generated
vendored
33
vendor/github.com/docker/containerd/supervisor/task.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
// StartResponse is the response containing a started container
|
||||
type StartResponse struct {
|
||||
Container runtime.Container
|
||||
}
|
||||
|
||||
// Task executes an action returning an error chan with either nil or
|
||||
// the error from executing the task
|
||||
type Task interface {
|
||||
// ErrorCh returns a channel used to report and error from an async task
|
||||
ErrorCh() chan error
|
||||
}
|
||||
|
||||
type baseTask struct {
|
||||
errCh chan error
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (t *baseTask) ErrorCh() chan error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.errCh == nil {
|
||||
t.errCh = make(chan error, 1)
|
||||
}
|
||||
return t.errCh
|
||||
}
|
12
vendor/github.com/docker/containerd/supervisor/types.go
generated
vendored
12
vendor/github.com/docker/containerd/supervisor/types.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
// State constants used in Event types
|
||||
const (
|
||||
StateStart = "start-container"
|
||||
StatePause = "pause"
|
||||
StateResume = "resume"
|
||||
StateExit = "exit"
|
||||
StateStartProcess = "start-process"
|
||||
StateOOM = "oom"
|
||||
StateLive = "live"
|
||||
)
|
92
vendor/github.com/docker/containerd/supervisor/update.go
generated
vendored
92
vendor/github.com/docker/containerd/supervisor/update.go
generated
vendored
@@ -1,92 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
type UpdateTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
State runtime.State
|
||||
Resources *runtime.Resource
|
||||
}
|
||||
|
||||
func (s *Supervisor) updateContainer(t *UpdateTask) error {
|
||||
i, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
container := i.container
|
||||
if t.State != "" {
|
||||
switch t.State {
|
||||
case runtime.Running:
|
||||
if err := container.Resume(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.notifySubscribers(Event{
|
||||
ID: t.ID,
|
||||
Type: StateResume,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
case runtime.Paused:
|
||||
if err := container.Pause(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.notifySubscribers(Event{
|
||||
ID: t.ID,
|
||||
Type: StatePause,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
default:
|
||||
return ErrUnknownContainerStatus
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if t.Resources != nil {
|
||||
return container.UpdateResources(t.Resources)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateProcessTask struct {
|
||||
baseTask
|
||||
ID string
|
||||
PID string
|
||||
CloseStdin bool
|
||||
Width int
|
||||
Height int
|
||||
}
|
||||
|
||||
func (s *Supervisor) updateProcess(t *UpdateProcessTask) error {
|
||||
i, ok := s.containers[t.ID]
|
||||
if !ok {
|
||||
return ErrContainerNotFound
|
||||
}
|
||||
processes, err := i.container.Processes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var process runtime.Process
|
||||
for _, p := range processes {
|
||||
if p.ID() == t.PID {
|
||||
process = p
|
||||
break
|
||||
}
|
||||
}
|
||||
if process == nil {
|
||||
return ErrProcessNotFound
|
||||
}
|
||||
if t.CloseStdin {
|
||||
if err := process.CloseStdin(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if t.Width > 0 || t.Height > 0 {
|
||||
if err := process.Resize(t.Width, t.Height); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
74
vendor/github.com/docker/containerd/supervisor/worker.go
generated
vendored
74
vendor/github.com/docker/containerd/supervisor/worker.go
generated
vendored
@@ -1,74 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/containerd/runtime"
|
||||
)
|
||||
|
||||
type Worker interface {
|
||||
Start()
|
||||
}
|
||||
|
||||
type startTask struct {
|
||||
Container runtime.Container
|
||||
Checkpoint string
|
||||
Stdin string
|
||||
Stdout string
|
||||
Stderr string
|
||||
Err chan error
|
||||
StartResponse chan StartResponse
|
||||
}
|
||||
|
||||
func NewWorker(s *Supervisor, wg *sync.WaitGroup) Worker {
|
||||
return &worker{
|
||||
s: s,
|
||||
wg: wg,
|
||||
}
|
||||
}
|
||||
|
||||
type worker struct {
|
||||
wg *sync.WaitGroup
|
||||
s *Supervisor
|
||||
}
|
||||
|
||||
func (w *worker) Start() {
|
||||
defer w.wg.Done()
|
||||
for t := range w.s.startTasks {
|
||||
started := time.Now()
|
||||
process, err := t.Container.Start(t.Checkpoint, runtime.NewStdio(t.Stdin, t.Stdout, t.Stderr))
|
||||
if err != nil {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"error": err,
|
||||
"id": t.Container.ID(),
|
||||
}).Error("containerd: start container")
|
||||
t.Err <- err
|
||||
evt := &DeleteTask{
|
||||
ID: t.Container.ID(),
|
||||
NoEvent: true,
|
||||
}
|
||||
w.s.SendTask(evt)
|
||||
continue
|
||||
}
|
||||
if err := w.s.monitor.MonitorOOM(t.Container); err != nil && err != runtime.ErrContainerExited {
|
||||
if process.State() != runtime.Stopped {
|
||||
logrus.WithField("error", err).Error("containerd: notify OOM events")
|
||||
}
|
||||
}
|
||||
if err := w.s.monitorProcess(process); err != nil {
|
||||
logrus.WithField("error", err).Error("containerd: add process to monitor")
|
||||
}
|
||||
ContainerStartTimer.UpdateSince(started)
|
||||
t.Err <- nil
|
||||
t.StartResponse <- StartResponse{
|
||||
Container: t.Container,
|
||||
}
|
||||
w.s.notifySubscribers(Event{
|
||||
Timestamp: time.Now(),
|
||||
ID: t.Container.ID(),
|
||||
Type: StateStart,
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user