2016-12-02 19:33:58 +00:00
|
|
|
package execution
|
|
|
|
|
|
|
|
import (
|
2016-12-05 22:15:03 +00:00
|
|
|
"fmt"
|
2016-12-02 19:33:58 +00:00
|
|
|
|
|
|
|
api "github.com/docker/containerd/api/execution"
|
2016-12-05 22:15:03 +00:00
|
|
|
google_protobuf "github.com/golang/protobuf/ptypes/empty"
|
|
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
|
|
"golang.org/x/net/context"
|
2016-12-02 19:33:58 +00:00
|
|
|
)
|
|
|
|
|
2016-12-05 22:33:31 +00:00
|
|
|
type ServiceOpts struct {
|
2016-12-02 19:33:58 +00:00
|
|
|
Root string
|
|
|
|
Runtime string
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:33:31 +00:00
|
|
|
func New(opts ServiceOpts, executor Executor) (*Service, error) {
|
2016-12-02 19:33:58 +00:00
|
|
|
return &Service{
|
2016-12-05 22:33:31 +00:00
|
|
|
o: opts,
|
2016-12-02 19:33:58 +00:00
|
|
|
executor: executor,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type Service struct {
|
2016-12-05 22:33:31 +00:00
|
|
|
o ServiceOpts
|
|
|
|
executor Executor
|
2016-12-02 19:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) Create(ctx context.Context, r *api.CreateContainerRequest) (*api.CreateContainerResponse, error) {
|
|
|
|
// TODO: write io and bundle path to dir
|
2016-12-05 22:15:03 +00:00
|
|
|
// TODO: open IOs
|
2016-12-05 22:33:31 +00:00
|
|
|
container, err := s.executor.Create(r.ID, CreateOpts{
|
2016-12-05 22:15:03 +00:00
|
|
|
Bundle: r.BundlePath,
|
|
|
|
// Stdin: r.Stdin,
|
|
|
|
// Stdout: r.Stdout,
|
|
|
|
// Stderr: r.Stderr,
|
|
|
|
})
|
2016-12-02 19:33:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
s.supervisor.Add(container)
|
2016-12-02 19:33:58 +00:00
|
|
|
|
|
|
|
return &api.CreateContainerResponse{
|
|
|
|
Container: toGRPCContainer(container),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) Delete(ctx context.Context, r *api.DeleteContainerRequest) (*google_protobuf.Empty, error) {
|
|
|
|
container, err := s.executor.Load(r.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = s.executor.Delete(container); err != nil {
|
2016-12-02 19:33:58 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) List(ctx context.Context, r *api.ListContainersRequest) (*api.ListContainersResponse, error) {
|
2016-12-02 19:33:58 +00:00
|
|
|
containers, err := s.executor.List()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
resp := &api.ListContainersResponse{}
|
2016-12-02 19:33:58 +00:00
|
|
|
for _, c := range containers {
|
2016-12-05 22:15:03 +00:00
|
|
|
resp.Containers = append(resp.Containers, toGRPCContainer(c))
|
2016-12-02 19:33:58 +00:00
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
return resp, nil
|
2016-12-02 19:33:58 +00:00
|
|
|
}
|
2016-12-02 23:37:16 +00:00
|
|
|
func (s *Service) Get(ctx context.Context, r *api.GetContainerRequest) (*api.GetContainerResponse, error) {
|
|
|
|
container, err := s.executor.Load(r.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &api.GetContainerResponse{
|
|
|
|
Container: toGRPCContainer(container),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) Update(ctx context.Context, r *api.UpdateContainerRequest) (*google_protobuf.Empty, error) {
|
2016-12-02 23:37:16 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) Pause(ctx context.Context, r *api.PauseContainerRequest) (*google_protobuf.Empty, error) {
|
2016-12-02 23:37:16 +00:00
|
|
|
container, err := s.executor.Load(r.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
return nil, s.executor.Pause(container)
|
2016-12-02 23:37:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) Resume(ctx context.Context, r *api.ResumeContainerRequest) (*google_protobuf.Empty, error) {
|
2016-12-02 23:37:16 +00:00
|
|
|
container, err := s.executor.Load(r.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
return nil, s.executor.Resume(container)
|
2016-12-02 23:37:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) StartProcess(ctx context.Context, r *api.StartProcessRequest) (*api.StartProcessResponse, error) {
|
|
|
|
container, err := s.executor.Load(r.ContainerId)
|
2016-12-02 23:37:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
// TODO: generate spec
|
|
|
|
var spec specs.Process
|
|
|
|
// TODO: open IOs
|
2016-12-05 22:33:31 +00:00
|
|
|
process, err := s.executor.StartProcess(container, CreateProcessOpts{
|
2016-12-05 22:15:03 +00:00
|
|
|
Spec: spec,
|
|
|
|
// Stdin: r.Stdin,
|
|
|
|
// Stdout: r.Stdout,
|
|
|
|
// Stderr: r.Stderr,
|
|
|
|
})
|
2016-12-02 23:37:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
s.supervisor.Add(process)
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
return &api.StartProcessResponse{
|
|
|
|
Process: toGRPCProcess(process),
|
2016-12-02 23:37:16 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// containerd managed execs + system pids forked in container
|
|
|
|
func (s *Service) GetProcess(ctx context.Context, r *api.GetProcessRequest) (*api.GetProcessResponse, error) {
|
2016-12-05 22:15:03 +00:00
|
|
|
container, err := s.executor.Load(r.Container.ID)
|
2016-12-02 23:37:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
process := s.executor.GetProcess(r.Pid)
|
|
|
|
if process == nil {
|
|
|
|
return nil, fmt.Errorf("Make me a constant! Process not foumd!")
|
2016-12-02 23:37:16 +00:00
|
|
|
}
|
|
|
|
return &api.GetProcessResponse{
|
2016-12-05 22:15:03 +00:00
|
|
|
Process: toGRPCProcess(process),
|
2016-12-02 23:37:16 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) SignalProcess(ctx context.Context, r *api.SignalProcessRequest) (*google_protobuf.Empty, error) {
|
|
|
|
container, err := s.executor.Load(r.Container.ID)
|
2016-12-02 23:37:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
return nil, s.executor.SignalProcess(container, r.Process.ID, r.Signal)
|
2016-12-02 23:37:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 22:15:03 +00:00
|
|
|
func (s *Service) DeleteProcess(ctx context.Context, r *api.DeleteProcessRequest) (*google_protobuf.Empty, error) {
|
|
|
|
container, err := s.executor.Load(r.Container.ID)
|
2016-12-02 23:37:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
if err := s.executor.DeleteProcess(container, r.Process.ID); err != nil {
|
2016-12-02 23:37:16 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) ListProcesses(ctx context.Context, r *api.ListProcessesRequest) (*api.ListProcessesResponse, error) {
|
2016-12-05 22:15:03 +00:00
|
|
|
container, err := s.executor.Load(r.Container.ID)
|
2016-12-02 23:37:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-05 22:15:03 +00:00
|
|
|
processes := container.Processes()
|
2016-12-02 23:37:16 +00:00
|
|
|
return &api.ListProcessesResponse{
|
2016-12-05 22:15:03 +00:00
|
|
|
Processes: toGRPCProcesses(processes),
|
2016-12-02 23:37:16 +00:00
|
|
|
}, nil
|
|
|
|
}
|
2016-12-02 19:33:58 +00:00
|
|
|
|
|
|
|
var (
|
|
|
|
_ = (api.ExecutionServiceServer)(&Service{})
|
|
|
|
_ = (api.ContainerServiceServer)(&Service{})
|
|
|
|
)
|