Update shim for exec
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
6808dbc02f
commit
835f3b6a97
37 changed files with 786 additions and 709 deletions
|
@ -2,6 +2,7 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
@ -75,18 +76,27 @@ func (s *apiServer) AddProcess(ctx context.Context, r *types.AddProcessRequest)
|
||||||
AdditionalGids: r.User.AdditionalGids,
|
AdditionalGids: r.User.AdditionalGids,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if r.Id == "" {
|
||||||
|
return nil, fmt.Errorf("container id cannot be empty")
|
||||||
|
}
|
||||||
|
if r.Pid == "" {
|
||||||
|
return nil, fmt.Errorf("process id cannot be empty")
|
||||||
|
}
|
||||||
e := supervisor.NewEvent(supervisor.AddProcessEventType)
|
e := supervisor.NewEvent(supervisor.AddProcessEventType)
|
||||||
e.ID = r.Id
|
e.ID = r.Id
|
||||||
|
e.Pid = r.Pid
|
||||||
e.ProcessSpec = process
|
e.ProcessSpec = process
|
||||||
e.Console = r.Console
|
e.StartResponse = make(chan supervisor.StartResponse, 1)
|
||||||
e.Stdin = r.Stdin
|
|
||||||
e.Stdout = r.Stdout
|
|
||||||
e.Stderr = r.Stderr
|
|
||||||
s.sv.SendEvent(e)
|
s.sv.SendEvent(e)
|
||||||
if err := <-e.Err; err != nil {
|
if err := <-e.Err; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &types.AddProcessResponse{}, nil
|
sr := <-e.StartResponse
|
||||||
|
return &types.AddProcessResponse{
|
||||||
|
Stdin: sr.Stdin,
|
||||||
|
Stdout: sr.Stdout,
|
||||||
|
Stderr: sr.Stderr,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiServer) CreateCheckpoint(ctx context.Context, r *types.CreateCheckpointRequest) (*types.CreateCheckpointResponse, error) {
|
func (s *apiServer) CreateCheckpoint(ctx context.Context, r *types.CreateCheckpointRequest) (*types.CreateCheckpointResponse, error) {
|
||||||
|
|
|
@ -65,7 +65,7 @@ var _ = math.Inf
|
||||||
type CreateContainerRequest struct {
|
type CreateContainerRequest struct {
|
||||||
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||||
BundlePath string `protobuf:"bytes,2,opt,name=bundlePath" json:"bundlePath,omitempty"`
|
BundlePath string `protobuf:"bytes,2,opt,name=bundlePath" json:"bundlePath,omitempty"`
|
||||||
Checkpoint string `protobuf:"bytes,3,opt,name=checkpoint" json:"checkpoint,omitempty"`
|
Checkpoint string `protobuf:"bytes,7,opt,name=checkpoint" json:"checkpoint,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} }
|
func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} }
|
||||||
|
@ -74,9 +74,10 @@ func (*CreateContainerRequest) ProtoMessage() {}
|
||||||
func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
|
||||||
type CreateContainerResponse struct {
|
type CreateContainerResponse struct {
|
||||||
Stdin string `protobuf:"bytes,1,opt,name=stdin" json:"stdin,omitempty"`
|
Pid uint32 `protobuf:"varint,1,opt,name=pid" json:"pid,omitempty"`
|
||||||
Stdout string `protobuf:"bytes,2,opt,name=stdout" json:"stdout,omitempty"`
|
Stdin string `protobuf:"bytes,2,opt,name=stdin" json:"stdin,omitempty"`
|
||||||
Stderr string `protobuf:"bytes,3,opt,name=stderr" json:"stderr,omitempty"`
|
Stdout string `protobuf:"bytes,3,opt,name=stdout" json:"stdout,omitempty"`
|
||||||
|
Stderr string `protobuf:"bytes,4,opt,name=stderr" json:"stderr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} }
|
func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} }
|
||||||
|
@ -110,10 +111,7 @@ type AddProcessRequest struct {
|
||||||
Args []string `protobuf:"bytes,4,rep,name=args" json:"args,omitempty"`
|
Args []string `protobuf:"bytes,4,rep,name=args" json:"args,omitempty"`
|
||||||
Env []string `protobuf:"bytes,5,rep,name=env" json:"env,omitempty"`
|
Env []string `protobuf:"bytes,5,rep,name=env" json:"env,omitempty"`
|
||||||
Cwd string `protobuf:"bytes,6,opt,name=cwd" json:"cwd,omitempty"`
|
Cwd string `protobuf:"bytes,6,opt,name=cwd" json:"cwd,omitempty"`
|
||||||
Stdin string `protobuf:"bytes,7,opt,name=stdin" json:"stdin,omitempty"`
|
Pid string `protobuf:"bytes,7,opt,name=pid" json:"pid,omitempty"`
|
||||||
Stdout string `protobuf:"bytes,8,opt,name=stdout" json:"stdout,omitempty"`
|
|
||||||
Stderr string `protobuf:"bytes,9,opt,name=stderr" json:"stderr,omitempty"`
|
|
||||||
Console string `protobuf:"bytes,10,opt,name=console" json:"console,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AddProcessRequest) Reset() { *m = AddProcessRequest{} }
|
func (m *AddProcessRequest) Reset() { *m = AddProcessRequest{} }
|
||||||
|
@ -140,6 +138,9 @@ func (*User) ProtoMessage() {}
|
||||||
func (*User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
func (*User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||||
|
|
||||||
type AddProcessResponse struct {
|
type AddProcessResponse struct {
|
||||||
|
Stdin string `protobuf:"bytes,1,opt,name=stdin" json:"stdin,omitempty"`
|
||||||
|
Stdout string `protobuf:"bytes,2,opt,name=stdout" json:"stdout,omitempty"`
|
||||||
|
Stderr string `protobuf:"bytes,3,opt,name=stderr" json:"stderr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AddProcessResponse) Reset() { *m = AddProcessResponse{} }
|
func (m *AddProcessResponse) Reset() { *m = AddProcessResponse{} }
|
||||||
|
@ -1084,94 +1085,94 @@ var _API_serviceDesc = grpc.ServiceDesc{
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 1440 bytes of a gzipped FileDescriptorProto
|
// 1440 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xd9, 0x72, 0xdc, 0x44,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xdb, 0x72, 0xdc, 0x44,
|
||||||
0x17, 0xf6, 0xec, 0x33, 0x67, 0x16, 0xdb, 0xf2, 0x92, 0xf1, 0xfc, 0x7f, 0x88, 0x11, 0x81, 0xa4,
|
0x13, 0xf6, 0x9e, 0x77, 0x7b, 0x0f, 0xb6, 0xe5, 0xd8, 0x59, 0xef, 0xff, 0x87, 0x04, 0x11, 0x48,
|
||||||
0xa8, 0x94, 0x2b, 0x38, 0x2c, 0x21, 0x5c, 0x40, 0x70, 0x52, 0x09, 0x54, 0x02, 0xae, 0xc4, 0xa6,
|
0x8a, 0x4a, 0xb9, 0x82, 0xc3, 0x21, 0x84, 0x0b, 0x08, 0x4e, 0x2a, 0x81, 0x4a, 0xc0, 0x95, 0xd8,
|
||||||
0x8a, 0x1b, 0xa6, 0x64, 0xa9, 0x19, 0x8b, 0xd1, 0x48, 0x42, 0x6a, 0x79, 0x79, 0x05, 0x9e, 0x87,
|
0x54, 0x71, 0xc3, 0x96, 0x2c, 0x0d, 0x6b, 0xb1, 0x3a, 0x21, 0x8d, 0x7c, 0xb8, 0xe4, 0x96, 0x07,
|
||||||
0xe2, 0x01, 0xa8, 0xe2, 0x9e, 0xe7, 0xe0, 0x29, 0x38, 0xdd, 0x7d, 0xd4, 0x5a, 0x66, 0x09, 0x5c,
|
0xe2, 0x01, 0xa8, 0xe2, 0x9e, 0xe7, 0xe0, 0x29, 0x68, 0xcd, 0xb4, 0x46, 0x23, 0xed, 0xae, 0x03,
|
||||||
0x70, 0x33, 0x55, 0xdd, 0x7d, 0xce, 0x77, 0xbe, 0xb3, 0xaa, 0x7b, 0xa0, 0x63, 0x85, 0xee, 0x41,
|
0x17, 0xdc, 0xb8, 0x6a, 0x46, 0xdd, 0x5f, 0x7f, 0xfd, 0x75, 0xf7, 0xec, 0x8c, 0xa1, 0x67, 0x45,
|
||||||
0x18, 0x05, 0x3c, 0x30, 0x1a, 0xfc, 0x3a, 0x64, 0xb1, 0xf9, 0x02, 0x76, 0x8f, 0x22, 0x66, 0x71,
|
0xee, 0x5e, 0x14, 0x87, 0x3c, 0x34, 0x5a, 0xfc, 0x32, 0x62, 0x89, 0xf9, 0x02, 0x76, 0x0e, 0x62,
|
||||||
0x76, 0x14, 0xf8, 0xdc, 0x72, 0x7d, 0x16, 0xbd, 0x62, 0x3f, 0x27, 0x2c, 0xe6, 0x06, 0x40, 0xd5,
|
0x66, 0x71, 0x76, 0x10, 0x06, 0xdc, 0x72, 0x03, 0x16, 0xbf, 0x62, 0x3f, 0xa7, 0x2c, 0xe1, 0x06,
|
||||||
0x75, 0x86, 0x95, 0xfd, 0xca, 0xdd, 0x8e, 0x81, 0x8b, 0xb3, 0xc4, 0x77, 0x3c, 0x76, 0x6c, 0xf1,
|
0x40, 0xdd, 0x75, 0xc6, 0xb5, 0x5b, 0xb5, 0xbb, 0x3d, 0x03, 0x17, 0x27, 0x69, 0xe0, 0x78, 0xec,
|
||||||
0xf3, 0x61, 0x35, 0xdd, 0xb3, 0xcf, 0x99, 0x3d, 0x0d, 0x03, 0xd7, 0xe7, 0xc3, 0x9a, 0xd8, 0x33,
|
0xd0, 0xe2, 0xa7, 0xe3, 0x7a, 0xbe, 0x67, 0x9f, 0x32, 0x7b, 0x1e, 0x85, 0x6e, 0xc0, 0xc7, 0x9d,
|
||||||
0x9f, 0xc3, 0x8d, 0x39, 0xb4, 0x38, 0x0c, 0xfc, 0x98, 0x19, 0x7d, 0x68, 0xc4, 0xdc, 0x71, 0x7d,
|
0x6c, 0xcf, 0x3c, 0x86, 0xeb, 0x0b, 0x68, 0x49, 0x14, 0x06, 0x09, 0x33, 0xfa, 0xd0, 0x88, 0x08,
|
||||||
0x42, 0x1c, 0x40, 0x13, 0x97, 0x41, 0xc2, 0x09, 0x4d, 0xad, 0x59, 0x14, 0x11, 0xd2, 0x43, 0xe8,
|
0x6f, 0x68, 0x0c, 0xa1, 0x95, 0x70, 0xc7, 0x0d, 0x08, 0x6a, 0x04, 0x6d, 0x5c, 0x86, 0x29, 0x1f,
|
||||||
0xbf, 0x76, 0x27, 0xbe, 0xe5, 0x2d, 0xa2, 0xd3, 0x85, 0x5a, 0x88, 0x8b, 0x4c, 0x53, 0x4a, 0x4a,
|
0x37, 0xb4, 0x35, 0x8b, 0xe3, 0x71, 0x53, 0xc0, 0x3e, 0x84, 0xe1, 0x6b, 0x77, 0x16, 0x58, 0xde,
|
||||||
0xcd, 0xbe, 0xb9, 0x01, 0x83, 0x54, 0x53, 0x99, 0x36, 0x7f, 0xad, 0xc0, 0xe6, 0x63, 0xc7, 0x39,
|
0x32, 0x6e, 0x04, 0x5c, 0x20, 0x09, 0x4b, 0x81, 0x34, 0x34, 0x37, 0x60, 0x94, 0x7b, 0x4a, 0x1e,
|
||||||
0x8e, 0x02, 0x9b, 0xc5, 0xf1, 0x22, 0xc0, 0x0d, 0x68, 0x73, 0x16, 0xcd, 0x5c, 0x81, 0x22, 0x50,
|
0xe6, 0x2f, 0x35, 0xd8, 0x7c, 0xec, 0x38, 0x87, 0x71, 0x68, 0xb3, 0x24, 0x59, 0x06, 0xb8, 0x01,
|
||||||
0xdb, 0xc6, 0x1e, 0xd4, 0x93, 0x98, 0x29, 0x36, 0xdd, 0xc3, 0xee, 0x81, 0x8c, 0xd6, 0xc1, 0x29,
|
0x5d, 0xce, 0x62, 0xdf, 0xcd, 0x50, 0x32, 0xd4, 0xae, 0xb1, 0x0b, 0xcd, 0x34, 0x61, 0xb1, 0xc0,
|
||||||
0x6e, 0x19, 0x3d, 0xa8, 0x5b, 0xd1, 0x24, 0x1e, 0xd6, 0xf7, 0x6b, 0x8a, 0x0b, 0xf3, 0x2f, 0x86,
|
0xec, 0xef, 0xf7, 0xf7, 0x84, 0x74, 0x7b, 0xc7, 0xb8, 0x65, 0x0c, 0xa0, 0x69, 0xc5, 0xb3, 0x04,
|
||||||
0x8d, 0x74, 0x61, 0x5f, 0x3a, 0xc3, 0xa6, 0x04, 0xd5, 0x1e, 0xb7, 0x4a, 0x1e, 0xb7, 0x4b, 0x1e,
|
0x89, 0x36, 0x24, 0x17, 0x16, 0x9c, 0x8d, 0x5b, 0xf9, 0xc2, 0x3e, 0x77, 0xc6, 0x6d, 0x9d, 0x65,
|
||||||
0x77, 0xe4, 0x7a, 0x1d, 0x5a, 0x36, 0xd2, 0x0d, 0x3c, 0x36, 0x04, 0x0a, 0x41, 0x5d, 0xda, 0x43,
|
0x87, 0xf2, 0x69, 0x0a, 0x67, 0xdc, 0x4c, 0x95, 0x26, 0xb8, 0x98, 0x51, 0x1e, 0x43, 0x63, 0x07,
|
||||||
0xd0, 0x84, 0x98, 0xf6, 0xc5, 0x62, 0x42, 0xae, 0xf7, 0x8d, 0x5d, 0x18, 0x58, 0x8e, 0xe3, 0x72,
|
0x46, 0x96, 0xe3, 0xb8, 0xdc, 0x0d, 0x91, 0xc5, 0x33, 0xd7, 0x49, 0x30, 0x76, 0x03, 0xf3, 0x39,
|
||||||
0x37, 0x40, 0xe2, 0xcf, 0x5c, 0x27, 0x46, 0xba, 0x35, 0x0c, 0xc1, 0x36, 0x18, 0x79, 0x7f, 0x29,
|
0x00, 0x43, 0x27, 0x4f, 0xda, 0x2a, 0x39, 0x6b, 0x15, 0x39, 0xeb, 0x15, 0x39, 0x85, 0xbc, 0x58,
|
||||||
0x0c, 0x2f, 0x74, 0x72, 0x74, 0xda, 0x16, 0xc5, 0xe2, 0xdd, 0x42, 0x5e, 0xab, 0xd2, 0xff, 0x4d,
|
0xf3, 0xbc, 0x4a, 0xaa, 0x7e, 0xcb, 0x74, 0x78, 0xb7, 0x54, 0xe0, 0xba, 0xc8, 0x7d, 0x93, 0x72,
|
||||||
0xf2, 0x3f, 0xd3, 0x34, 0x47, 0x30, 0x9c, 0x47, 0x23, 0x4b, 0x0f, 0xe0, 0xc6, 0x13, 0xe6, 0xb1,
|
0x2f, 0x3c, 0xcd, 0x09, 0x8c, 0x17, 0xd1, 0x48, 0xec, 0x07, 0x70, 0xfd, 0x09, 0xf3, 0xd8, 0x9b,
|
||||||
0x37, 0x59, 0xc2, 0x40, 0xfa, 0xd6, 0x8c, 0xa9, 0x3c, 0x0a, 0xc0, 0x79, 0x25, 0x02, 0x7c, 0x07,
|
0x22, 0xa1, 0x88, 0x81, 0xe5, 0x33, 0x49, 0x37, 0x03, 0x5c, 0x74, 0x22, 0xc0, 0x77, 0x60, 0xfb,
|
||||||
0x76, 0x5e, 0xb8, 0x31, 0x5f, 0x09, 0x67, 0x7e, 0x0f, 0x90, 0x09, 0x68, 0x70, 0x6d, 0x8a, 0x5d,
|
0x85, 0x9b, 0xf0, 0x2b, 0xe1, 0xcc, 0xef, 0x01, 0x0a, 0x03, 0x05, 0xae, 0x42, 0xb1, 0x0b, 0x97,
|
||||||
0xb9, 0x9c, 0x92, 0x8b, 0x41, 0xe4, 0x76, 0x28, 0x73, 0xdb, 0x36, 0xb6, 0xa0, 0x9b, 0xf8, 0xee,
|
0x53, 0x61, 0x51, 0x73, 0x6e, 0x47, 0x42, 0x96, 0xae, 0xb1, 0x05, 0xfd, 0x34, 0x70, 0x2f, 0x5e,
|
||||||
0xd5, 0xeb, 0xc0, 0x9e, 0x32, 0x2e, 0xb2, 0x2a, 0x36, 0x45, 0xee, 0xce, 0x99, 0xe7, 0x61, 0x5e,
|
0x87, 0xf6, 0x9c, 0xf1, 0x44, 0xb4, 0x5e, 0x57, 0x48, 0x7b, 0xca, 0x3c, 0x0f, 0x6b, 0x8a, 0x4b,
|
||||||
0x71, 0x69, 0x7e, 0x01, 0xbb, 0x65, 0xfb, 0x54, 0xd6, 0xef, 0x41, 0x37, 0x8b, 0x56, 0x8c, 0xd6,
|
0xf3, 0x0b, 0xd8, 0xa9, 0xc6, 0xa7, 0x1a, 0xbc, 0x07, 0xfd, 0x42, 0xad, 0x04, 0xa3, 0x35, 0x96,
|
||||||
0x6a, 0x8b, 0xc3, 0x35, 0x80, 0xde, 0x6b, 0x8e, 0xd1, 0x22, 0xe2, 0xe6, 0x3e, 0x0c, 0x74, 0x8f,
|
0xcb, 0x35, 0x82, 0xc1, 0x6b, 0x8e, 0x6a, 0x11, 0x71, 0xf3, 0x16, 0x8c, 0xd4, 0xb0, 0x88, 0x0f,
|
||||||
0xc8, 0x03, 0x55, 0x0f, 0x16, 0x4f, 0x62, 0x72, 0x67, 0x0a, 0x2d, 0xca, 0x60, 0x5a, 0xef, 0xff,
|
0xb2, 0x5c, 0x16, 0x4f, 0x13, 0x4a, 0x67, 0x0e, 0x1d, 0x2a, 0xb8, 0x3e, 0x44, 0xff, 0x4d, 0x9f,
|
||||||
0x5d, 0xad, 0x9a, 0x1e, 0x74, 0x34, 0x9d, 0xe5, 0x39, 0x2a, 0xcd, 0x01, 0xd9, 0xa9, 0xc6, 0xdb,
|
0x9a, 0x1e, 0xf4, 0x14, 0x9d, 0xd5, 0x35, 0xaa, 0x1c, 0x08, 0x72, 0x6a, 0xdf, 0x86, 0x5e, 0x24,
|
||||||
0xd0, 0x09, 0x15, 0x4f, 0xa6, 0xec, 0x74, 0x0f, 0x07, 0x44, 0x21, 0xe5, 0x9f, 0xb9, 0xd6, 0x90,
|
0x79, 0x32, 0x19, 0xa7, 0xbf, 0x3f, 0x22, 0x0a, 0x39, 0xff, 0x22, 0xb5, 0x96, 0x88, 0x76, 0x07,
|
||||||
0xd6, 0xee, 0x40, 0xeb, 0xa5, 0x65, 0x9f, 0xa3, 0x31, 0x81, 0x6f, 0x87, 0xe4, 0x73, 0x5f, 0x08,
|
0x3a, 0x2f, 0x2d, 0xfb, 0x14, 0x83, 0x65, 0xf8, 0x76, 0x44, 0x39, 0x0f, 0x33, 0x43, 0x9f, 0xf9,
|
||||||
0xce, 0xd8, 0x2c, 0x88, 0xae, 0xa5, 0xbd, 0xba, 0xf9, 0x1d, 0x4e, 0x01, 0x15, 0x35, 0x0a, 0xf7,
|
0x61, 0x7c, 0x29, 0xe2, 0x35, 0xcd, 0xef, 0xf0, 0x04, 0x90, 0xaa, 0x91, 0xdc, 0xb7, 0xb1, 0x39,
|
||||||
0x6d, 0x2c, 0xce, 0x94, 0x67, 0x1a, 0xed, 0x8d, 0x34, 0xda, 0xda, 0x81, 0x5b, 0xd0, 0x9a, 0x29,
|
0x73, 0x9e, 0xb9, 0xda, 0x1b, 0xb9, 0xda, 0x2a, 0x81, 0x9b, 0xd0, 0xf1, 0x25, 0x3e, 0xf5, 0x6f,
|
||||||
0x7c, 0xaa, 0xdf, 0x94, 0x10, 0x59, 0x35, 0x9f, 0xc0, 0xee, 0x69, 0xe8, 0xbc, 0x69, 0xea, 0x65,
|
0x4e, 0x88, 0xa2, 0x9a, 0x4f, 0x60, 0xe7, 0x38, 0x72, 0xde, 0x74, 0xfc, 0x15, 0xa7, 0x4a, 0x3d,
|
||||||
0x93, 0xa5, 0x9a, 0xb2, 0x23, 0x37, 0xd4, 0x8c, 0xda, 0x83, 0x1b, 0x73, 0x28, 0x54, 0xb0, 0xeb,
|
0x67, 0x47, 0x69, 0xc8, 0x81, 0xda, 0x85, 0xeb, 0x0b, 0x28, 0xd4, 0xb0, 0xeb, 0x30, 0x7c, 0x7a,
|
||||||
0xd0, 0x7f, 0x7a, 0xc1, 0xb0, 0x22, 0xd2, 0x7c, 0xff, 0x59, 0x81, 0x86, 0xdc, 0x11, 0x1e, 0x0b,
|
0xc6, 0xb0, 0x23, 0xf2, 0x7a, 0xff, 0x59, 0x83, 0x96, 0xd8, 0xc9, 0x32, 0xce, 0xc8, 0x50, 0x0c,
|
||||||
0x32, 0x64, 0x43, 0xd9, 0xcb, 0xcd, 0x40, 0x8d, 0xdf, 0x2f, 0x45, 0xbb, 0x9e, 0x1f, 0x7d, 0x8d,
|
0x19, 0x4f, 0x1b, 0x58, 0x85, 0x3f, 0xac, 0xa8, 0xdd, 0xd4, 0x0f, 0x94, 0x56, 0x85, 0x60, 0x47,
|
||||||
0x12, 0xc1, 0x96, 0x54, 0x40, 0xbf, 0x29, 0x15, 0x72, 0xc6, 0xcc, 0x27, 0xa2, 0x18, 0xbe, 0xce,
|
0x38, 0x60, 0xde, 0x54, 0x8a, 0x71, 0xb7, 0x94, 0x77, 0x5e, 0x88, 0xb2, 0x7c, 0xbd, 0x15, 0xf2,
|
||||||
0x92, 0xf0, 0x15, 0x27, 0x00, 0x2c, 0x9b, 0x00, 0xbf, 0x55, 0xa0, 0xf7, 0x0d, 0xe3, 0x97, 0x41,
|
0x95, 0x4f, 0x00, 0x58, 0x75, 0x02, 0xfc, 0x56, 0x83, 0xc1, 0x37, 0x8c, 0x9f, 0x87, 0xf1, 0x3c,
|
||||||
0x34, 0x15, 0x49, 0x8a, 0x4b, 0x2d, 0x87, 0x75, 0x1a, 0x5d, 0x8d, 0xcf, 0xae, 0x39, 0x96, 0x85,
|
0x2b, 0x52, 0x52, 0x19, 0x39, 0xec, 0xd3, 0xf8, 0x62, 0x7a, 0x72, 0xc9, 0xb1, 0x2d, 0x44, 0x35,
|
||||||
0xcc, 0xa6, 0xf0, 0x07, 0x77, 0x8e, 0x2d, 0xd5, 0x68, 0x35, 0xb9, 0xb7, 0x09, 0x9d, 0x57, 0x57,
|
0xb3, 0x7c, 0x70, 0xe7, 0xd0, 0x92, 0x83, 0xd6, 0x10, 0x7b, 0x9b, 0xd0, 0x7b, 0x75, 0x31, 0xc5,
|
||||||
0x63, 0x9c, 0x82, 0x41, 0xa4, 0x7a, 0x4f, 0x8a, 0xe1, 0x96, 0x13, 0x05, 0x61, 0xc8, 0x94, 0xa7,
|
0x43, 0x2a, 0x8c, 0xe5, 0xec, 0x09, 0x33, 0xdc, 0x72, 0xe2, 0x30, 0x8a, 0x98, 0xcc, 0xb4, 0x99,
|
||||||
0x75, 0x01, 0x76, 0x92, 0x82, 0x35, 0x53, 0x29, 0xdc, 0x09, 0x09, 0xac, 0x95, 0x82, 0x9d, 0x68,
|
0x81, 0x1d, 0xe5, 0x60, 0xed, 0xdc, 0x0a, 0x77, 0x22, 0x02, 0xeb, 0xe4, 0x60, 0x47, 0x0a, 0xac,
|
||||||
0xb0, 0x76, 0x4e, 0x2c, 0x05, 0xeb, 0xc8, 0xaa, 0x9a, 0x41, 0xfb, 0x28, 0x4c, 0x4e, 0x63, 0x6b,
|
0xab, 0x99, 0xe5, 0x60, 0x3d, 0xd1, 0x55, 0x3e, 0x74, 0x0f, 0xa2, 0xf4, 0x38, 0xb1, 0x66, 0x2c,
|
||||||
0xc2, 0x44, 0xf7, 0xf3, 0x80, 0x5b, 0xde, 0x38, 0x11, 0x4b, 0x49, 0xbd, 0x6e, 0x6c, 0x43, 0x2f,
|
0x9b, 0x7e, 0x1e, 0x72, 0xcb, 0x9b, 0xa6, 0xd9, 0x52, 0x50, 0x6f, 0x1a, 0xd7, 0x60, 0x10, 0xb1,
|
||||||
0x64, 0x11, 0xd6, 0x25, 0xed, 0x56, 0x31, 0x50, 0x75, 0xe3, 0x7f, 0xb0, 0x25, 0x97, 0x63, 0xd7,
|
0x18, 0xfb, 0x92, 0x76, 0xeb, 0x28, 0x54, 0xd3, 0xf8, 0x1f, 0x6c, 0x89, 0xe5, 0xd4, 0x0d, 0xa6,
|
||||||
0x1f, 0x4f, 0x59, 0xe4, 0x33, 0x6f, 0x16, 0x38, 0x8c, 0xfc, 0xd8, 0x83, 0x4d, 0x7d, 0x28, 0x9a,
|
0x73, 0x16, 0x07, 0xcc, 0xf3, 0x43, 0x87, 0x51, 0x1e, 0xbb, 0xb0, 0xa9, 0x3e, 0x66, 0xc3, 0x28,
|
||||||
0x51, 0x1e, 0x49, 0x7f, 0xcc, 0x13, 0x18, 0x9c, 0x9c, 0xe3, 0x37, 0x97, 0x7b, 0xae, 0x3f, 0x79,
|
0x3e, 0x89, 0x7c, 0xcc, 0x23, 0x18, 0x1d, 0x9d, 0xe2, 0x8f, 0x2f, 0xf7, 0xdc, 0x60, 0xf6, 0xc4,
|
||||||
0x62, 0x71, 0x4b, 0x8c, 0x7a, 0xc4, 0x77, 0x03, 0x27, 0x26, 0x83, 0xa8, 0xcd, 0x95, 0x08, 0x73,
|
0xe2, 0x96, 0xb1, 0x8e, 0x75, 0x62, 0xb1, 0x1b, 0x3a, 0x09, 0x05, 0x44, 0x6f, 0x2e, 0x4d, 0x98,
|
||||||
0xc6, 0xe9, 0x91, 0x0a, 0x1a, 0xce, 0xf8, 0xec, 0x88, 0xbb, 0x33, 0x32, 0x68, 0xfe, 0x20, 0x9d,
|
0x33, 0xcd, 0x3f, 0x49, 0xd1, 0xf0, 0x27, 0xa1, 0xf8, 0xc4, 0x5d, 0x9f, 0x02, 0x9a, 0x3f, 0x88,
|
||||||
0x50, 0x81, 0x37, 0xa1, 0x93, 0x91, 0xad, 0xc8, 0x7c, 0xad, 0xa7, 0xf9, 0x4a, 0x1d, 0x3d, 0x80,
|
0x24, 0xa4, 0xf0, 0x26, 0xf4, 0x0a, 0xb2, 0x35, 0x51, 0xaf, 0xf5, 0xbc, 0x5e, 0x79, 0xa2, 0x7b,
|
||||||
0x75, 0xae, 0x59, 0x8c, 0xb1, 0x6a, 0x2d, 0xea, 0x8d, 0x1d, 0x92, 0x2c, 0x72, 0x34, 0x3f, 0x07,
|
0xb0, 0xce, 0x15, 0x8b, 0x29, 0x76, 0xad, 0x45, 0xb3, 0xb1, 0x4d, 0x96, 0x65, 0x8e, 0xe6, 0xe7,
|
||||||
0x78, 0x29, 0x5b, 0x51, 0x32, 0xc6, 0x79, 0x98, 0x0f, 0x10, 0x06, 0x7a, 0x66, 0x5d, 0xe9, 0xe8,
|
0x00, 0x2f, 0xc5, 0x28, 0x0a, 0xc6, 0x78, 0x1e, 0xea, 0x02, 0xa1, 0xd0, 0xbe, 0x75, 0xa1, 0xd4,
|
||||||
0x88, 0x2d, 0xf4, 0xe9, 0x47, 0xcb, 0xf5, 0x6c, 0xba, 0x0b, 0xd4, 0xcd, 0xbf, 0x2a, 0xd0, 0x55,
|
0xc9, 0xb6, 0x30, 0xa7, 0x1f, 0x2d, 0xd7, 0xb3, 0x03, 0x4e, 0x04, 0xff, 0xaa, 0x41, 0x5f, 0x22,
|
||||||
0x08, 0x8a, 0x24, 0x42, 0xd8, 0xd8, 0x7e, 0x29, 0xc4, 0x7e, 0x8a, 0x58, 0xfc, 0xc2, 0xe4, 0x6c,
|
0x48, 0x92, 0x08, 0x61, 0xe3, 0xf8, 0xe5, 0x10, 0xb7, 0x72, 0xc4, 0xf2, 0x2f, 0x8c, 0x16, 0x13,
|
||||||
0x62, 0x19, 0xc6, 0x97, 0x56, 0x48, 0x56, 0x6a, 0xcb, 0xc4, 0xee, 0x40, 0x4f, 0x65, 0x83, 0x04,
|
0xdb, 0x30, 0x39, 0xb7, 0x22, 0x8a, 0xd2, 0x58, 0x65, 0x76, 0x07, 0x06, 0xb2, 0x1a, 0x64, 0xd8,
|
||||||
0xeb, 0xcb, 0x04, 0xef, 0x89, 0xef, 0x31, 0x32, 0x91, 0xf3, 0xaf, 0x7b, 0x78, 0xb3, 0x20, 0x21,
|
0x5c, 0x65, 0x78, 0x2f, 0xfb, 0xb9, 0x44, 0x26, 0xe2, 0xfc, 0xeb, 0xef, 0xdf, 0x28, 0x59, 0x08,
|
||||||
0x39, 0x1e, 0xc8, 0xdf, 0xa7, 0x3e, 0x8f, 0xae, 0x47, 0xf7, 0x00, 0xb2, 0x95, 0x68, 0xbb, 0x29,
|
0x8e, 0x7b, 0xe2, 0xef, 0xd3, 0x80, 0xc7, 0x97, 0x93, 0x7b, 0x00, 0xc5, 0x2a, 0x1b, 0xbb, 0x39,
|
||||||
0xbb, 0xa6, 0xca, 0x46, 0x4f, 0x2e, 0x2c, 0x2f, 0x21, 0xcf, 0x1f, 0x55, 0x1f, 0x56, 0xcc, 0xaf,
|
0xbb, 0xa4, 0xce, 0xc6, 0x4c, 0xce, 0x2c, 0x2f, 0xa5, 0xcc, 0x1f, 0xd5, 0x1f, 0xd6, 0xcc, 0xaf,
|
||||||
0x61, 0xfd, 0x4b, 0x6f, 0xea, 0x06, 0x39, 0x15, 0x94, 0x9a, 0x59, 0x3f, 0x05, 0x11, 0xf9, 0x2b,
|
0x61, 0xfd, 0x4b, 0x6f, 0xee, 0x86, 0x9a, 0x0b, 0x5a, 0xf9, 0xd6, 0x4f, 0x61, 0x4c, 0xf9, 0x66,
|
||||||
0x96, 0xae, 0x8f, 0x4b, 0x15, 0x2e, 0xec, 0xfb, 0x20, 0xa4, 0x09, 0xaa, 0xf1, 0x54, 0xbd, 0xfc,
|
0x4b, 0x37, 0xc0, 0xa5, 0x94, 0x0b, 0xe7, 0x3e, 0x8c, 0xe8, 0x04, 0x55, 0x78, 0xb2, 0x5f, 0x7e,
|
||||||
0x5e, 0x03, 0xc8, 0xc0, 0x8c, 0x47, 0x30, 0x72, 0x83, 0x31, 0x96, 0xd4, 0x85, 0x6b, 0x33, 0xd5,
|
0x6f, 0x00, 0x14, 0x60, 0xc6, 0x23, 0x98, 0xb8, 0xe1, 0x14, 0x5b, 0xea, 0xcc, 0xb5, 0x99, 0x1c,
|
||||||
0x02, 0xe3, 0x88, 0xd9, 0x49, 0x14, 0xbb, 0x17, 0x8c, 0x46, 0xe0, 0x2e, 0xf9, 0x52, 0xe6, 0xf0,
|
0x81, 0x69, 0xcc, 0xec, 0x34, 0x4e, 0xdc, 0x33, 0x46, 0x47, 0xe0, 0x0e, 0xe5, 0x52, 0xe5, 0xf0,
|
||||||
0x11, 0xec, 0x64, 0xba, 0x4e, 0x4e, 0xad, 0xba, 0x52, 0xed, 0x01, 0x6c, 0xa1, 0x1a, 0x0e, 0xae,
|
0x11, 0x6c, 0x17, 0xbe, 0x8e, 0xe6, 0x56, 0xbf, 0xd2, 0xed, 0x01, 0x6c, 0xa1, 0x1b, 0x1e, 0x5c,
|
||||||
0xa4, 0xa0, 0x54, 0x5b, 0xa9, 0xf4, 0x29, 0xec, 0xe5, 0x78, 0x8a, 0x4a, 0xcd, 0xa9, 0xd6, 0x57,
|
0x69, 0xc9, 0xa9, 0x71, 0xa5, 0xd3, 0xa7, 0xb0, 0xab, 0xf1, 0xcc, 0x3a, 0x55, 0x73, 0x6d, 0x5e,
|
||||||
0xaa, 0x7e, 0x0c, 0xbb, 0xa8, 0x7a, 0x69, 0xb9, 0xbc, 0xac, 0xd7, 0xf8, 0x07, 0x3c, 0x67, 0x2c,
|
0xe9, 0xfa, 0x31, 0xec, 0xa0, 0xeb, 0xb9, 0xe5, 0xf2, 0xaa, 0x5f, 0xeb, 0x1f, 0xf0, 0xf4, 0x59,
|
||||||
0x9a, 0x14, 0x78, 0x36, 0x57, 0x2a, 0x7d, 0x00, 0x9b, 0xa8, 0x54, 0xb2, 0xd3, 0x7a, 0x93, 0x4a,
|
0x3c, 0x2b, 0xf1, 0x6c, 0x5f, 0xe9, 0xf4, 0x01, 0x6c, 0xa2, 0x53, 0x25, 0x4e, 0xe7, 0x4d, 0x2e,
|
||||||
0xcc, 0x6c, 0x8e, 0x53, 0x25, 0xa7, 0xd2, 0x5e, 0xa5, 0x62, 0x3e, 0x86, 0xde, 0xf3, 0x64, 0xc2,
|
0x09, 0xb3, 0x39, 0x9e, 0x2a, 0x9a, 0x4b, 0xf7, 0x2a, 0x17, 0xf3, 0x31, 0x0c, 0x9e, 0xa7, 0x33,
|
||||||
0xb8, 0x77, 0xa6, 0xab, 0xff, 0xdf, 0x36, 0xd0, 0x2f, 0x55, 0xe8, 0x1e, 0x4d, 0xa2, 0x20, 0x09,
|
0xc6, 0xbd, 0x13, 0xd5, 0xfd, 0xff, 0x76, 0x80, 0x7e, 0xad, 0x43, 0xff, 0x60, 0x16, 0x87, 0x69,
|
||||||
0x0b, 0x5d, 0xae, 0x6a, 0x78, 0xae, 0xcb, 0x95, 0xcc, 0x5d, 0xe8, 0xa9, 0x0f, 0x28, 0x89, 0xa9,
|
0x54, 0x9a, 0x72, 0xd9, 0xc3, 0x0b, 0x53, 0x2e, 0x6d, 0xee, 0xc2, 0x40, 0xfe, 0x80, 0x92, 0x99,
|
||||||
0xe6, 0x32, 0xe6, 0x4b, 0x5d, 0x5c, 0x5c, 0xce, 0x04, 0x67, 0x12, 0x2c, 0xb6, 0x57, 0xae, 0xfc,
|
0x1c, 0x2e, 0x63, 0xb1, 0xd5, 0xb3, 0x8b, 0xcb, 0x49, 0xc6, 0x99, 0x0c, 0xcb, 0xe3, 0xa5, 0xb5,
|
||||||
0x3e, 0x83, 0xfe, 0xb9, 0x72, 0x84, 0x24, 0x55, 0x2a, 0x6f, 0xa7, 0x96, 0x33, 0x82, 0x07, 0x79,
|
0xdf, 0x67, 0x30, 0x3c, 0x95, 0x89, 0x90, 0xa5, 0x2c, 0xe5, 0xed, 0x3c, 0x72, 0x41, 0x70, 0x4f,
|
||||||
0x87, 0x55, 0x13, 0x3d, 0x87, 0xcd, 0xb9, 0xcd, 0x62, 0x2f, 0x99, 0xf9, 0x5e, 0xea, 0x1e, 0x6e,
|
0x4f, 0x58, 0x0e, 0xd1, 0x73, 0xd8, 0x5c, 0xd8, 0x2c, 0xcf, 0x92, 0xa9, 0xcf, 0x52, 0x7f, 0x7f,
|
||||||
0x11, 0x6c, 0x5e, 0x4b, 0x36, 0x58, 0x08, 0x0d, 0xc5, 0xe7, 0x7d, 0xe8, 0xfb, 0xea, 0xa3, 0xa3,
|
0x8b, 0x60, 0x75, 0x2f, 0x31, 0x60, 0x11, 0xb4, 0x24, 0x9f, 0xf7, 0x61, 0x18, 0xc8, 0x1f, 0x1d,
|
||||||
0x23, 0x51, 0xcb, 0x29, 0x16, 0x3e, 0x48, 0x18, 0x0d, 0x5b, 0xf2, 0x5b, 0x18, 0x8d, 0x7c, 0x6c,
|
0xa5, 0x44, 0x43, 0x73, 0x2c, 0xfd, 0x20, 0xa1, 0x1a, 0xb6, 0xe0, 0xb7, 0x54, 0x0d, 0x5d, 0x5b,
|
||||||
0x31, 0x1f, 0xa2, 0x22, 0x50, 0x6c, 0x16, 0x52, 0xf8, 0x47, 0xea, 0xc6, 0xb6, 0xe8, 0xbd, 0x70,
|
0xac, 0x47, 0xd6, 0x11, 0x68, 0xe6, 0x47, 0x24, 0xff, 0x44, 0xde, 0xd8, 0x96, 0xbd, 0x15, 0xf6,
|
||||||
0xf8, 0x47, 0x03, 0x6a, 0x8f, 0x8f, 0xbf, 0x32, 0x5e, 0xc1, 0x7a, 0xe9, 0xbd, 0x63, 0xa4, 0x63,
|
0xff, 0x68, 0x41, 0xe3, 0xf1, 0xe1, 0x57, 0xc6, 0x2b, 0x58, 0xaf, 0x3c, 0x7c, 0x8c, 0xfc, 0x58,
|
||||||
0x65, 0xf1, 0xab, 0x6a, 0xf4, 0xd6, 0xb2, 0x63, 0xba, 0x38, 0xac, 0x09, 0xcc, 0xd2, 0xad, 0x42,
|
0x59, 0xfe, 0xbc, 0x9a, 0xbc, 0xb5, 0xea, 0x33, 0x5d, 0x1c, 0xd6, 0x32, 0xcc, 0xca, 0xad, 0x42,
|
||||||
0x63, 0x2e, 0xbe, 0xb3, 0x68, 0xcc, 0x65, 0x97, 0x91, 0x35, 0xe3, 0x13, 0x68, 0xaa, 0x37, 0x91,
|
0x61, 0x2e, 0xbf, 0xb3, 0x28, 0xcc, 0x55, 0x97, 0x91, 0x35, 0xe3, 0x13, 0x68, 0xcb, 0xf7, 0x90,
|
||||||
0xb1, 0x4d, 0xb2, 0x85, 0xc7, 0xd5, 0x68, 0xa7, 0xb4, 0xab, 0x15, 0x8f, 0x00, 0xb2, 0x97, 0x84,
|
0x71, 0x8d, 0x6c, 0x4b, 0x0f, 0xab, 0xc9, 0x76, 0x65, 0x57, 0x39, 0x1e, 0x00, 0x14, 0x0f, 0x0f,
|
||||||
0x31, 0x24, 0xb1, 0xb9, 0xc7, 0xd4, 0x68, 0x6f, 0xc1, 0x89, 0x06, 0x39, 0x85, 0x8d, 0xf2, 0x53,
|
0x63, 0x4c, 0x66, 0x0b, 0x0f, 0xa9, 0xc9, 0xee, 0x92, 0x2f, 0x0a, 0xe4, 0x18, 0x36, 0xaa, 0x4f,
|
||||||
0xc1, 0x28, 0xc5, 0xa1, 0x7c, 0xb1, 0x1f, 0xdd, 0x5a, 0x7a, 0x9e, 0x87, 0x2d, 0x3f, 0x18, 0x34,
|
0x05, 0xa3, 0xa2, 0x43, 0xf5, 0x62, 0x3f, 0xb9, 0xb9, 0xf2, 0xbb, 0x0e, 0x5b, 0x7d, 0x30, 0x28,
|
||||||
0xec, 0x92, 0xe7, 0x87, 0x86, 0x5d, 0xfa, 0xd2, 0x58, 0x33, 0xbe, 0x85, 0x41, 0xf1, 0xae, 0x6f,
|
0xd8, 0x15, 0xcf, 0x0f, 0x05, 0xbb, 0xf2, 0xa5, 0xb1, 0x66, 0x7c, 0x0b, 0xa3, 0xf2, 0x5d, 0xdf,
|
||||||
0xfc, 0x9f, 0x94, 0x16, 0x3e, 0x41, 0x46, 0x37, 0x97, 0x9c, 0x6a, 0xc0, 0x0f, 0x55, 0xe9, 0xe2,
|
0xf8, 0x3f, 0x39, 0x2d, 0x7d, 0x82, 0x4c, 0x6e, 0xac, 0xf8, 0xaa, 0x00, 0x3f, 0x94, 0xad, 0x8b,
|
||||||
0x5d, 0x23, 0x8d, 0x72, 0xee, 0x21, 0x30, 0xda, 0x2e, 0x6e, 0x6a, 0xad, 0xfb, 0xd0, 0x54, 0x37,
|
0x77, 0x8d, 0x5c, 0x65, 0xed, 0x21, 0x30, 0xb9, 0x56, 0xde, 0x54, 0x5e, 0xf7, 0xa1, 0x2d, 0x6f,
|
||||||
0x48, 0x9d, 0xb2, 0xc2, 0x85, 0x72, 0xd4, 0xcb, 0xef, 0x9a, 0x6b, 0xf7, 0x2b, 0x38, 0xa5, 0xda,
|
0x90, 0xaa, 0x64, 0xa5, 0x0b, 0xe5, 0x64, 0xa0, 0xef, 0x9a, 0x6b, 0xf7, 0x6b, 0x78, 0x4a, 0x75,
|
||||||
0xcf, 0x18, 0x57, 0xf5, 0x9c, 0x37, 0x35, 0xa7, 0x22, 0x37, 0x85, 0xca, 0x59, 0x53, 0xfe, 0x17,
|
0x9f, 0x31, 0x2e, 0xfb, 0x59, 0x0f, 0xb5, 0xe0, 0x22, 0x36, 0x33, 0x97, 0x93, 0xb6, 0xf8, 0xa7,
|
||||||
0xf0, 0xe0, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x15, 0x52, 0xba, 0x18, 0x10, 0x00, 0x00,
|
0xc0, 0x83, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x0f, 0x82, 0xdf, 0x21, 0x10, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ message CreateContainerRequest {
|
||||||
|
|
||||||
message CreateContainerResponse {
|
message CreateContainerResponse {
|
||||||
uint32 pid = 1; // PID of the containers main process
|
uint32 pid = 1; // PID of the containers main process
|
||||||
string stdin = 1; // path to the file where stdin will be read (optional)
|
string stdin = 2; // path to the file where stdin will be read (optional)
|
||||||
string stdout = 2; // path to file where stdout will be written (optional)
|
string stdout = 3; // path to file where stdout will be written (optional)
|
||||||
string stderr = 3; // path to file where stderr will be written (optional)
|
string stderr = 4; // path to file where stderr will be written (optional)
|
||||||
}
|
}
|
||||||
|
|
||||||
message SignalRequest {
|
message SignalRequest {
|
||||||
|
@ -44,10 +44,7 @@ message AddProcessRequest {
|
||||||
repeated string args = 4; // Arguments for process, first is binary path itself
|
repeated string args = 4; // Arguments for process, first is binary path itself
|
||||||
repeated string env = 5; // List of environment variables for process
|
repeated string env = 5; // List of environment variables for process
|
||||||
string cwd = 6; // Workind directory of process
|
string cwd = 6; // Workind directory of process
|
||||||
string stdin = 7; // path to the file where stdin will be read (optional)
|
string pid = 7; // Process ID
|
||||||
string stdout = 8; // path to file where stdout will be written (optional)
|
|
||||||
string stderr = 9; // path to file where stderr will be written (optional)
|
|
||||||
string console = 10; // path to the console for a container (optional)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
message User {
|
message User {
|
||||||
|
@ -57,6 +54,9 @@ message User {
|
||||||
}
|
}
|
||||||
|
|
||||||
message AddProcessResponse {
|
message AddProcessResponse {
|
||||||
|
string stdin = 1; // path to the file where stdin will be read (optional)
|
||||||
|
string stdout = 2; // path to file where stdout will be written (optional)
|
||||||
|
string stderr = 3; // path to file where stderr will be written (optional)
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateCheckpointRequest {
|
message CreateCheckpointRequest {
|
||||||
|
|
0
containerd-shim/example/config.json
Normal file
0
containerd-shim/example/config.json
Normal file
0
containerd-shim/example/init/exit
Normal file
0
containerd-shim/example/init/exit
Normal file
0
containerd-shim/example/init/pid
Normal file
0
containerd-shim/example/init/pid
Normal file
0
containerd-shim/example/init/process.json
Normal file
0
containerd-shim/example/init/process.json
Normal file
0
containerd-shim/example/init/resize
Normal file
0
containerd-shim/example/init/resize
Normal file
0
containerd-shim/example/init/stderr
Normal file
0
containerd-shim/example/init/stderr
Normal file
0
containerd-shim/example/init/stdin
Normal file
0
containerd-shim/example/init/stdin
Normal file
0
containerd-shim/example/init/stdout
Normal file
0
containerd-shim/example/init/stdout
Normal file
0
containerd-shim/example/logger/exit
Normal file
0
containerd-shim/example/logger/exit
Normal file
0
containerd-shim/example/logger/pid
Normal file
0
containerd-shim/example/logger/pid
Normal file
0
containerd-shim/example/logger/process.json
Normal file
0
containerd-shim/example/logger/process.json
Normal file
0
containerd-shim/example/logger/resize
Normal file
0
containerd-shim/example/logger/resize
Normal file
0
containerd-shim/example/logger/stderr
Normal file
0
containerd-shim/example/logger/stderr
Normal file
0
containerd-shim/example/logger/stdin
Normal file
0
containerd-shim/example/logger/stdin
Normal file
0
containerd-shim/example/logger/stdout
Normal file
0
containerd-shim/example/logger/stdout
Normal file
|
@ -1,43 +1,21 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/containerd/util"
|
"github.com/docker/containerd/util"
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
|
||||||
"github.com/opencontainers/specs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var fexec bool
|
||||||
bufferSize = 2048
|
|
||||||
)
|
|
||||||
|
|
||||||
type stdio struct {
|
func init() {
|
||||||
stdin *os.File
|
flag.BoolVar(&fexec, "exec", false, "exec a process instead of starting the init")
|
||||||
stdout *os.File
|
flag.Parse()
|
||||||
stderr *os.File
|
|
||||||
console string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stdio) Close() error {
|
|
||||||
err := s.stdin.Close()
|
|
||||||
if oerr := s.stdout.Close(); err == nil {
|
|
||||||
err = oerr
|
|
||||||
}
|
|
||||||
if oerr := s.stderr.Close(); err == nil {
|
|
||||||
err = oerr
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// containerd-shim is a small shim that sits in front of a runc implementation
|
// containerd-shim is a small shim that sits in front of a runc implementation
|
||||||
|
@ -45,41 +23,27 @@ func (s *stdio) Close() error {
|
||||||
//
|
//
|
||||||
// the cwd of the shim should be the bundle for the container. Arg1 should be the path
|
// the cwd of the shim should be the bundle for the container. Arg1 should be the path
|
||||||
// to the state directory where the shim can locate fifos and other information.
|
// to the state directory where the shim can locate fifos and other information.
|
||||||
//
|
|
||||||
// └── shim
|
|
||||||
// ├── control
|
|
||||||
// ├── stderr
|
|
||||||
// ├── stdin
|
|
||||||
// ├── stdout
|
|
||||||
// ├── pid
|
|
||||||
// └── exit
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
|
||||||
logrus.Fatal("shim: no arguments provided")
|
|
||||||
}
|
|
||||||
// start handling signals as soon as possible so that things are properly reaped
|
// start handling signals as soon as possible so that things are properly reaped
|
||||||
// or if runc exits before we hit the handler
|
// or if runc exits before we hit the handler
|
||||||
signals := make(chan os.Signal, bufferSize)
|
signals := make(chan os.Signal, 2048)
|
||||||
signal.Notify(signals)
|
signal.Notify(signals)
|
||||||
// set the shim as the subreaper for all orphaned processes created by the container
|
// set the shim as the subreaper for all orphaned processes created by the container
|
||||||
if err := util.SetSubreaper(1); err != nil {
|
if err := util.SetSubreaper(1); err != nil {
|
||||||
logrus.WithField("error", err).Fatal("shim: set as subreaper")
|
logrus.WithField("error", err).Fatal("shim: set as subreaper")
|
||||||
}
|
}
|
||||||
// open the exit pipe
|
// open the exit pipe
|
||||||
f, err := os.OpenFile(filepath.Join(os.Args[1], "exit"), syscall.O_WRONLY, 0)
|
f, err := os.OpenFile("exit", syscall.O_WRONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithField("error", err).Fatal("shim: open exit pipe")
|
logrus.WithField("error", err).Fatal("shim: open exit pipe")
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
// open the fifos for use with the command
|
p, err := newProcess(flag.Arg(0), flag.Arg(1), fexec)
|
||||||
std, err := openContainerSTDIO(os.Args[1])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithField("error", err).Fatal("shim: open container STDIO from fifo")
|
logrus.WithField("error", err).Fatal("shim: create new process")
|
||||||
}
|
}
|
||||||
// star the container process by invoking runc
|
if err := p.start(); err != nil {
|
||||||
runcPid, err := startRunc(std, os.Args[2])
|
logrus.WithField("error", err).Fatal("shim: start process")
|
||||||
if err != nil {
|
|
||||||
logrus.WithField("error", err).Fatal("shim: start runc")
|
|
||||||
}
|
}
|
||||||
var exitShim bool
|
var exitShim bool
|
||||||
for s := range signals {
|
for s := range signals {
|
||||||
|
@ -92,22 +56,27 @@ func main() {
|
||||||
}
|
}
|
||||||
for _, e := range exits {
|
for _, e := range exits {
|
||||||
// check to see if runc is one of the processes that has exited
|
// check to see if runc is one of the processes that has exited
|
||||||
if e.Pid == runcPid {
|
if e.Pid == p.pid() {
|
||||||
exitShim = true
|
exitShim = true
|
||||||
logrus.WithFields(logrus.Fields{"pid": e.Pid, "status": e.Status}).Info("shim: runc exited")
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"pid": e.Pid,
|
||||||
if err := writeInt(filepath.Join(os.Args[1], "exitStatus"), e.Status); err != nil {
|
"status": e.Status,
|
||||||
logrus.WithFields(logrus.Fields{"error": err, "status": e.Status}).Error("shim: write exit status")
|
}).Info("shim: runc exited")
|
||||||
|
if err := writeInt("exitStatus", e.Status); err != nil {
|
||||||
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"error": err,
|
||||||
|
"status": e.Status,
|
||||||
|
}).Error("shim: write exit status")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// runc has exited so the shim can also exit
|
// runc has exited so the shim can also exit
|
||||||
if exitShim {
|
if exitShim {
|
||||||
if err := std.Close(); err != nil {
|
if err := p.Close(); err != nil {
|
||||||
logrus.WithField("error", err).Error("shim: close stdio")
|
logrus.WithField("error", err).Error("shim: close stdio")
|
||||||
}
|
}
|
||||||
if err := deleteContainer(os.Args[2]); err != nil {
|
if err := p.delete(); err != nil {
|
||||||
logrus.WithField("error", err).Error("shim: delete runc state")
|
logrus.WithField("error", err).Error("shim: delete runc state")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -115,90 +84,6 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// startRunc starts runc detached and returns the container's pid
|
|
||||||
func startRunc(s *stdio, id string) (int, error) {
|
|
||||||
pidFile := filepath.Join(os.Args[1], "pid")
|
|
||||||
cmd := exec.Command("runc", "--id", id, "start", "-d", "--console", s.console, "--pid-file", pidFile)
|
|
||||||
cmd.Stdin = s.stdin
|
|
||||||
cmd.Stdout = s.stdout
|
|
||||||
cmd.Stderr = s.stderr
|
|
||||||
// set the parent death signal to SIGKILL so that if the shim dies the container
|
|
||||||
// process also dies
|
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
||||||
Pdeathsig: syscall.SIGKILL,
|
|
||||||
}
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
data, err := ioutil.ReadFile(pidFile)
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
return strconv.Atoi(string(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteContainer(id string) error {
|
|
||||||
return exec.Command("runc", "--id", id, "delete").Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// openContainerSTDIO opens the pre-created fifo's for use with the container
|
|
||||||
// in RDWR so that they remain open if the other side stops listening
|
|
||||||
func openContainerSTDIO(dir string) (*stdio, error) {
|
|
||||||
s := &stdio{}
|
|
||||||
spec, err := getSpec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if spec.Process.Terminal {
|
|
||||||
console, err := libcontainer.NewConsole(int(spec.Process.User.UID), int(spec.Process.User.GID))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.console = console.Path()
|
|
||||||
stdin, err := os.OpenFile(filepath.Join(dir, "stdin"), syscall.O_RDWR, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
io.Copy(console, stdin)
|
|
||||||
}()
|
|
||||||
stdout, err := os.OpenFile(filepath.Join(dir, "stdout"), syscall.O_RDWR, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
io.Copy(stdout, console)
|
|
||||||
console.Close()
|
|
||||||
}()
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
for name, dest := range map[string]**os.File{
|
|
||||||
"stdin": &s.stdin,
|
|
||||||
"stdout": &s.stdout,
|
|
||||||
"stderr": &s.stderr,
|
|
||||||
} {
|
|
||||||
f, err := os.OpenFile(filepath.Join(dir, name), syscall.O_RDWR, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
*dest = f
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSpec() (*specs.Spec, error) {
|
|
||||||
var s specs.Spec
|
|
||||||
f, err := os.Open("config.json")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if err := json.NewDecoder(f).Decode(&s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeInt(path string, i int) error {
|
func writeInt(path string, i int) error {
|
||||||
f, err := os.Create(path)
|
f, err := os.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
165
containerd-shim/process.go
Normal file
165
containerd-shim/process.go
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer"
|
||||||
|
"github.com/opencontainers/specs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type process struct {
|
||||||
|
id string
|
||||||
|
bundle string
|
||||||
|
stdio *stdio
|
||||||
|
s specs.Process
|
||||||
|
exec bool
|
||||||
|
containerPid int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProcess(id, bundle string, exec bool) (*process, error) {
|
||||||
|
f, err := os.Open("process.json")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
p := &process{
|
||||||
|
id: id,
|
||||||
|
bundle: bundle,
|
||||||
|
exec: exec,
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(f).Decode(&p.s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := p.openIO(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *process) start() error {
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
args := []string{
|
||||||
|
"--id", p.id,
|
||||||
|
}
|
||||||
|
if p.exec {
|
||||||
|
args = append(args, "exec",
|
||||||
|
"--process", filepath.Join(cwd, "process.json"))
|
||||||
|
} else {
|
||||||
|
args = append(args, "start",
|
||||||
|
"--bundle", p.bundle)
|
||||||
|
}
|
||||||
|
args = append(args,
|
||||||
|
"-d",
|
||||||
|
"--console", p.stdio.console,
|
||||||
|
"--pid-file", filepath.Join(cwd, "pid"),
|
||||||
|
)
|
||||||
|
cmd := exec.Command("runc", args...)
|
||||||
|
cmd.Stdin = p.stdio.stdin
|
||||||
|
cmd.Stdout = p.stdio.stdout
|
||||||
|
cmd.Stderr = p.stdio.stderr
|
||||||
|
// set the parent death signal to SIGKILL so that if the shim dies the container
|
||||||
|
// process also dies
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Pdeathsig: syscall.SIGKILL,
|
||||||
|
}
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadFile("pid")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pid, err := strconv.Atoi(string(data))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.containerPid = pid
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *process) pid() int {
|
||||||
|
return p.containerPid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *process) delete() error {
|
||||||
|
if !p.exec {
|
||||||
|
return exec.Command("runc", "--id", p.id, "delete").Run()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// openIO opens the pre-created fifo's for use with the container
|
||||||
|
// in RDWR so that they remain open if the other side stops listening
|
||||||
|
func (p *process) openIO() error {
|
||||||
|
p.stdio = &stdio{}
|
||||||
|
if p.s.Terminal {
|
||||||
|
// FIXME: this is wrong for user namespaces and will need to be translated
|
||||||
|
console, err := libcontainer.NewConsole(int(p.s.User.UID), int(p.s.User.GID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.stdio.console = console.Path()
|
||||||
|
stdin, err := os.OpenFile("stdin", syscall.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
io.Copy(console, stdin)
|
||||||
|
}()
|
||||||
|
stdout, err := os.OpenFile("stdout", syscall.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
io.Copy(stdout, console)
|
||||||
|
console.Close()
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// non-tty
|
||||||
|
for name, dest := range map[string]**os.File{
|
||||||
|
"stdin": &p.stdio.stdin,
|
||||||
|
"stdout": &p.stdio.stdout,
|
||||||
|
"stderr": &p.stdio.stderr,
|
||||||
|
} {
|
||||||
|
f, err := os.OpenFile(name, syscall.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*dest = f
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *process) Close() error {
|
||||||
|
return p.stdio.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type stdio struct {
|
||||||
|
stdin *os.File
|
||||||
|
stdout *os.File
|
||||||
|
stderr *os.File
|
||||||
|
console string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stdio) Close() error {
|
||||||
|
err := s.stdin.Close()
|
||||||
|
if oerr := s.stdout.Close(); err == nil {
|
||||||
|
err = oerr
|
||||||
|
}
|
||||||
|
if oerr := s.stderr.Close(); err == nil {
|
||||||
|
err = oerr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
100
ctr/container.go
100
ctr/container.go
|
@ -145,7 +145,7 @@ var attachCommand = cli.Command{
|
||||||
io.Copy(stdin, os.Stdin)
|
io.Copy(stdin, os.Stdin)
|
||||||
closer()
|
closer()
|
||||||
}()
|
}()
|
||||||
if err := waitForExit(c, id, closer); err != nil {
|
if err := waitForExit(c, id, "init", closer); err != nil {
|
||||||
fatal(err.Error(), 1)
|
fatal(err.Error(), 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -217,7 +217,7 @@ var startCommand = cli.Command{
|
||||||
io.Copy(stdin, os.Stdin)
|
io.Copy(stdin, os.Stdin)
|
||||||
restoreAndCloseStdin()
|
restoreAndCloseStdin()
|
||||||
}()
|
}()
|
||||||
if err := waitForExit(c, id, restoreAndCloseStdin); err != nil {
|
if err := waitForExit(c, id, "init", restoreAndCloseStdin); err != nil {
|
||||||
fatal(err.Error(), 1)
|
fatal(err.Error(), 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,6 +303,10 @@ var execCommand = cli.Command{
|
||||||
Name: "id",
|
Name: "id",
|
||||||
Usage: "container id to add the process to",
|
Usage: "container id to add the process to",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "pid",
|
||||||
|
Usage: "process id for the new process",
|
||||||
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "attach,a",
|
Name: "attach,a",
|
||||||
Usage: "connect to the stdio of the container",
|
Usage: "connect to the stdio of the container",
|
||||||
|
@ -330,58 +334,50 @@ var execCommand = cli.Command{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: func(context *cli.Context) {
|
Action: func(context *cli.Context) {
|
||||||
panic("not implemented")
|
p := &types.AddProcessRequest{
|
||||||
/*
|
Pid: context.String("pid"),
|
||||||
p := &types.AddProcessRequest{
|
Args: context.Args(),
|
||||||
Args: context.Args(),
|
Cwd: context.String("cwd"),
|
||||||
Cwd: context.String("cwd"),
|
Terminal: context.Bool("tty"),
|
||||||
Terminal: context.Bool("tty"),
|
Id: context.String("id"),
|
||||||
Id: context.String("id"),
|
Env: context.StringSlice("env"),
|
||||||
Env: context.StringSlice("env"),
|
User: &types.User{
|
||||||
User: &types.User{
|
Uid: uint32(context.Int("uid")),
|
||||||
Uid: uint32(context.Int("uid")),
|
Gid: uint32(context.Int("gid")),
|
||||||
Gid: uint32(context.Int("gid")),
|
},
|
||||||
},
|
}
|
||||||
}
|
c := getClient(context)
|
||||||
c := getClient(context)
|
resp, err := c.AddProcess(netcontext.Background(), p)
|
||||||
events, err := c.Events(netcontext.Background(), &types.EventsRequest{})
|
if err != nil {
|
||||||
if err != nil {
|
fatal(err.Error(), 1)
|
||||||
fatal(err.Error(), 1)
|
}
|
||||||
}
|
if context.Bool("attach") {
|
||||||
if context.Bool("attach") {
|
if context.Bool("tty") {
|
||||||
if p.Terminal {
|
s, err := term.SetRawTerminal(os.Stdin.Fd())
|
||||||
if err := attachTty(&p.Console); err != nil {
|
|
||||||
fatal(err.Error(), 1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := attachStdio(&p.Stdin, &p.Stdout, &p.Stderr); err != nil {
|
|
||||||
fatal(err.Error(), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r, err := c.AddProcess(netcontext.Background(), p)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err.Error(), 1)
|
fatal(err.Error(), 1)
|
||||||
}
|
}
|
||||||
if context.Bool("attach") {
|
state = s
|
||||||
go func() {
|
}
|
||||||
io.Copy(stdin, os.Stdin)
|
if err := attachStdio(resp.Stdin, resp.Stdout, resp.Stderr); err != nil {
|
||||||
if state != nil {
|
fatal(err.Error(), 1)
|
||||||
term.RestoreTerminal(os.Stdin.Fd(), state)
|
}
|
||||||
}
|
}
|
||||||
stdin.Close()
|
if context.Bool("attach") {
|
||||||
}()
|
restoreAndCloseStdin := func() {
|
||||||
for {
|
if state != nil {
|
||||||
e, err := events.Recv()
|
term.RestoreTerminal(os.Stdin.Fd(), state)
|
||||||
if err != nil {
|
|
||||||
fatal(err.Error(), 1)
|
|
||||||
}
|
|
||||||
if e.Pid == r.Pid && e.Type == "exit" {
|
|
||||||
os.Exit(int(e.Status))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
stdin.Close()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
io.Copy(stdin, os.Stdin)
|
||||||
|
restoreAndCloseStdin()
|
||||||
|
}()
|
||||||
|
if err := waitForExit(c, context.String("id"), context.String("pid"), restoreAndCloseStdin); err != nil {
|
||||||
|
fatal(err.Error(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +403,7 @@ var statsCommand = cli.Command{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForExit(c types.APIClient, id string, closer func()) error {
|
func waitForExit(c types.APIClient, id, pid string, closer func()) error {
|
||||||
events, err := c.Events(netcontext.Background(), &types.EventsRequest{})
|
events, err := c.Events(netcontext.Background(), &types.EventsRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -419,7 +415,7 @@ func waitForExit(c types.APIClient, id string, closer func()) error {
|
||||||
events, _ = c.Events(netcontext.Background(), &types.EventsRequest{})
|
events, _ = c.Events(netcontext.Background(), &types.EventsRequest{})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if e.Id == id && e.Type == "exit" && e.Pid == "init" {
|
if e.Id == id && e.Type == "exit" && e.Pid == pid {
|
||||||
closer()
|
closer()
|
||||||
os.Exit(int(e.Status))
|
os.Exit(int(e.Status))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +1,17 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/opencontainers/specs"
|
"github.com/opencontainers/specs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Process interface {
|
|
||||||
io.Closer
|
|
||||||
|
|
||||||
// ID of the process.
|
|
||||||
// This is either "init" when it is the container's init process or
|
|
||||||
// it is a user provided id for the process similar to the container id
|
|
||||||
ID() string
|
|
||||||
// Stdin returns the path the the processes stdin fifo
|
|
||||||
Stdin() string
|
|
||||||
// Stdout returns the path the the processes stdout fifo
|
|
||||||
Stdout() string
|
|
||||||
// Stderr returns the path the the processes stderr fifo
|
|
||||||
Stderr() string
|
|
||||||
// ExitFD returns the fd the provides an event when the process exits
|
|
||||||
ExitFD() int
|
|
||||||
// ExitStatus returns the exit status of the process or an error if it
|
|
||||||
// has not exited
|
|
||||||
ExitStatus() (int, error)
|
|
||||||
Spec() specs.Process
|
|
||||||
// Signal sends the provided signal to the process
|
|
||||||
Signal(os.Signal) error
|
|
||||||
// Container returns the container that the process belongs to
|
|
||||||
Container() Container
|
|
||||||
}
|
|
||||||
|
|
||||||
type State string
|
|
||||||
|
|
||||||
const (
|
|
||||||
Paused = State("paused")
|
|
||||||
Running = State("running")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Console interface {
|
|
||||||
io.ReadWriter
|
|
||||||
io.Closer
|
|
||||||
}
|
|
||||||
|
|
||||||
type IO struct {
|
|
||||||
Stdin io.WriteCloser
|
|
||||||
Stdout io.ReadCloser
|
|
||||||
Stderr io.ReadCloser
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IO) Close() error {
|
|
||||||
var oerr error
|
|
||||||
for _, c := range []io.Closer{
|
|
||||||
i.Stdin,
|
|
||||||
i.Stdout,
|
|
||||||
i.Stderr,
|
|
||||||
} {
|
|
||||||
if c != nil {
|
|
||||||
if err := c.Close(); oerr == nil {
|
|
||||||
oerr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return oerr
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stat struct {
|
|
||||||
// Timestamp is the time that the statistics where collected
|
|
||||||
Timestamp time.Time
|
|
||||||
// Data is the raw stats
|
|
||||||
// TODO: it is currently an interface because we don't know what type of exec drivers
|
|
||||||
// we will have or what the structure should look like at the moment os the containers
|
|
||||||
// can return what they want and we could marshal to json or whatever.
|
|
||||||
Data interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Checkpoint struct {
|
|
||||||
// Timestamp is the time that checkpoint happened
|
|
||||||
Timestamp time.Time
|
|
||||||
// Name is the name of the checkpoint
|
|
||||||
Name string
|
|
||||||
// Tcp checkpoints open tcp connections
|
|
||||||
Tcp bool
|
|
||||||
// UnixSockets persists unix sockets in the checkpoint
|
|
||||||
UnixSockets bool
|
|
||||||
// Shell persists tty sessions in the checkpoint
|
|
||||||
Shell bool
|
|
||||||
// Exit exits the container after the checkpoint is finished
|
|
||||||
Exit bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Container interface {
|
type Container interface {
|
||||||
// ID returns the container ID
|
// ID returns the container ID
|
||||||
ID() string
|
ID() string
|
||||||
|
@ -99,10 +19,10 @@ type Container interface {
|
||||||
Path() string
|
Path() string
|
||||||
// Start starts the init process of the container
|
// Start starts the init process of the container
|
||||||
Start() (Process, error)
|
Start() (Process, error)
|
||||||
|
// Exec starts another process in an existing container
|
||||||
|
Exec(string, specs.Process) (Process, error)
|
||||||
// Delete removes the container's state and any resources
|
// Delete removes the container's state and any resources
|
||||||
Delete() error
|
Delete() error
|
||||||
// Pid returns the container's init process id
|
|
||||||
// Pid() (int, error)
|
|
||||||
// Processes returns all the containers processes that have been added
|
// Processes returns all the containers processes that have been added
|
||||||
Processes() ([]Process, error)
|
Processes() ([]Process, error)
|
||||||
// State returns the containers runtime state
|
// State returns the containers runtime state
|
||||||
|
@ -111,6 +31,7 @@ type Container interface {
|
||||||
Resume() error
|
Resume() error
|
||||||
// Pause pauses a running container
|
// Pause pauses a running container
|
||||||
Pause() error
|
Pause() error
|
||||||
|
RemoveProcess(string) error
|
||||||
// Checkpoints returns all the checkpoints for a container
|
// Checkpoints returns all the checkpoints for a container
|
||||||
// Checkpoints() ([]Checkpoint, error)
|
// Checkpoints() ([]Checkpoint, error)
|
||||||
// Checkpoint creates a new checkpoint
|
// Checkpoint creates a new checkpoint
|
||||||
|
@ -124,3 +45,183 @@ type Container interface {
|
||||||
// OOM signals the channel if the container received an OOM notification
|
// OOM signals the channel if the container received an OOM notification
|
||||||
// OOM() (<-chan struct{}, error)
|
// OOM() (<-chan struct{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New returns a new container
|
||||||
|
func New(root, id, bundle string) (Container, error) {
|
||||||
|
c := &container{
|
||||||
|
root: root,
|
||||||
|
id: id,
|
||||||
|
bundle: bundle,
|
||||||
|
processes: make(map[string]*process),
|
||||||
|
}
|
||||||
|
if err := os.Mkdir(filepath.Join(root, id), 0755); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f, err := os.Create(filepath.Join(root, id, StateFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := json.NewEncoder(f).Encode(state{
|
||||||
|
Bundle: bundle,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Load(root, id string) (Container, error) {
|
||||||
|
var s state
|
||||||
|
f, err := os.Open(filepath.Join(root, id, StateFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := json.NewDecoder(f).Decode(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c := &container{
|
||||||
|
root: root,
|
||||||
|
id: id,
|
||||||
|
bundle: s.Bundle,
|
||||||
|
processes: make(map[string]*process),
|
||||||
|
}
|
||||||
|
dirs, err := ioutil.ReadDir(filepath.Join(root, id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, d := range dirs {
|
||||||
|
if !d.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pid := d.Name()
|
||||||
|
s, err := readProcessSpec(filepath.Join(root, id, pid))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p, err := loadProcess(filepath.Join(root, id, pid), pid, c, *s)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithField("id", id).WithField("pid", pid).Debug("containerd: error loading process %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.processes[pid] = p
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readProcessSpec(dir string) (*specs.Process, error) {
|
||||||
|
f, err := os.Open(filepath.Join(dir, "process.json"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
var s specs.Process
|
||||||
|
if err := json.NewDecoder(f).Decode(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type container struct {
|
||||||
|
// path to store runtime state information
|
||||||
|
root string
|
||||||
|
id string
|
||||||
|
bundle string
|
||||||
|
processes map[string]*process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) ID() string {
|
||||||
|
return c.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Path() string {
|
||||||
|
return c.bundle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Start() (Process, error) {
|
||||||
|
processRoot := filepath.Join(c.root, c.id, InitProcessID)
|
||||||
|
if err := os.MkdirAll(processRoot, 0755); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cmd := exec.Command("containerd-shim", c.id, c.bundle)
|
||||||
|
cmd.Dir = processRoot
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setpgid: true,
|
||||||
|
}
|
||||||
|
spec, err := c.readSpec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p, err := newProcess(processRoot, InitProcessID, c, spec.Process)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.processes[InitProcessID] = p
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Exec(pid string, spec specs.Process) (Process, error) {
|
||||||
|
processRoot := filepath.Join(c.root, c.id, pid)
|
||||||
|
if err := os.MkdirAll(processRoot, 0755); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cmd := exec.Command("containerd-shim", "-exec", c.id, c.bundle)
|
||||||
|
cmd.Dir = processRoot
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setpgid: true,
|
||||||
|
}
|
||||||
|
p, err := newProcess(processRoot, pid, c, spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.processes[pid] = p
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) readSpec() (*specs.LinuxSpec, error) {
|
||||||
|
var spec specs.LinuxSpec
|
||||||
|
f, err := os.Open(filepath.Join(c.bundle, "config.json"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := json.NewDecoder(f).Decode(&spec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Pause() error {
|
||||||
|
return exec.Command("runc", "--id", c.id, "pause").Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Resume() error {
|
||||||
|
return exec.Command("runc", "--id", c.id, "resume").Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) State() State {
|
||||||
|
return Running
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Delete() error {
|
||||||
|
return os.RemoveAll(filepath.Join(c.root, c.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) Processes() ([]Process, error) {
|
||||||
|
out := []Process{}
|
||||||
|
for _, p := range c.processes {
|
||||||
|
out = append(out, p)
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *container) RemoveProcess(pid string) error {
|
||||||
|
delete(c.processes, pid)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
172
runtime/lib.go
172
runtime/lib.go
|
@ -1,172 +0,0 @@
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
"github.com/opencontainers/specs"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ExitFile = "exit"
|
|
||||||
ExitStatusFile = "exitStatus"
|
|
||||||
StateFile = "state.json"
|
|
||||||
InitProcessID = "init"
|
|
||||||
)
|
|
||||||
|
|
||||||
type state struct {
|
|
||||||
Bundle string `json:"bundle"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new container
|
|
||||||
func New(root, id, bundle string) (Container, error) {
|
|
||||||
c := &container{
|
|
||||||
root: root,
|
|
||||||
id: id,
|
|
||||||
bundle: bundle,
|
|
||||||
processes: make(map[string]*process),
|
|
||||||
}
|
|
||||||
if err := os.Mkdir(filepath.Join(root, id), 0755); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
f, err := os.Create(filepath.Join(root, id, StateFile))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if err := json.NewEncoder(f).Encode(state{
|
|
||||||
Bundle: bundle,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Load(root, id string) (Container, error) {
|
|
||||||
var s state
|
|
||||||
f, err := os.Open(filepath.Join(root, id, StateFile))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if err := json.NewDecoder(f).Decode(&s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c := &container{
|
|
||||||
root: root,
|
|
||||||
id: id,
|
|
||||||
bundle: s.Bundle,
|
|
||||||
processes: make(map[string]*process),
|
|
||||||
}
|
|
||||||
dirs, err := ioutil.ReadDir(filepath.Join(root, id))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, d := range dirs {
|
|
||||||
if !d.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pid := d.Name()
|
|
||||||
// TODO: get the process spec from a state file in the process dir
|
|
||||||
p, err := loadProcess(filepath.Join(root, id, pid), pid, c, specs.Process{})
|
|
||||||
if err != nil {
|
|
||||||
if err == ErrProcessExited {
|
|
||||||
logrus.WithField("id", id).WithField("pid", pid).Debug("containerd: process exited while away")
|
|
||||||
// TODO: fire events to do the removal
|
|
||||||
if err := os.RemoveAll(filepath.Join(root, id, pid)); err != nil {
|
|
||||||
logrus.WithField("error", err).Warn("containerd: remove process state")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.processes[pid] = p
|
|
||||||
}
|
|
||||||
if len(c.processes) == 0 {
|
|
||||||
return nil, ErrContainerExited
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type container struct {
|
|
||||||
// path to store runtime state information
|
|
||||||
root string
|
|
||||||
id string
|
|
||||||
bundle string
|
|
||||||
processes map[string]*process
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) ID() string {
|
|
||||||
return c.id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) Path() string {
|
|
||||||
return c.bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) Start() (Process, error) {
|
|
||||||
processRoot := filepath.Join(c.root, c.id, InitProcessID)
|
|
||||||
if err := os.MkdirAll(processRoot, 0755); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cmd := exec.Command("containerd-shim", processRoot, c.id)
|
|
||||||
cmd.Dir = c.bundle
|
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
||||||
Setpgid: true,
|
|
||||||
}
|
|
||||||
spec, err := c.readSpec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p, err := newProcess(processRoot, InitProcessID, c, spec.Process)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.processes[InitProcessID] = p
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) readSpec() (*specs.LinuxSpec, error) {
|
|
||||||
var spec specs.LinuxSpec
|
|
||||||
f, err := os.Open(filepath.Join(c.bundle, "config.json"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if err := json.NewDecoder(f).Decode(&spec); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &spec, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) Pause() error {
|
|
||||||
return errNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) Resume() error {
|
|
||||||
return errNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) State() State {
|
|
||||||
return Running
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) Delete() error {
|
|
||||||
return os.RemoveAll(filepath.Join(c.root, c.id))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *container) Processes() ([]Process, error) {
|
|
||||||
out := []Process{}
|
|
||||||
for _, p := range c.processes {
|
|
||||||
out = append(out, p)
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
|
@ -1,6 +1,8 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -10,6 +12,31 @@ import (
|
||||||
"github.com/opencontainers/specs"
|
"github.com/opencontainers/specs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Process interface {
|
||||||
|
io.Closer
|
||||||
|
|
||||||
|
// ID of the process.
|
||||||
|
// This is either "init" when it is the container's init process or
|
||||||
|
// it is a user provided id for the process similar to the container id
|
||||||
|
ID() string
|
||||||
|
// Stdin returns the path the the processes stdin fifo
|
||||||
|
Stdin() string
|
||||||
|
// Stdout returns the path the the processes stdout fifo
|
||||||
|
Stdout() string
|
||||||
|
// Stderr returns the path the the processes stderr fifo
|
||||||
|
Stderr() string
|
||||||
|
// ExitFD returns the fd the provides an event when the process exits
|
||||||
|
ExitFD() int
|
||||||
|
// ExitStatus returns the exit status of the process or an error if it
|
||||||
|
// has not exited
|
||||||
|
ExitStatus() (int, error)
|
||||||
|
Spec() specs.Process
|
||||||
|
// Signal sends the provided signal to the process
|
||||||
|
Signal(os.Signal) error
|
||||||
|
// Container returns the container that the process belongs to
|
||||||
|
Container() Container
|
||||||
|
}
|
||||||
|
|
||||||
func newProcess(root, id string, c *container, s specs.Process) (*process, error) {
|
func newProcess(root, id string, c *container, s specs.Process) (*process, error) {
|
||||||
p := &process{
|
p := &process{
|
||||||
root: root,
|
root: root,
|
||||||
|
@ -17,6 +44,14 @@ func newProcess(root, id string, c *container, s specs.Process) (*process, error
|
||||||
container: c,
|
container: c,
|
||||||
spec: s,
|
spec: s,
|
||||||
}
|
}
|
||||||
|
f, err := os.Create(filepath.Join(root, "process.json"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := json.NewEncoder(f).Encode(s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
// create fifo's for the process
|
// create fifo's for the process
|
||||||
for name, fd := range map[string]*string{
|
for name, fd := range map[string]*string{
|
||||||
"stdin": &p.stdin,
|
"stdin": &p.stdin,
|
||||||
|
@ -58,7 +93,7 @@ func loadProcess(root, id string, c *container, s specs.Process) (*process, erro
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil, ErrProcessExited
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getExitPipe(path string) (*os.File, error) {
|
func getExitPipe(path string) (*os.File, error) {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotChildProcess = errors.New("containerd: not a child process for container")
|
ErrNotChildProcess = errors.New("containerd: not a child process for container")
|
||||||
|
@ -14,3 +17,46 @@ var (
|
||||||
|
|
||||||
errNotImplemented = errors.New("containerd: not implemented")
|
errNotImplemented = errors.New("containerd: not implemented")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ExitFile = "exit"
|
||||||
|
ExitStatusFile = "exitStatus"
|
||||||
|
StateFile = "state.json"
|
||||||
|
InitProcessID = "init"
|
||||||
|
)
|
||||||
|
|
||||||
|
type State string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Paused = State("paused")
|
||||||
|
Running = State("running")
|
||||||
|
)
|
||||||
|
|
||||||
|
type state struct {
|
||||||
|
Bundle string `json:"bundle"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stat struct {
|
||||||
|
// Timestamp is the time that the statistics where collected
|
||||||
|
Timestamp time.Time
|
||||||
|
// Data is the raw stats
|
||||||
|
// TODO: it is currently an interface because we don't know what type of exec drivers
|
||||||
|
// we will have or what the structure should look like at the moment os the containers
|
||||||
|
// can return what they want and we could marshal to json or whatever.
|
||||||
|
Data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Checkpoint struct {
|
||||||
|
// Timestamp is the time that checkpoint happened
|
||||||
|
Timestamp time.Time
|
||||||
|
// Name is the name of the checkpoint
|
||||||
|
Name string
|
||||||
|
// Tcp checkpoints open tcp connections
|
||||||
|
Tcp bool
|
||||||
|
// UnixSockets persists unix sockets in the checkpoint
|
||||||
|
UnixSockets bool
|
||||||
|
// Shell persists tty sessions in the checkpoint
|
||||||
|
Shell bool
|
||||||
|
// Exit exits the container after the checkpoint is finished
|
||||||
|
Exit bool
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package supervisor
|
package supervisor
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type AddProcessEvent struct {
|
type AddProcessEvent struct {
|
||||||
s *Supervisor
|
s *Supervisor
|
||||||
}
|
}
|
||||||
|
@ -7,32 +9,23 @@ type AddProcessEvent struct {
|
||||||
// TODO: add this to worker for concurrent starts??? maybe not because of races where the container
|
// TODO: add this to worker for concurrent starts??? maybe not because of races where the container
|
||||||
// could be stopped and removed...
|
// could be stopped and removed...
|
||||||
func (h *AddProcessEvent) Handle(e *Event) error {
|
func (h *AddProcessEvent) Handle(e *Event) error {
|
||||||
/*
|
start := time.Now()
|
||||||
start := time.Now()
|
ci, ok := h.s.containers[e.ID]
|
||||||
ci, ok := h.s.containers[e.ID]
|
if !ok {
|
||||||
if !ok {
|
return ErrContainerNotFound
|
||||||
return ErrContainerNotFound
|
}
|
||||||
}
|
process, err := ci.container.Exec(e.Pid, *e.ProcessSpec)
|
||||||
p, io, err := h.s.runtime.StartProcess(ci.container, *e.Process, e.Console)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
if err := h.s.monitorProcess(process); err != nil {
|
||||||
if e.Pid, err = p.Pid(); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
ExecProcessTimer.UpdateSince(start)
|
||||||
h.s.processes[e.Pid] = &containerInfo{
|
e.StartResponse <- StartResponse{
|
||||||
container: ci.container,
|
Stdin: process.Stdin(),
|
||||||
}
|
Stdout: process.Stdout(),
|
||||||
l, err := h.s.copyIO(e.Stdin, e.Stdout, e.Stderr, io)
|
Stderr: process.Stderr(),
|
||||||
if err != nil {
|
}
|
||||||
// log the error but continue with the other commands
|
|
||||||
logrus.WithFields(logrus.Fields{
|
|
||||||
"error": err,
|
|
||||||
"id": e.ID,
|
|
||||||
}).Error("log stdio")
|
|
||||||
}
|
|
||||||
h.s.processes[e.Pid].copier = l
|
|
||||||
ExecProcessTimer.UpdateSince(start)
|
|
||||||
*/
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,6 @@ func (h *DeleteEvent) Handle(e *Event) error {
|
||||||
if err := h.deleteContainer(i.container); err != nil {
|
if err := h.deleteContainer(i.container); err != nil {
|
||||||
logrus.WithField("error", err).Error("containerd: deleting container")
|
logrus.WithField("error", err).Error("containerd: deleting container")
|
||||||
}
|
}
|
||||||
if i.copier != nil {
|
|
||||||
if err := i.copier.Close(); err != nil {
|
|
||||||
logrus.WithField("error", err).Error("containerd: close container copier")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.s.notifySubscribers(&Event{
|
h.s.notifySubscribers(&Event{
|
||||||
Type: ExitEventType,
|
Type: ExitEventType,
|
||||||
ID: e.ID,
|
ID: e.ID,
|
||||||
|
|
|
@ -25,7 +25,9 @@ func (h *ExitEvent) Handle(e *Event) error {
|
||||||
if proc.ID() != runtime.InitProcessID {
|
if proc.ID() != runtime.InitProcessID {
|
||||||
ne := NewEvent(ExecExitEventType)
|
ne := NewEvent(ExecExitEventType)
|
||||||
ne.ID = proc.Container().ID()
|
ne.ID = proc.Container().ID()
|
||||||
|
ne.Pid = proc.ID()
|
||||||
ne.Status = status
|
ne.Status = status
|
||||||
|
ne.Process = proc
|
||||||
h.s.SendEvent(ne)
|
h.s.SendEvent(ne)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -51,17 +53,11 @@ type ExecExitEvent struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ExecExitEvent) Handle(e *Event) error {
|
func (h *ExecExitEvent) Handle(e *Event) error {
|
||||||
|
container := e.Process.Container()
|
||||||
// exec process: we remove this process without notifying the main event loop
|
// exec process: we remove this process without notifying the main event loop
|
||||||
/*
|
if err := container.RemoveProcess(e.Pid); err != nil {
|
||||||
info := h.s.processes[e.Pid]
|
logrus.WithField("error", err).Error("containerd: find container for pid")
|
||||||
if err := info.container.RemoveProcess(e.Pid); err != nil {
|
}
|
||||||
logrus.WithField("error", err).Error("containerd: find container for pid")
|
h.s.notifySubscribers(e)
|
||||||
}
|
|
||||||
if err := info.copier.Close(); err != nil {
|
|
||||||
logrus.WithField("error", err).Error("containerd: close process IO")
|
|
||||||
}
|
|
||||||
delete(h.s.processes, e.Pid)
|
|
||||||
h.s.notifySubscribers(e)
|
|
||||||
*/
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
package supervisor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ioConfig struct {
|
|
||||||
StdoutPath string
|
|
||||||
StderrPath string
|
|
||||||
StdinPath string
|
|
||||||
|
|
||||||
Stdin io.WriteCloser
|
|
||||||
Stdout io.ReadCloser
|
|
||||||
Stderr io.ReadCloser
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCopier(i *ioConfig) (*copier, error) {
|
|
||||||
l := &copier{
|
|
||||||
config: i,
|
|
||||||
}
|
|
||||||
if i.StdinPath != "" {
|
|
||||||
f, err := os.OpenFile(i.StdinPath, os.O_RDONLY, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
l.closers = append(l.closers, f)
|
|
||||||
go func() {
|
|
||||||
io.Copy(i.Stdin, f)
|
|
||||||
i.Stdin.Close()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
if i.StdoutPath != "" {
|
|
||||||
f, err := os.OpenFile(i.StdoutPath, os.O_RDWR, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
l.closers = append(l.closers, f)
|
|
||||||
go io.Copy(f, i.Stdout)
|
|
||||||
}
|
|
||||||
if i.StderrPath != "" {
|
|
||||||
f, err := os.OpenFile(i.StderrPath, os.O_RDWR, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
l.closers = append(l.closers, f)
|
|
||||||
go io.Copy(f, i.Stderr)
|
|
||||||
}
|
|
||||||
return l, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type copier struct {
|
|
||||||
config *ioConfig
|
|
||||||
closers []io.Closer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *copier) Close() (err error) {
|
|
||||||
for _, c := range append(l.closers, l.config.Stdin, l.config.Stdout, l.config.Stderr) {
|
|
||||||
if c != nil {
|
|
||||||
if cerr := c.Close(); err == nil {
|
|
||||||
err = cerr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -11,6 +11,7 @@ var (
|
||||||
EventsCounter = metrics.NewCounter()
|
EventsCounter = metrics.NewCounter()
|
||||||
ExecProcessTimer = metrics.NewTimer()
|
ExecProcessTimer = metrics.NewTimer()
|
||||||
ExitProcessTimer = metrics.NewTimer()
|
ExitProcessTimer = metrics.NewTimer()
|
||||||
|
EpollFdCounter = metrics.NewCounter()
|
||||||
)
|
)
|
||||||
|
|
||||||
func Metrics() map[string]interface{} {
|
func Metrics() map[string]interface{} {
|
||||||
|
@ -23,5 +24,6 @@ func Metrics() map[string]interface{} {
|
||||||
"events": EventsCounter,
|
"events": EventsCounter,
|
||||||
"exec-process-time": ExecProcessTimer,
|
"exec-process-time": ExecProcessTimer,
|
||||||
"exit-process-time": ExitProcessTimer,
|
"exit-process-time": ExitProcessTimer,
|
||||||
|
"epoll-fds": EpollFdCounter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ func (m *Monitor) Monitor(p runtime.Process) error {
|
||||||
if err := syscall.EpollCtl(m.epollFd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
|
if err := syscall.EpollCtl(m.epollFd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
EpollFdCounter.Inc(1)
|
||||||
m.processes[fd] = p
|
m.processes[fd] = p
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -75,6 +76,7 @@ func (m *Monitor) start() {
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logrus.WithField("error", err).Fatal("containerd: epoll remove fd")
|
logrus.WithField("error", err).Fatal("containerd: epoll remove fd")
|
||||||
}
|
}
|
||||||
|
EpollFdCounter.Dec(1)
|
||||||
if err := proc.Close(); err != nil {
|
if err := proc.Close(); err != nil {
|
||||||
logrus.WithField("error", err).Error("containerd: close process IO")
|
logrus.WithField("error", err).Error("containerd: close process IO")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,18 @@ type SignalEvent struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SignalEvent) Handle(e *Event) error {
|
func (h *SignalEvent) Handle(e *Event) error {
|
||||||
/*
|
i, ok := h.s.containers[e.ID]
|
||||||
i, ok := h.s.containers[e.ID]
|
if !ok {
|
||||||
if !ok {
|
return ErrContainerNotFound
|
||||||
return ErrContainerNotFound
|
}
|
||||||
|
processes, err := i.container.Processes()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, p := range processes {
|
||||||
|
if p.ID() == e.Pid {
|
||||||
|
return p.Signal(e.Signal)
|
||||||
}
|
}
|
||||||
processes, err := i.container.Processes()
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, p := range processes {
|
|
||||||
if pid, err := p.Pid(); err == nil && pid == e.Pid {
|
|
||||||
return p.Signal(e.Signal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return ErrProcessNotFound
|
return ErrProcessNotFound
|
||||||
}
|
}
|
||||||
|
|
69
supervisor/sort_test.go
Normal file
69
supervisor/sort_test.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package supervisor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/containerd/runtime"
|
||||||
|
"github.com/opencontainers/specs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testProcess struct {
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) ID() string {
|
||||||
|
return p.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Stdin() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Stdout() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Stderr() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) ExitFD() int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) ExitStatus() (int, error) {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Container() runtime.Container {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Spec() specs.Process {
|
||||||
|
return specs.Process{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Signal(os.Signal) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testProcess) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSortProcesses(t *testing.T) {
|
||||||
|
p := []runtime.Process{
|
||||||
|
&testProcess{"ls"},
|
||||||
|
&testProcess{"other"},
|
||||||
|
&testProcess{"init"},
|
||||||
|
&testProcess{"other2"},
|
||||||
|
}
|
||||||
|
s := &processSorter{p}
|
||||||
|
sort.Sort(s)
|
||||||
|
|
||||||
|
if id := p[len(p)-1].ID(); id != "init" {
|
||||||
|
t.Fatalf("expected init but received %q", id)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ package supervisor
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@ func New(stateDir string, tasks chan *StartTask, oom bool) (*Supervisor, error)
|
||||||
|
|
||||||
type containerInfo struct {
|
type containerInfo struct {
|
||||||
container runtime.Container
|
container runtime.Container
|
||||||
copier *copier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Supervisor struct {
|
type Supervisor struct {
|
||||||
|
@ -195,14 +194,6 @@ func (s *Supervisor) restore() error {
|
||||||
id := d.Name()
|
id := d.Name()
|
||||||
container, err := runtime.Load(s.stateDir, id)
|
container, err := runtime.Load(s.stateDir, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == runtime.ErrContainerExited {
|
|
||||||
logrus.WithField("id", id).Debug("containerd: container exited while away")
|
|
||||||
// TODO: fire events to do the removal
|
|
||||||
if err := os.RemoveAll(filepath.Join(s.stateDir, id)); err != nil {
|
|
||||||
logrus.WithField("error", err).Warn("containerd: remove container state")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
processes, err := container.Processes()
|
processes, err := container.Processes()
|
||||||
|
@ -214,11 +205,42 @@ func (s *Supervisor) restore() error {
|
||||||
container: container,
|
container: container,
|
||||||
}
|
}
|
||||||
logrus.WithField("id", id).Debug("containerd: container restored")
|
logrus.WithField("id", id).Debug("containerd: container restored")
|
||||||
|
var exitedProcesses []runtime.Process
|
||||||
for _, p := range processes {
|
for _, p := range processes {
|
||||||
if err := s.monitorProcess(p); err != nil {
|
if _, err := p.ExitStatus(); err == nil {
|
||||||
return err
|
exitedProcesses = append(exitedProcesses, p)
|
||||||
|
} else {
|
||||||
|
if err := s.monitorProcess(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(exitedProcesses) > 0 {
|
||||||
|
// sort processes so that init is fired last because that is how the kernel sends the
|
||||||
|
// exit events
|
||||||
|
sort.Sort(&processSorter{exitedProcesses})
|
||||||
|
for _, p := range exitedProcesses {
|
||||||
|
e := NewEvent(ExitEventType)
|
||||||
|
e.Process = p
|
||||||
|
s.SendEvent(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
|
@ -27,17 +27,17 @@ func (h *UpdateEvent) Handle(e *Event) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if e.Signal != nil {
|
if e.Signal != nil {
|
||||||
/*
|
// signal the pid1/main process of the container
|
||||||
// signal the pid1/main process of the container
|
processes, err := container.Processes()
|
||||||
processes, err := container.Processes()
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
|
for _, p := range processes {
|
||||||
|
if p.ID() == runtime.InitProcessID {
|
||||||
|
return p.Signal(e.Signal)
|
||||||
}
|
}
|
||||||
if len(processes) == 0 {
|
}
|
||||||
return ErrProcessNotFound
|
return ErrProcessNotFound
|
||||||
}
|
|
||||||
return processes[0].Signal(e.Signal)
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ type Worker interface {
|
||||||
type StartTask struct {
|
type StartTask struct {
|
||||||
Container runtime.Container
|
Container runtime.Container
|
||||||
Checkpoint string
|
Checkpoint string
|
||||||
IO *runtime.IO
|
|
||||||
Stdin string
|
Stdin string
|
||||||
Stdout string
|
Stdout string
|
||||||
Stderr string
|
Stderr string
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
const Version = "0.0.4"
|
const Version = "0.0.5"
|
||||||
|
|
Loading…
Reference in a new issue