2017-01-24 23:55:32 +00:00
|
|
|
package shim
|
2017-01-19 22:16:50 +00:00
|
|
|
|
|
|
|
import (
|
2017-01-24 00:18:10 +00:00
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
runc "github.com/crosbymichael/go-runc"
|
2017-01-24 23:55:32 +00:00
|
|
|
apishim "github.com/docker/containerd/api/shim"
|
2017-01-19 22:16:50 +00:00
|
|
|
"github.com/docker/containerd/utils"
|
|
|
|
google_protobuf "github.com/golang/protobuf/ptypes/empty"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
|
|
|
|
2017-01-19 23:21:25 +00:00
|
|
|
var emptyResponse = &google_protobuf.Empty{}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func NewService() *Service {
|
|
|
|
return &Service{
|
|
|
|
processes: make(map[int]process),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type Service struct {
|
2017-01-24 00:18:10 +00:00
|
|
|
initPid int
|
|
|
|
mu sync.Mutex
|
|
|
|
processes map[int]process
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func (s *Service) Create(ctx context.Context, r *apishim.CreateRequest) (*apishim.CreateResponse, error) {
|
2017-01-24 00:18:10 +00:00
|
|
|
process, err := newInitProcess(ctx, r)
|
2017-01-19 22:16:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
pid := process.Pid()
|
|
|
|
s.initPid, s.processes[pid] = pid, process
|
|
|
|
s.mu.Unlock()
|
2017-01-24 23:55:32 +00:00
|
|
|
return &apishim.CreateResponse{
|
2017-01-24 00:18:10 +00:00
|
|
|
Pid: uint32(pid),
|
2017-01-19 22:16:50 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func (s *Service) Start(ctx context.Context, r *apishim.StartRequest) (*google_protobuf.Empty, error) {
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
p := s.processes[s.initPid]
|
|
|
|
s.mu.Unlock()
|
|
|
|
if err := p.Start(ctx); err != nil {
|
2017-01-19 23:21:25 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return emptyResponse, nil
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func (s *Service) Delete(ctx context.Context, r *apishim.DeleteRequest) (*apishim.DeleteResponse, error) {
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
p, ok := s.processes[int(r.Pid)]
|
|
|
|
s.mu.Unlock()
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("process does not exist %d", r.Pid)
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
2017-01-24 00:18:10 +00:00
|
|
|
if err := p.Delete(ctx); err != nil {
|
|
|
|
return nil, err
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
delete(s.processes, int(r.Pid))
|
|
|
|
s.mu.Unlock()
|
2017-01-24 23:55:32 +00:00
|
|
|
return &apishim.DeleteResponse{
|
2017-01-24 00:18:10 +00:00
|
|
|
ExitStatus: uint32(p.Status()),
|
|
|
|
}, nil
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func (s *Service) Exec(ctx context.Context, r *apishim.ExecRequest) (*apishim.ExecResponse, error) {
|
2017-01-24 22:45:18 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
defer s.mu.Unlock()
|
|
|
|
process, err := newExecProcess(ctx, r, s.processes[s.initPid].(*initProcess))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pid := process.Pid()
|
|
|
|
s.processes[pid] = process
|
2017-01-24 23:55:32 +00:00
|
|
|
return &apishim.ExecResponse{
|
2017-01-24 22:45:18 +00:00
|
|
|
Pid: uint32(pid),
|
|
|
|
}, nil
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func (s *Service) Pty(ctx context.Context, r *apishim.PtyRequest) (*google_protobuf.Empty, error) {
|
2017-01-24 00:18:10 +00:00
|
|
|
ws := runc.WinSize{
|
2017-01-19 22:16:50 +00:00
|
|
|
Width: uint16(r.Width),
|
|
|
|
Height: uint16(r.Height),
|
|
|
|
}
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
p, ok := s.processes[int(r.Pid)]
|
|
|
|
s.mu.Unlock()
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("process does not exist %d", r.Pid)
|
|
|
|
}
|
|
|
|
if err := p.Resize(ws); err != nil {
|
2017-01-19 22:16:50 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-19 23:21:25 +00:00
|
|
|
return emptyResponse, nil
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 23:55:32 +00:00
|
|
|
func (s *Service) ProcessExit(e utils.Exit) error {
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Lock()
|
|
|
|
if p, ok := s.processes[e.Pid]; ok {
|
|
|
|
p.Exited(e.Status)
|
2017-01-19 22:16:50 +00:00
|
|
|
}
|
2017-01-24 00:18:10 +00:00
|
|
|
s.mu.Unlock()
|
2017-01-19 22:16:50 +00:00
|
|
|
return nil
|
|
|
|
}
|