From 5f5f4904e02c8c08ecfcdecb68cb721448482224 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 5 Nov 2015 16:40:57 -0800 Subject: [PATCH] Making containers run and delete --- api/v1/server.go | 4 ++-- container.go | 2 ++ containerd/daemon.go | 9 ++++++- runtime_linux.go | 8 +++++++ supervisor.go | 57 +++++++++++++++++++++++++++----------------- 5 files changed, 55 insertions(+), 25 deletions(-) diff --git a/api/v1/server.go b/api/v1/server.go index aef85d09d..874da0485 100644 --- a/api/v1/server.go +++ b/api/v1/server.go @@ -15,8 +15,8 @@ func NewServer(supervisor *containerd.Supervisor) http.Handler { r: r, } r.HandleFunc("/containers", s.containers).Methods("GET") - r.HandleFunc("/containers/{id:*}", s.createContainer).Methods("POST") - r.HandleFunc("/containers/{id:*}", s.deleteContainer).Methods("DELETE") + r.HandleFunc("/containers/{id:.*}", s.createContainer).Methods("POST") + r.HandleFunc("/containers/{id:.*}", s.deleteContainer).Methods("DELETE") return s } diff --git a/container.go b/container.go index d36a1e845..ed37f6a76 100644 --- a/container.go +++ b/container.go @@ -1,6 +1,8 @@ package containerd type Container interface { + ID() string + Pid() (int, error) SetExited(status int) Delete() error } diff --git a/containerd/daemon.go b/containerd/daemon.go index 2f926f89c..e457bd08b 100644 --- a/containerd/daemon.go +++ b/containerd/daemon.go @@ -2,6 +2,7 @@ package main import ( "log" + "net/http" "os" "os/signal" "runtime" @@ -11,6 +12,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" "github.com/crosbymichael/containerd" + "github.com/crosbymichael/containerd/api/v1" "github.com/opencontainers/runc/libcontainer/utils" "github.com/rcrowley/go-metrics" ) @@ -55,7 +57,11 @@ func daemon(stateDir string, concurrency, bufferSize int) error { events := make(chan containerd.Event, bufferSize) // start the signal handler in the background. go startSignalHandler(supervisor, bufferSize) - return supervisor.Run(events) + if err := supervisor.Start(events); err != nil { + return err + } + server := v1.NewServer(supervisor) + return http.ListenAndServe("localhost:8888", server) } func startSignalHandler(supervisor *containerd.Supervisor, bufferSize int) { @@ -67,6 +73,7 @@ func startSignalHandler(supervisor *containerd.Supervisor, bufferSize int) { switch s { case syscall.SIGTERM, syscall.SIGINT, syscall.SIGSTOP: supervisor.Stop() + os.Exit(0) case syscall.SIGCHLD: exits, err := reap() if err != nil { diff --git a/runtime_linux.go b/runtime_linux.go index 61e1ee737..0e6d1389c 100644 --- a/runtime_linux.go +++ b/runtime_linux.go @@ -165,6 +165,14 @@ type libcontainerContainer struct { exited bool } +func (c *libcontainerContainer) ID() string { + return c.c.ID() +} + +func (c *libcontainerContainer) Pid() (int, error) { + return c.initProcess.Pid() +} + func (c *libcontainerContainer) SetExited(status int) { c.exitStatus = status // meh diff --git a/supervisor.go b/supervisor.go index a6801df77..676384d3f 100644 --- a/supervisor.go +++ b/supervisor.go @@ -53,37 +53,50 @@ type Supervisor struct { workerGroup sync.WaitGroup } -// Run is a blocking call that runs the supervisor for monitoring contianer processes and +// 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. -func (s *Supervisor) Run(events chan Event) error { +func (s *Supervisor) Start(events chan Event) error { if events == nil { return ErrEventChanNil } s.events = events - for evt := range events { - logrus.WithField("event", evt).Debug("containerd: processing event") - switch e := evt.(type) { - case *ExitEvent: - logrus.WithFields(logrus.Fields{ - "pid": e.Pid, - "status": e.Status, - }).Debug("containerd: process exited") - if container, ok := s.processes[e.Pid]; ok { - container.SetExited(e.Status) + go func() { + for evt := range events { + logrus.WithField("event", evt).Debug("containerd: processing event") + switch e := evt.(type) { + case *ExitEvent: + logrus.WithFields(logrus.Fields{ + "pid": e.Pid, + "status": e.Status, + }).Debug("containerd: process exited") + if container, ok := s.processes[e.Pid]; ok { + container.SetExited(e.Status) + if err := container.Delete(); err != nil { + logrus.WithField("error", err).Error("containerd: deleting container") + } + delete(s.processes, e.Pid) + delete(s.containers, container.ID()) + } + case *StartedEvent: + s.containers[e.ID] = e.Container + pid, err := e.Container.Pid() + if err != nil { + logrus.WithField("error", err).Error("containerd: getting container pid") + continue + } + s.processes[pid] = e.Container + case *CreateContainerEvent: + j := &CreateJob{ + ID: e.ID, + BundlePath: e.BundlePath, + Err: e.Err, + } + s.jobs <- j } - case *StartedEvent: - s.containers[e.ID] = e.Container - case *CreateContainerEvent: - j := &CreateJob{ - ID: e.ID, - BundlePath: e.BundlePath, - Err: e.Err, - } - s.jobs <- j } - } + }() return nil }