2015-12-17 16:07:04 -08:00
|
|
|
package supervisor
|
2015-12-02 17:42:28 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2015-12-15 16:22:53 -08:00
|
|
|
"github.com/Sirupsen/logrus"
|
2015-12-02 17:42:28 -08:00
|
|
|
"github.com/docker/containerd/runtime"
|
|
|
|
)
|
|
|
|
|
2016-06-03 15:00:49 -07:00
|
|
|
// Worker interface
|
2015-12-02 17:42:28 -08:00
|
|
|
type Worker interface {
|
|
|
|
Start()
|
|
|
|
}
|
|
|
|
|
2016-02-11 17:26:24 -08:00
|
|
|
type startTask struct {
|
2016-05-25 20:42:37 -04:00
|
|
|
Container runtime.Container
|
|
|
|
CheckpointPath string
|
|
|
|
Stdin string
|
|
|
|
Stdout string
|
|
|
|
Stderr string
|
|
|
|
Err chan error
|
|
|
|
StartResponse chan StartResponse
|
2015-12-02 17:42:28 -08:00
|
|
|
}
|
|
|
|
|
2016-06-03 15:00:49 -07:00
|
|
|
// NewWorker return a new initialized worker
|
2015-12-02 17:42:28 -08:00
|
|
|
func NewWorker(s *Supervisor, wg *sync.WaitGroup) Worker {
|
|
|
|
return &worker{
|
|
|
|
s: s,
|
|
|
|
wg: wg,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type worker struct {
|
|
|
|
wg *sync.WaitGroup
|
|
|
|
s *Supervisor
|
|
|
|
}
|
|
|
|
|
2016-06-03 15:00:49 -07:00
|
|
|
// Start runs a loop in charge of starting new containers
|
2015-12-02 17:42:28 -08:00
|
|
|
func (w *worker) Start() {
|
|
|
|
defer w.wg.Done()
|
2016-02-17 10:55:54 -08:00
|
|
|
for t := range w.s.startTasks {
|
2016-02-01 15:07:02 -08:00
|
|
|
started := time.Now()
|
2016-05-25 20:42:37 -04:00
|
|
|
process, err := t.Container.Start(t.CheckpointPath, runtime.NewStdio(t.Stdin, t.Stdout, t.Stderr))
|
2016-02-01 15:07:02 -08:00
|
|
|
if err != nil {
|
2016-02-25 12:59:34 -08:00
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
"error": err,
|
|
|
|
"id": t.Container.ID(),
|
|
|
|
}).Error("containerd: start container")
|
|
|
|
t.Err <- err
|
2016-02-17 10:55:54 -08:00
|
|
|
evt := &DeleteTask{
|
2016-03-11 16:40:42 -08:00
|
|
|
ID: t.Container.ID(),
|
|
|
|
NoEvent: true,
|
2016-07-15 11:49:43 -07:00
|
|
|
Process: process,
|
2016-02-17 10:55:54 -08:00
|
|
|
}
|
2016-02-11 17:26:24 -08:00
|
|
|
w.s.SendTask(evt)
|
2016-02-01 15:07:02 -08:00
|
|
|
continue
|
2015-12-02 17:42:28 -08:00
|
|
|
}
|
2016-02-29 14:15:16 -08:00
|
|
|
if err := w.s.monitor.MonitorOOM(t.Container); err != nil && err != runtime.ErrContainerExited {
|
2016-04-06 17:39:13 -07:00
|
|
|
if process.State() != runtime.Stopped {
|
|
|
|
logrus.WithField("error", err).Error("containerd: notify OOM events")
|
|
|
|
}
|
2016-02-29 14:15:16 -08:00
|
|
|
}
|
2016-01-06 13:32:46 -08:00
|
|
|
if err := w.s.monitorProcess(process); err != nil {
|
|
|
|
logrus.WithField("error", err).Error("containerd: add process to monitor")
|
2016-06-24 12:02:53 -07:00
|
|
|
t.Err <- err
|
|
|
|
evt := &DeleteTask{
|
|
|
|
ID: t.Container.ID(),
|
|
|
|
NoEvent: true,
|
2016-07-15 11:49:43 -07:00
|
|
|
Process: process,
|
2016-06-24 12:02:53 -07:00
|
|
|
}
|
|
|
|
w.s.SendTask(evt)
|
|
|
|
continue
|
2015-12-15 16:22:53 -08:00
|
|
|
}
|
2016-08-26 13:25:19 -04:00
|
|
|
// only call process start if we aren't restoring from a checkpoint
|
|
|
|
// if we have restored from a checkpoint then the process is already started
|
|
|
|
if t.CheckpointPath == "" {
|
|
|
|
if err := process.Start(); err != nil {
|
|
|
|
logrus.WithField("error", err).Error("containerd: start init process")
|
|
|
|
t.Err <- err
|
|
|
|
evt := &DeleteTask{
|
|
|
|
ID: t.Container.ID(),
|
|
|
|
NoEvent: true,
|
|
|
|
Process: process,
|
|
|
|
}
|
|
|
|
w.s.SendTask(evt)
|
|
|
|
continue
|
2016-06-24 12:02:53 -07:00
|
|
|
}
|
2016-06-09 13:33:26 -07:00
|
|
|
}
|
2015-12-02 17:42:28 -08:00
|
|
|
ContainerStartTimer.UpdateSince(started)
|
|
|
|
t.Err <- nil
|
2016-02-11 11:56:11 -08:00
|
|
|
t.StartResponse <- StartResponse{
|
|
|
|
Container: t.Container,
|
|
|
|
}
|
2016-02-11 17:26:24 -08:00
|
|
|
w.s.notifySubscribers(Event{
|
|
|
|
Timestamp: time.Now(),
|
|
|
|
ID: t.Container.ID(),
|
2016-04-19 19:02:37 +08:00
|
|
|
Type: StateStart,
|
2016-02-11 17:26:24 -08:00
|
|
|
})
|
2015-12-02 17:42:28 -08:00
|
|
|
}
|
|
|
|
}
|