Update shim for exec

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-02-01 11:02:41 -08:00
parent 6808dbc02f
commit 835f3b6a97
37 changed files with 786 additions and 709 deletions

View file

@ -2,6 +2,7 @@ package server
import (
"errors"
"fmt"
"syscall"
"google.golang.org/grpc"
@ -75,18 +76,27 @@ func (s *apiServer) AddProcess(ctx context.Context, r *types.AddProcessRequest)
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.ID = r.Id
e.Pid = r.Pid
e.ProcessSpec = process
e.Console = r.Console
e.Stdin = r.Stdin
e.Stdout = r.Stdout
e.Stderr = r.Stderr
e.StartResponse = make(chan supervisor.StartResponse, 1)
s.sv.SendEvent(e)
if err := <-e.Err; err != nil {
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) {

View file

@ -65,7 +65,7 @@ var _ = math.Inf
type CreateContainerRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,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{} }
@ -74,9 +74,10 @@ func (*CreateContainerRequest) ProtoMessage() {}
func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type CreateContainerResponse 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"`
Pid uint32 `protobuf:"varint,1,opt,name=pid" json:"pid,omitempty"`
Stdin string `protobuf:"bytes,2,opt,name=stdin" json:"stdin,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{} }
@ -110,10 +111,7 @@ type AddProcessRequest struct {
Args []string `protobuf:"bytes,4,rep,name=args" json:"args,omitempty"`
Env []string `protobuf:"bytes,5,rep,name=env" json:"env,omitempty"`
Cwd string `protobuf:"bytes,6,opt,name=cwd" json:"cwd,omitempty"`
Stdin string `protobuf:"bytes,7,opt,name=stdin" json:"stdin,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"`
Pid string `protobuf:"bytes,7,opt,name=pid" json:"pid,omitempty"`
}
func (m *AddProcessRequest) Reset() { *m = AddProcessRequest{} }
@ -140,6 +138,9 @@ func (*User) ProtoMessage() {}
func (*User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
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{} }
@ -1084,94 +1085,94 @@ var _API_serviceDesc = grpc.ServiceDesc{
var fileDescriptor0 = []byte{
// 1440 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xd9, 0x72, 0xdc, 0x44,
0x17, 0xf6, 0xec, 0x33, 0x67, 0x16, 0xdb, 0xf2, 0x92, 0xf1, 0xfc, 0x7f, 0x88, 0x11, 0x81, 0xa4,
0xa8, 0x94, 0x2b, 0x38, 0x2c, 0x21, 0x5c, 0x40, 0x70, 0x52, 0x09, 0x54, 0x02, 0xae, 0xc4, 0xa6,
0x8a, 0x1b, 0xa6, 0x64, 0xa9, 0x19, 0x8b, 0xd1, 0x48, 0x42, 0x6a, 0x79, 0x79, 0x05, 0x9e, 0x87,
0xe2, 0x01, 0xa8, 0xe2, 0x9e, 0xe7, 0xe0, 0x29, 0x38, 0xdd, 0x7d, 0xd4, 0x5a, 0x66, 0x09, 0x5c,
0x70, 0x33, 0x55, 0xdd, 0x7d, 0xce, 0x77, 0xbe, 0xb3, 0xaa, 0x7b, 0xa0, 0x63, 0x85, 0xee, 0x41,
0x18, 0x05, 0x3c, 0x30, 0x1a, 0xfc, 0x3a, 0x64, 0xb1, 0xf9, 0x02, 0x76, 0x8f, 0x22, 0x66, 0x71,
0x76, 0x14, 0xf8, 0xdc, 0x72, 0x7d, 0x16, 0xbd, 0x62, 0x3f, 0x27, 0x2c, 0xe6, 0x06, 0x40, 0xd5,
0x75, 0x86, 0x95, 0xfd, 0xca, 0xdd, 0x8e, 0x81, 0x8b, 0xb3, 0xc4, 0x77, 0x3c, 0x76, 0x6c, 0xf1,
0xf3, 0x61, 0x35, 0xdd, 0xb3, 0xcf, 0x99, 0x3d, 0x0d, 0x03, 0xd7, 0xe7, 0xc3, 0x9a, 0xd8, 0x33,
0x9f, 0xc3, 0x8d, 0x39, 0xb4, 0x38, 0x0c, 0xfc, 0x98, 0x19, 0x7d, 0x68, 0xc4, 0xdc, 0x71, 0x7d,
0x42, 0x1c, 0x40, 0x13, 0x97, 0x41, 0xc2, 0x09, 0x4d, 0xad, 0x59, 0x14, 0x11, 0xd2, 0x43, 0xe8,
0xbf, 0x76, 0x27, 0xbe, 0xe5, 0x2d, 0xa2, 0xd3, 0x85, 0x5a, 0x88, 0x8b, 0x4c, 0x53, 0x4a, 0x4a,
0xcd, 0xbe, 0xb9, 0x01, 0x83, 0x54, 0x53, 0x99, 0x36, 0x7f, 0xad, 0xc0, 0xe6, 0x63, 0xc7, 0x39,
0x8e, 0x02, 0x9b, 0xc5, 0xf1, 0x22, 0xc0, 0x0d, 0x68, 0x73, 0x16, 0xcd, 0x5c, 0x81, 0x22, 0x50,
0xdb, 0xc6, 0x1e, 0xd4, 0x93, 0x98, 0x29, 0x36, 0xdd, 0xc3, 0xee, 0x81, 0x8c, 0xd6, 0xc1, 0x29,
0x6e, 0x19, 0x3d, 0xa8, 0x5b, 0xd1, 0x24, 0x1e, 0xd6, 0xf7, 0x6b, 0x8a, 0x0b, 0xf3, 0x2f, 0x86,
0x8d, 0x74, 0x61, 0x5f, 0x3a, 0xc3, 0xa6, 0x04, 0xd5, 0x1e, 0xb7, 0x4a, 0x1e, 0xb7, 0x4b, 0x1e,
0x77, 0xe4, 0x7a, 0x1d, 0x5a, 0x36, 0xd2, 0x0d, 0x3c, 0x36, 0x04, 0x0a, 0x41, 0x5d, 0xda, 0x43,
0xd0, 0x84, 0x98, 0xf6, 0xc5, 0x62, 0x42, 0xae, 0xf7, 0x8d, 0x5d, 0x18, 0x58, 0x8e, 0xe3, 0x72,
0x37, 0x40, 0xe2, 0xcf, 0x5c, 0x27, 0x46, 0xba, 0x35, 0x0c, 0xc1, 0x36, 0x18, 0x79, 0x7f, 0x29,
0x0c, 0x2f, 0x74, 0x72, 0x74, 0xda, 0x16, 0xc5, 0xe2, 0xdd, 0x42, 0x5e, 0xab, 0xd2, 0xff, 0x4d,
0xf2, 0x3f, 0xd3, 0x34, 0x47, 0x30, 0x9c, 0x47, 0x23, 0x4b, 0x0f, 0xe0, 0xc6, 0x13, 0xe6, 0xb1,
0x37, 0x59, 0xc2, 0x40, 0xfa, 0xd6, 0x8c, 0xa9, 0x3c, 0x0a, 0xc0, 0x79, 0x25, 0x02, 0x7c, 0x07,
0x76, 0x5e, 0xb8, 0x31, 0x5f, 0x09, 0x67, 0x7e, 0x0f, 0x90, 0x09, 0x68, 0x70, 0x6d, 0x8a, 0x5d,
0xb9, 0x9c, 0x92, 0x8b, 0x41, 0xe4, 0x76, 0x28, 0x73, 0xdb, 0x36, 0xb6, 0xa0, 0x9b, 0xf8, 0xee,
0xd5, 0xeb, 0xc0, 0x9e, 0x32, 0x2e, 0xb2, 0x2a, 0x36, 0x45, 0xee, 0xce, 0x99, 0xe7, 0x61, 0x5e,
0x71, 0x69, 0x7e, 0x01, 0xbb, 0x65, 0xfb, 0x54, 0xd6, 0xef, 0x41, 0x37, 0x8b, 0x56, 0x8c, 0xd6,
0x6a, 0x8b, 0xc3, 0x35, 0x80, 0xde, 0x6b, 0x8e, 0xd1, 0x22, 0xe2, 0xe6, 0x3e, 0x0c, 0x74, 0x8f,
0xc8, 0x03, 0x55, 0x0f, 0x16, 0x4f, 0x62, 0x72, 0x67, 0x0a, 0x2d, 0xca, 0x60, 0x5a, 0xef, 0xff,
0x5d, 0xad, 0x9a, 0x1e, 0x74, 0x34, 0x9d, 0xe5, 0x39, 0x2a, 0xcd, 0x01, 0xd9, 0xa9, 0xc6, 0xdb,
0xd0, 0x09, 0x15, 0x4f, 0xa6, 0xec, 0x74, 0x0f, 0x07, 0x44, 0x21, 0xe5, 0x9f, 0xb9, 0xd6, 0x90,
0xd6, 0xee, 0x40, 0xeb, 0xa5, 0x65, 0x9f, 0xa3, 0x31, 0x81, 0x6f, 0x87, 0xe4, 0x73, 0x5f, 0x08,
0xce, 0xd8, 0x2c, 0x88, 0xae, 0xa5, 0xbd, 0xba, 0xf9, 0x1d, 0x4e, 0x01, 0x15, 0x35, 0x0a, 0xf7,
0x6d, 0x2c, 0xce, 0x94, 0x67, 0x1a, 0xed, 0x8d, 0x34, 0xda, 0xda, 0x81, 0x5b, 0xd0, 0x9a, 0x29,
0x7c, 0xaa, 0xdf, 0x94, 0x10, 0x59, 0x35, 0x9f, 0xc0, 0xee, 0x69, 0xe8, 0xbc, 0x69, 0xea, 0x65,
0x93, 0xa5, 0x9a, 0xb2, 0x23, 0x37, 0xd4, 0x8c, 0xda, 0x83, 0x1b, 0x73, 0x28, 0x54, 0xb0, 0xeb,
0xd0, 0x7f, 0x7a, 0xc1, 0xb0, 0x22, 0xd2, 0x7c, 0xff, 0x59, 0x81, 0x86, 0xdc, 0x11, 0x1e, 0x0b,
0x32, 0x64, 0x43, 0xd9, 0xcb, 0xcd, 0x40, 0x8d, 0xdf, 0x2f, 0x45, 0xbb, 0x9e, 0x1f, 0x7d, 0x8d,
0x12, 0xc1, 0x96, 0x54, 0x40, 0xbf, 0x29, 0x15, 0x72, 0xc6, 0xcc, 0x27, 0xa2, 0x18, 0xbe, 0xce,
0x92, 0xf0, 0x15, 0x27, 0x00, 0x2c, 0x9b, 0x00, 0xbf, 0x55, 0xa0, 0xf7, 0x0d, 0xe3, 0x97, 0x41,
0x34, 0x15, 0x49, 0x8a, 0x4b, 0x2d, 0x87, 0x75, 0x1a, 0x5d, 0x8d, 0xcf, 0xae, 0x39, 0x96, 0x85,
0xcc, 0xa6, 0xf0, 0x07, 0x77, 0x8e, 0x2d, 0xd5, 0x68, 0x35, 0xb9, 0xb7, 0x09, 0x9d, 0x57, 0x57,
0x63, 0x9c, 0x82, 0x41, 0xa4, 0x7a, 0x4f, 0x8a, 0xe1, 0x96, 0x13, 0x05, 0x61, 0xc8, 0x94, 0xa7,
0x75, 0x01, 0x76, 0x92, 0x82, 0x35, 0x53, 0x29, 0xdc, 0x09, 0x09, 0xac, 0x95, 0x82, 0x9d, 0x68,
0xb0, 0x76, 0x4e, 0x2c, 0x05, 0xeb, 0xc8, 0xaa, 0x9a, 0x41, 0xfb, 0x28, 0x4c, 0x4e, 0x63, 0x6b,
0xc2, 0x44, 0xf7, 0xf3, 0x80, 0x5b, 0xde, 0x38, 0x11, 0x4b, 0x49, 0xbd, 0x6e, 0x6c, 0x43, 0x2f,
0x64, 0x11, 0xd6, 0x25, 0xed, 0x56, 0x31, 0x50, 0x75, 0xe3, 0x7f, 0xb0, 0x25, 0x97, 0x63, 0xd7,
0x1f, 0x4f, 0x59, 0xe4, 0x33, 0x6f, 0x16, 0x38, 0x8c, 0xfc, 0xd8, 0x83, 0x4d, 0x7d, 0x28, 0x9a,
0x51, 0x1e, 0x49, 0x7f, 0xcc, 0x13, 0x18, 0x9c, 0x9c, 0xe3, 0x37, 0x97, 0x7b, 0xae, 0x3f, 0x79,
0x62, 0x71, 0x4b, 0x8c, 0x7a, 0xc4, 0x77, 0x03, 0x27, 0x26, 0x83, 0xa8, 0xcd, 0x95, 0x08, 0x73,
0xc6, 0xe9, 0x91, 0x0a, 0x1a, 0xce, 0xf8, 0xec, 0x88, 0xbb, 0x33, 0x32, 0x68, 0xfe, 0x20, 0x9d,
0x50, 0x81, 0x37, 0xa1, 0x93, 0x91, 0xad, 0xc8, 0x7c, 0xad, 0xa7, 0xf9, 0x4a, 0x1d, 0x3d, 0x80,
0x75, 0xae, 0x59, 0x8c, 0xb1, 0x6a, 0x2d, 0xea, 0x8d, 0x1d, 0x92, 0x2c, 0x72, 0x34, 0x3f, 0x07,
0x78, 0x29, 0x5b, 0x51, 0x32, 0xc6, 0x79, 0x98, 0x0f, 0x10, 0x06, 0x7a, 0x66, 0x5d, 0xe9, 0xe8,
0x88, 0x2d, 0xf4, 0xe9, 0x47, 0xcb, 0xf5, 0x6c, 0xba, 0x0b, 0xd4, 0xcd, 0xbf, 0x2a, 0xd0, 0x55,
0x08, 0x8a, 0x24, 0x42, 0xd8, 0xd8, 0x7e, 0x29, 0xc4, 0x7e, 0x8a, 0x58, 0xfc, 0xc2, 0xe4, 0x6c,
0x62, 0x19, 0xc6, 0x97, 0x56, 0x48, 0x56, 0x6a, 0xcb, 0xc4, 0xee, 0x40, 0x4f, 0x65, 0x83, 0x04,
0xeb, 0xcb, 0x04, 0xef, 0x89, 0xef, 0x31, 0x32, 0x91, 0xf3, 0xaf, 0x7b, 0x78, 0xb3, 0x20, 0x21,
0x39, 0x1e, 0xc8, 0xdf, 0xa7, 0x3e, 0x8f, 0xae, 0x47, 0xf7, 0x00, 0xb2, 0x95, 0x68, 0xbb, 0x29,
0xbb, 0xa6, 0xca, 0x46, 0x4f, 0x2e, 0x2c, 0x2f, 0x21, 0xcf, 0x1f, 0x55, 0x1f, 0x56, 0xcc, 0xaf,
0x61, 0xfd, 0x4b, 0x6f, 0xea, 0x06, 0x39, 0x15, 0x94, 0x9a, 0x59, 0x3f, 0x05, 0x11, 0xf9, 0x2b,
0x96, 0xae, 0x8f, 0x4b, 0x15, 0x2e, 0xec, 0xfb, 0x20, 0xa4, 0x09, 0xaa, 0xf1, 0x54, 0xbd, 0xfc,
0x5e, 0x03, 0xc8, 0xc0, 0x8c, 0x47, 0x30, 0x72, 0x83, 0x31, 0x96, 0xd4, 0x85, 0x6b, 0x33, 0xd5,
0x02, 0xe3, 0x88, 0xd9, 0x49, 0x14, 0xbb, 0x17, 0x8c, 0x46, 0xe0, 0x2e, 0xf9, 0x52, 0xe6, 0xf0,
0x11, 0xec, 0x64, 0xba, 0x4e, 0x4e, 0xad, 0xba, 0x52, 0xed, 0x01, 0x6c, 0xa1, 0x1a, 0x0e, 0xae,
0xa4, 0xa0, 0x54, 0x5b, 0xa9, 0xf4, 0x29, 0xec, 0xe5, 0x78, 0x8a, 0x4a, 0xcd, 0xa9, 0xd6, 0x57,
0xaa, 0x7e, 0x0c, 0xbb, 0xa8, 0x7a, 0x69, 0xb9, 0xbc, 0xac, 0xd7, 0xf8, 0x07, 0x3c, 0x67, 0x2c,
0x9a, 0x14, 0x78, 0x36, 0x57, 0x2a, 0x7d, 0x00, 0x9b, 0xa8, 0x54, 0xb2, 0xd3, 0x7a, 0x93, 0x4a,
0xcc, 0x6c, 0x8e, 0x53, 0x25, 0xa7, 0xd2, 0x5e, 0xa5, 0x62, 0x3e, 0x86, 0xde, 0xf3, 0x64, 0xc2,
0xb8, 0x77, 0xa6, 0xab, 0xff, 0xdf, 0x36, 0xd0, 0x2f, 0x55, 0xe8, 0x1e, 0x4d, 0xa2, 0x20, 0x09,
0x0b, 0x5d, 0xae, 0x6a, 0x78, 0xae, 0xcb, 0x95, 0xcc, 0x5d, 0xe8, 0xa9, 0x0f, 0x28, 0x89, 0xa9,
0xe6, 0x32, 0xe6, 0x4b, 0x5d, 0x5c, 0x5c, 0xce, 0x04, 0x67, 0x12, 0x2c, 0xb6, 0x57, 0xae, 0xfc,
0x3e, 0x83, 0xfe, 0xb9, 0x72, 0x84, 0x24, 0x55, 0x2a, 0x6f, 0xa7, 0x96, 0x33, 0x82, 0x07, 0x79,
0x87, 0x55, 0x13, 0x3d, 0x87, 0xcd, 0xb9, 0xcd, 0x62, 0x2f, 0x99, 0xf9, 0x5e, 0xea, 0x1e, 0x6e,
0x11, 0x6c, 0x5e, 0x4b, 0x36, 0x58, 0x08, 0x0d, 0xc5, 0xe7, 0x7d, 0xe8, 0xfb, 0xea, 0xa3, 0xa3,
0x23, 0x51, 0xcb, 0x29, 0x16, 0x3e, 0x48, 0x18, 0x0d, 0x5b, 0xf2, 0x5b, 0x18, 0x8d, 0x7c, 0x6c,
0x31, 0x1f, 0xa2, 0x22, 0x50, 0x6c, 0x16, 0x52, 0xf8, 0x47, 0xea, 0xc6, 0xb6, 0xe8, 0xbd, 0x70,
0xf8, 0x47, 0x03, 0x6a, 0x8f, 0x8f, 0xbf, 0x32, 0x5e, 0xc1, 0x7a, 0xe9, 0xbd, 0x63, 0xa4, 0x63,
0x65, 0xf1, 0xab, 0x6a, 0xf4, 0xd6, 0xb2, 0x63, 0xba, 0x38, 0xac, 0x09, 0xcc, 0xd2, 0xad, 0x42,
0x63, 0x2e, 0xbe, 0xb3, 0x68, 0xcc, 0x65, 0x97, 0x91, 0x35, 0xe3, 0x13, 0x68, 0xaa, 0x37, 0x91,
0xb1, 0x4d, 0xb2, 0x85, 0xc7, 0xd5, 0x68, 0xa7, 0xb4, 0xab, 0x15, 0x8f, 0x00, 0xb2, 0x97, 0x84,
0x31, 0x24, 0xb1, 0xb9, 0xc7, 0xd4, 0x68, 0x6f, 0xc1, 0x89, 0x06, 0x39, 0x85, 0x8d, 0xf2, 0x53,
0xc1, 0x28, 0xc5, 0xa1, 0x7c, 0xb1, 0x1f, 0xdd, 0x5a, 0x7a, 0x9e, 0x87, 0x2d, 0x3f, 0x18, 0x34,
0xec, 0x92, 0xe7, 0x87, 0x86, 0x5d, 0xfa, 0xd2, 0x58, 0x33, 0xbe, 0x85, 0x41, 0xf1, 0xae, 0x6f,
0xfc, 0x9f, 0x94, 0x16, 0x3e, 0x41, 0x46, 0x37, 0x97, 0x9c, 0x6a, 0xc0, 0x0f, 0x55, 0xe9, 0xe2,
0x5d, 0x23, 0x8d, 0x72, 0xee, 0x21, 0x30, 0xda, 0x2e, 0x6e, 0x6a, 0xad, 0xfb, 0xd0, 0x54, 0x37,
0x48, 0x9d, 0xb2, 0xc2, 0x85, 0x72, 0xd4, 0xcb, 0xef, 0x9a, 0x6b, 0xf7, 0x2b, 0x38, 0xa5, 0xda,
0xcf, 0x18, 0x57, 0xf5, 0x9c, 0x37, 0x35, 0xa7, 0x22, 0x37, 0x85, 0xca, 0x59, 0x53, 0xfe, 0x17,
0xf0, 0xe0, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x15, 0x52, 0xba, 0x18, 0x10, 0x00, 0x00,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xdb, 0x72, 0xdc, 0x44,
0x13, 0xf6, 0x9e, 0x77, 0x7b, 0x0f, 0xb6, 0xe5, 0xd8, 0x59, 0xef, 0xff, 0x87, 0x04, 0x11, 0x48,
0x8a, 0x4a, 0xb9, 0x82, 0xc3, 0x21, 0x84, 0x0b, 0x08, 0x4e, 0x2a, 0x81, 0x4a, 0xc0, 0x95, 0xd8,
0x54, 0x71, 0xc3, 0x96, 0x2c, 0x0d, 0x6b, 0xb1, 0x3a, 0x21, 0x8d, 0x7c, 0xb8, 0xe4, 0x96, 0x07,
0xe2, 0x01, 0xa8, 0xe2, 0x9e, 0xe7, 0xe0, 0x29, 0x68, 0xcd, 0xb4, 0x46, 0x23, 0xed, 0xae, 0x03,
0x17, 0xdc, 0xb8, 0x6a, 0x46, 0xdd, 0x5f, 0x7f, 0xfd, 0x75, 0xf7, 0xec, 0x8c, 0xa1, 0x67, 0x45,
0xee, 0x5e, 0x14, 0x87, 0x3c, 0x34, 0x5a, 0xfc, 0x32, 0x62, 0x89, 0xf9, 0x02, 0x76, 0x0e, 0x62,
0x66, 0x71, 0x76, 0x10, 0x06, 0xdc, 0x72, 0x03, 0x16, 0xbf, 0x62, 0x3f, 0xa7, 0x2c, 0xe1, 0x06,
0x40, 0xdd, 0x75, 0xc6, 0xb5, 0x5b, 0xb5, 0xbb, 0x3d, 0x03, 0x17, 0x27, 0x69, 0xe0, 0x78, 0xec,
0xd0, 0xe2, 0xa7, 0xe3, 0x7a, 0xbe, 0x67, 0x9f, 0x32, 0x7b, 0x1e, 0x85, 0x6e, 0xc0, 0xc7, 0x9d,
0x6c, 0xcf, 0x3c, 0x86, 0xeb, 0x0b, 0x68, 0x49, 0x14, 0x06, 0x09, 0x33, 0xfa, 0xd0, 0x88, 0x08,
0x6f, 0x68, 0x0c, 0xa1, 0x95, 0x70, 0xc7, 0x0d, 0x08, 0x6a, 0x04, 0x6d, 0x5c, 0x86, 0x29, 0x1f,
0x37, 0xb4, 0x35, 0x8b, 0xe3, 0x71, 0x53, 0xc0, 0x3e, 0x84, 0xe1, 0x6b, 0x77, 0x16, 0x58, 0xde,
0x32, 0x6e, 0x04, 0x5c, 0x20, 0x09, 0x4b, 0x81, 0x34, 0x34, 0x37, 0x60, 0x94, 0x7b, 0x4a, 0x1e,
0xe6, 0x2f, 0x35, 0xd8, 0x7c, 0xec, 0x38, 0x87, 0x71, 0x68, 0xb3, 0x24, 0x59, 0x06, 0xb8, 0x01,
0x5d, 0xce, 0x62, 0xdf, 0xcd, 0x50, 0x32, 0xd4, 0xae, 0xb1, 0x0b, 0xcd, 0x34, 0x61, 0xb1, 0xc0,
0xec, 0xef, 0xf7, 0xf7, 0x84, 0x74, 0x7b, 0xc7, 0xb8, 0x65, 0x0c, 0xa0, 0x69, 0xc5, 0xb3, 0x04,
0x89, 0x36, 0x24, 0x17, 0x16, 0x9c, 0x8d, 0x5b, 0xf9, 0xc2, 0x3e, 0x77, 0xc6, 0x6d, 0x9d, 0x65,
0x87, 0xf2, 0x69, 0x0a, 0x67, 0xdc, 0x4c, 0x95, 0x26, 0xb8, 0x98, 0x51, 0x1e, 0x43, 0x63, 0x07,
0x46, 0x96, 0xe3, 0xb8, 0xdc, 0x0d, 0x91, 0xc5, 0x33, 0xd7, 0x49, 0x30, 0x76, 0x03, 0xf3, 0x39,
0x00, 0x43, 0x27, 0x4f, 0xda, 0x2a, 0x39, 0x6b, 0x15, 0x39, 0xeb, 0x15, 0x39, 0x85, 0xbc, 0x58,
0xf3, 0xbc, 0x4a, 0xaa, 0x7e, 0xcb, 0x74, 0x78, 0xb7, 0x54, 0xe0, 0xba, 0xc8, 0x7d, 0x93, 0x72,
0x2f, 0x3c, 0xcd, 0x09, 0x8c, 0x17, 0xd1, 0x48, 0xec, 0x07, 0x70, 0xfd, 0x09, 0xf3, 0xd8, 0x9b,
0x22, 0xa1, 0x88, 0x81, 0xe5, 0x33, 0x49, 0x37, 0x03, 0x5c, 0x74, 0x22, 0xc0, 0x77, 0x60, 0xfb,
0x85, 0x9b, 0xf0, 0x2b, 0xe1, 0xcc, 0xef, 0x01, 0x0a, 0x03, 0x05, 0xae, 0x42, 0xb1, 0x0b, 0x97,
0x53, 0x61, 0x51, 0x73, 0x6e, 0x47, 0x42, 0x96, 0xae, 0xb1, 0x05, 0xfd, 0x34, 0x70, 0x2f, 0x5e,
0x87, 0xf6, 0x9c, 0xf1, 0x44, 0xb4, 0x5e, 0x57, 0x48, 0x7b, 0xca, 0x3c, 0x0f, 0x6b, 0x8a, 0x4b,
0xf3, 0x0b, 0xd8, 0xa9, 0xc6, 0xa7, 0x1a, 0xbc, 0x07, 0xfd, 0x42, 0xad, 0x04, 0xa3, 0x35, 0x96,
0xcb, 0x35, 0x82, 0xc1, 0x6b, 0x8e, 0x6a, 0x11, 0x71, 0xf3, 0x16, 0x8c, 0xd4, 0xb0, 0x88, 0x0f,
0xb2, 0x5c, 0x16, 0x4f, 0x13, 0x4a, 0x67, 0x0e, 0x1d, 0x2a, 0xb8, 0x3e, 0x44, 0xff, 0x4d, 0x9f,
0x9a, 0x1e, 0xf4, 0x14, 0x9d, 0xd5, 0x35, 0xaa, 0x1c, 0x08, 0x72, 0x6a, 0xdf, 0x86, 0x5e, 0x24,
0x79, 0x32, 0x19, 0xa7, 0xbf, 0x3f, 0x22, 0x0a, 0x39, 0xff, 0x22, 0xb5, 0x96, 0x88, 0x76, 0x07,
0x3a, 0x2f, 0x2d, 0xfb, 0x14, 0x83, 0x65, 0xf8, 0x76, 0x44, 0x39, 0x0f, 0x33, 0x43, 0x9f, 0xf9,
0x61, 0x7c, 0x29, 0xe2, 0x35, 0xcd, 0xef, 0xf0, 0x04, 0x90, 0xaa, 0x91, 0xdc, 0xb7, 0xb1, 0x39,
0x73, 0x9e, 0xb9, 0xda, 0x1b, 0xb9, 0xda, 0x2a, 0x81, 0x9b, 0xd0, 0xf1, 0x25, 0x3e, 0xf5, 0x6f,
0x4e, 0x88, 0xa2, 0x9a, 0x4f, 0x60, 0xe7, 0x38, 0x72, 0xde, 0x74, 0xfc, 0x15, 0xa7, 0x4a, 0x3d,
0x67, 0x47, 0x69, 0xc8, 0x81, 0xda, 0x85, 0xeb, 0x0b, 0x28, 0xd4, 0xb0, 0xeb, 0x30, 0x7c, 0x7a,
0xc6, 0xb0, 0x23, 0xf2, 0x7a, 0xff, 0x59, 0x83, 0x96, 0xd8, 0xc9, 0x32, 0xce, 0xc8, 0x50, 0x0c,
0x19, 0x4f, 0x1b, 0x58, 0x85, 0x3f, 0xac, 0xa8, 0xdd, 0xd4, 0x0f, 0x94, 0x56, 0x85, 0x60, 0x47,
0x38, 0x60, 0xde, 0x54, 0x8a, 0x71, 0xb7, 0x94, 0x77, 0x5e, 0x88, 0xb2, 0x7c, 0xbd, 0x15, 0xf2,
0x95, 0x4f, 0x00, 0x58, 0x75, 0x02, 0xfc, 0x56, 0x83, 0xc1, 0x37, 0x8c, 0x9f, 0x87, 0xf1, 0x3c,
0x2b, 0x52, 0x52, 0x19, 0x39, 0xec, 0xd3, 0xf8, 0x62, 0x7a, 0x72, 0xc9, 0xb1, 0x2d, 0x44, 0x35,
0xb3, 0x7c, 0x70, 0xe7, 0xd0, 0x92, 0x83, 0xd6, 0x10, 0x7b, 0x9b, 0xd0, 0x7b, 0x75, 0x31, 0xc5,
0x43, 0x2a, 0x8c, 0xe5, 0xec, 0x09, 0x33, 0xdc, 0x72, 0xe2, 0x30, 0x8a, 0x98, 0xcc, 0xb4, 0x99,
0x81, 0x1d, 0xe5, 0x60, 0xed, 0xdc, 0x0a, 0x77, 0x22, 0x02, 0xeb, 0xe4, 0x60, 0x47, 0x0a, 0xac,
0xab, 0x99, 0xe5, 0x60, 0x3d, 0xd1, 0x55, 0x3e, 0x74, 0x0f, 0xa2, 0xf4, 0x38, 0xb1, 0x66, 0x2c,
0x9b, 0x7e, 0x1e, 0x72, 0xcb, 0x9b, 0xa6, 0xd9, 0x52, 0x50, 0x6f, 0x1a, 0xd7, 0x60, 0x10, 0xb1,
0x18, 0xfb, 0x92, 0x76, 0xeb, 0x28, 0x54, 0xd3, 0xf8, 0x1f, 0x6c, 0x89, 0xe5, 0xd4, 0x0d, 0xa6,
0x73, 0x16, 0x07, 0xcc, 0xf3, 0x43, 0x87, 0x51, 0x1e, 0xbb, 0xb0, 0xa9, 0x3e, 0x66, 0xc3, 0x28,
0x3e, 0x89, 0x7c, 0xcc, 0x23, 0x18, 0x1d, 0x9d, 0xe2, 0x8f, 0x2f, 0xf7, 0xdc, 0x60, 0xf6, 0xc4,
0xe2, 0x96, 0xb1, 0x8e, 0x75, 0x62, 0xb1, 0x1b, 0x3a, 0x09, 0x05, 0x44, 0x6f, 0x2e, 0x4d, 0x98,
0x33, 0xcd, 0x3f, 0x49, 0xd1, 0xf0, 0x27, 0xa1, 0xf8, 0xc4, 0x5d, 0x9f, 0x02, 0x9a, 0x3f, 0x88,
0x24, 0xa4, 0xf0, 0x26, 0xf4, 0x0a, 0xb2, 0x35, 0x51, 0xaf, 0xf5, 0xbc, 0x5e, 0x79, 0xa2, 0x7b,
0xb0, 0xce, 0x15, 0x8b, 0x29, 0x76, 0xad, 0x45, 0xb3, 0xb1, 0x4d, 0x96, 0x65, 0x8e, 0xe6, 0xe7,
0x00, 0x2f, 0xc5, 0x28, 0x0a, 0xc6, 0x78, 0x1e, 0xea, 0x02, 0xa1, 0xd0, 0xbe, 0x75, 0xa1, 0xd4,
0xc9, 0xb6, 0x30, 0xa7, 0x1f, 0x2d, 0xd7, 0xb3, 0x03, 0x4e, 0x04, 0xff, 0xaa, 0x41, 0x5f, 0x22,
0x48, 0x92, 0x08, 0x61, 0xe3, 0xf8, 0xe5, 0x10, 0xb7, 0x72, 0xc4, 0xf2, 0x2f, 0x8c, 0x16, 0x13,
0xdb, 0x30, 0x39, 0xb7, 0x22, 0x8a, 0xd2, 0x58, 0x65, 0x76, 0x07, 0x06, 0xb2, 0x1a, 0x64, 0xd8,
0x5c, 0x65, 0x78, 0x2f, 0xfb, 0xb9, 0x44, 0x26, 0xe2, 0xfc, 0xeb, 0xef, 0xdf, 0x28, 0x59, 0x08,
0x8e, 0x7b, 0xe2, 0xef, 0xd3, 0x80, 0xc7, 0x97, 0x93, 0x7b, 0x00, 0xc5, 0x2a, 0x1b, 0xbb, 0x39,
0xbb, 0xa4, 0xce, 0xc6, 0x4c, 0xce, 0x2c, 0x2f, 0xa5, 0xcc, 0x1f, 0xd5, 0x1f, 0xd6, 0xcc, 0xaf,
0x61, 0xfd, 0x4b, 0x6f, 0xee, 0x86, 0x9a, 0x0b, 0x5a, 0xf9, 0xd6, 0x4f, 0x61, 0x4c, 0xf9, 0x66,
0x4b, 0x37, 0xc0, 0xa5, 0x94, 0x0b, 0xe7, 0x3e, 0x8c, 0xe8, 0x04, 0x55, 0x78, 0xb2, 0x5f, 0x7e,
0x6f, 0x00, 0x14, 0x60, 0xc6, 0x23, 0x98, 0xb8, 0xe1, 0x14, 0x5b, 0xea, 0xcc, 0xb5, 0x99, 0x1c,
0x81, 0x69, 0xcc, 0xec, 0x34, 0x4e, 0xdc, 0x33, 0x46, 0x47, 0xe0, 0x0e, 0xe5, 0x52, 0xe5, 0xf0,
0x11, 0x6c, 0x17, 0xbe, 0x8e, 0xe6, 0x56, 0xbf, 0xd2, 0xed, 0x01, 0x6c, 0xa1, 0x1b, 0x1e, 0x5c,
0x69, 0xc9, 0xa9, 0x71, 0xa5, 0xd3, 0xa7, 0xb0, 0xab, 0xf1, 0xcc, 0x3a, 0x55, 0x73, 0x6d, 0x5e,
0xe9, 0xfa, 0x31, 0xec, 0xa0, 0xeb, 0xb9, 0xe5, 0xf2, 0xaa, 0x5f, 0xeb, 0x1f, 0xf0, 0xf4, 0x59,
0x3c, 0x2b, 0xf1, 0x6c, 0x5f, 0xe9, 0xf4, 0x01, 0x6c, 0xa2, 0x53, 0x25, 0x4e, 0xe7, 0x4d, 0x2e,
0x09, 0xb3, 0x39, 0x9e, 0x2a, 0x9a, 0x4b, 0xf7, 0x2a, 0x17, 0xf3, 0x31, 0x0c, 0x9e, 0xa7, 0x33,
0xc6, 0xbd, 0x13, 0xd5, 0xfd, 0xff, 0x76, 0x80, 0x7e, 0xad, 0x43, 0xff, 0x60, 0x16, 0x87, 0x69,
0x54, 0x9a, 0x72, 0xd9, 0xc3, 0x0b, 0x53, 0x2e, 0x6d, 0xee, 0xc2, 0x40, 0xfe, 0x80, 0x92, 0x99,
0x1c, 0x2e, 0x63, 0xb1, 0xd5, 0xb3, 0x8b, 0xcb, 0x49, 0xc6, 0x99, 0x0c, 0xcb, 0xe3, 0xa5, 0xb5,
0xdf, 0x67, 0x30, 0x3c, 0x95, 0x89, 0x90, 0xa5, 0x2c, 0xe5, 0xed, 0x3c, 0x72, 0x41, 0x70, 0x4f,
0x4f, 0x58, 0x0e, 0xd1, 0x73, 0xd8, 0x5c, 0xd8, 0x2c, 0xcf, 0x92, 0xa9, 0xcf, 0x52, 0x7f, 0x7f,
0x8b, 0x60, 0x75, 0x2f, 0x31, 0x60, 0x11, 0xb4, 0x24, 0x9f, 0xf7, 0x61, 0x18, 0xc8, 0x1f, 0x1d,
0xa5, 0x44, 0x43, 0x73, 0x2c, 0xfd, 0x20, 0xa1, 0x1a, 0xb6, 0xe0, 0xb7, 0x54, 0x0d, 0x5d, 0x5b,
0xac, 0x47, 0xd6, 0x11, 0x68, 0xe6, 0x47, 0x24, 0xff, 0x44, 0xde, 0xd8, 0x96, 0xbd, 0x15, 0xf6,
0xff, 0x68, 0x41, 0xe3, 0xf1, 0xe1, 0x57, 0xc6, 0x2b, 0x58, 0xaf, 0x3c, 0x7c, 0x8c, 0xfc, 0x58,
0x59, 0xfe, 0xbc, 0x9a, 0xbc, 0xb5, 0xea, 0x33, 0x5d, 0x1c, 0xd6, 0x32, 0xcc, 0xca, 0xad, 0x42,
0x61, 0x2e, 0xbf, 0xb3, 0x28, 0xcc, 0x55, 0x97, 0x91, 0x35, 0xe3, 0x13, 0x68, 0xcb, 0xf7, 0x90,
0x71, 0x8d, 0x6c, 0x4b, 0x0f, 0xab, 0xc9, 0x76, 0x65, 0x57, 0x39, 0x1e, 0x00, 0x14, 0x0f, 0x0f,
0x63, 0x4c, 0x66, 0x0b, 0x0f, 0xa9, 0xc9, 0xee, 0x92, 0x2f, 0x0a, 0xe4, 0x18, 0x36, 0xaa, 0x4f,
0x05, 0xa3, 0xa2, 0x43, 0xf5, 0x62, 0x3f, 0xb9, 0xb9, 0xf2, 0xbb, 0x0e, 0x5b, 0x7d, 0x30, 0x28,
0xd8, 0x15, 0xcf, 0x0f, 0x05, 0xbb, 0xf2, 0xa5, 0xb1, 0x66, 0x7c, 0x0b, 0xa3, 0xf2, 0x5d, 0xdf,
0xf8, 0x3f, 0x39, 0x2d, 0x7d, 0x82, 0x4c, 0x6e, 0xac, 0xf8, 0xaa, 0x00, 0x3f, 0x94, 0xad, 0x8b,
0x77, 0x8d, 0x5c, 0x65, 0xed, 0x21, 0x30, 0xb9, 0x56, 0xde, 0x54, 0x5e, 0xf7, 0xa1, 0x2d, 0x6f,
0x90, 0xaa, 0x64, 0xa5, 0x0b, 0xe5, 0x64, 0xa0, 0xef, 0x9a, 0x6b, 0xf7, 0x6b, 0x78, 0x4a, 0x75,
0x9f, 0x31, 0x2e, 0xfb, 0x59, 0x0f, 0xb5, 0xe0, 0x22, 0x36, 0x33, 0x97, 0x93, 0xb6, 0xf8, 0xa7,
0xc0, 0x83, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x0f, 0x82, 0xdf, 0x21, 0x10, 0x00, 0x00,
}

View file

@ -23,9 +23,9 @@ message CreateContainerRequest {
message CreateContainerResponse {
uint32 pid = 1; // PID of the containers main process
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)
string stdin = 2; // path to the file where stdin will be read (optional)
string stdout = 3; // path to file where stdout will be written (optional)
string stderr = 4; // path to file where stderr will be written (optional)
}
message SignalRequest {
@ -44,10 +44,7 @@ message AddProcessRequest {
repeated string args = 4; // Arguments for process, first is binary path itself
repeated string env = 5; // List of environment variables for process
string cwd = 6; // Workind directory of process
string stdin = 7; // path to the file where stdin will be read (optional)
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)
string pid = 7; // Process ID
};
message User {
@ -57,6 +54,9 @@ message User {
}
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 {

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

@ -1,43 +1,21 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"os/signal"
"path/filepath"
"strconv"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/docker/containerd/util"
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/specs"
)
const (
bufferSize = 2048
)
var fexec bool
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
func init() {
flag.BoolVar(&fexec, "exec", false, "exec a process instead of starting the init")
flag.Parse()
}
// 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
// to the state directory where the shim can locate fifos and other information.
//
// └── shim
// ├── control
// ├── stderr
// ├── stdin
// ├── stdout
// ├── pid
// └── exit
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
// or if runc exits before we hit the handler
signals := make(chan os.Signal, bufferSize)
signals := make(chan os.Signal, 2048)
signal.Notify(signals)
// set the shim as the subreaper for all orphaned processes created by the container
if err := util.SetSubreaper(1); err != nil {
logrus.WithField("error", err).Fatal("shim: set as subreaper")
}
// 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 {
logrus.WithField("error", err).Fatal("shim: open exit pipe")
}
defer f.Close()
// open the fifos for use with the command
std, err := openContainerSTDIO(os.Args[1])
p, err := newProcess(flag.Arg(0), flag.Arg(1), fexec)
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
runcPid, err := startRunc(std, os.Args[2])
if err != nil {
logrus.WithField("error", err).Fatal("shim: start runc")
if err := p.start(); err != nil {
logrus.WithField("error", err).Fatal("shim: start process")
}
var exitShim bool
for s := range signals {
@ -92,22 +56,27 @@ func main() {
}
for _, e := range exits {
// check to see if runc is one of the processes that has exited
if e.Pid == runcPid {
if e.Pid == p.pid() {
exitShim = true
logrus.WithFields(logrus.Fields{"pid": e.Pid, "status": e.Status}).Info("shim: runc exited")
if err := writeInt(filepath.Join(os.Args[1], "exitStatus"), e.Status); err != nil {
logrus.WithFields(logrus.Fields{"error": err, "status": e.Status}).Error("shim: write exit status")
logrus.WithFields(logrus.Fields{
"pid": e.Pid,
"status": e.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
if exitShim {
if err := std.Close(); err != nil {
if err := p.Close(); err != nil {
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")
}
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 {
f, err := os.Create(path)
if err != nil {

165
containerd-shim/process.go Normal file
View 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
}

View file

@ -145,7 +145,7 @@ var attachCommand = cli.Command{
io.Copy(stdin, os.Stdin)
closer()
}()
if err := waitForExit(c, id, closer); err != nil {
if err := waitForExit(c, id, "init", closer); err != nil {
fatal(err.Error(), 1)
}
},
@ -217,7 +217,7 @@ var startCommand = cli.Command{
io.Copy(stdin, os.Stdin)
restoreAndCloseStdin()
}()
if err := waitForExit(c, id, restoreAndCloseStdin); err != nil {
if err := waitForExit(c, id, "init", restoreAndCloseStdin); err != nil {
fatal(err.Error(), 1)
}
}
@ -303,6 +303,10 @@ var execCommand = cli.Command{
Name: "id",
Usage: "container id to add the process to",
},
cli.StringFlag{
Name: "pid",
Usage: "process id for the new process",
},
cli.BoolFlag{
Name: "attach,a",
Usage: "connect to the stdio of the container",
@ -330,58 +334,50 @@ var execCommand = cli.Command{
},
},
Action: func(context *cli.Context) {
panic("not implemented")
/*
p := &types.AddProcessRequest{
Args: context.Args(),
Cwd: context.String("cwd"),
Terminal: context.Bool("tty"),
Id: context.String("id"),
Env: context.StringSlice("env"),
User: &types.User{
Uid: uint32(context.Int("uid")),
Gid: uint32(context.Int("gid")),
},
}
c := getClient(context)
events, err := c.Events(netcontext.Background(), &types.EventsRequest{})
if err != nil {
fatal(err.Error(), 1)
}
if context.Bool("attach") {
if p.Terminal {
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)
p := &types.AddProcessRequest{
Pid: context.String("pid"),
Args: context.Args(),
Cwd: context.String("cwd"),
Terminal: context.Bool("tty"),
Id: context.String("id"),
Env: context.StringSlice("env"),
User: &types.User{
Uid: uint32(context.Int("uid")),
Gid: uint32(context.Int("gid")),
},
}
c := getClient(context)
resp, err := c.AddProcess(netcontext.Background(), p)
if err != nil {
fatal(err.Error(), 1)
}
if context.Bool("attach") {
if context.Bool("tty") {
s, err := term.SetRawTerminal(os.Stdin.Fd())
if err != nil {
fatal(err.Error(), 1)
}
if context.Bool("attach") {
go func() {
io.Copy(stdin, os.Stdin)
if state != nil {
term.RestoreTerminal(os.Stdin.Fd(), state)
}
stdin.Close()
}()
for {
e, err := events.Recv()
if err != nil {
fatal(err.Error(), 1)
}
if e.Pid == r.Pid && e.Type == "exit" {
os.Exit(int(e.Status))
}
}
state = s
}
if err := attachStdio(resp.Stdin, resp.Stdout, resp.Stderr); err != nil {
fatal(err.Error(), 1)
}
}
if context.Bool("attach") {
restoreAndCloseStdin := func() {
if state != nil {
term.RestoreTerminal(os.Stdin.Fd(), state)
}
*/
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{})
if err != nil {
return err
@ -419,7 +415,7 @@ func waitForExit(c types.APIClient, id string, closer func()) error {
events, _ = c.Events(netcontext.Background(), &types.EventsRequest{})
continue
}
if e.Id == id && e.Type == "exit" && e.Pid == "init" {
if e.Id == id && e.Type == "exit" && e.Pid == pid {
closer()
os.Exit(int(e.Status))
}

View file

@ -1,97 +1,17 @@
package runtime
import (
"io"
"encoding/json"
"io/ioutil"
"os"
"time"
"os/exec"
"path/filepath"
"syscall"
"github.com/Sirupsen/logrus"
"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 {
// ID returns the container ID
ID() string
@ -99,10 +19,10 @@ type Container interface {
Path() string
// Start starts the init process of the container
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() error
// Pid returns the container's init process id
// Pid() (int, error)
// Processes returns all the containers processes that have been added
Processes() ([]Process, error)
// State returns the containers runtime state
@ -111,6 +31,7 @@ type Container interface {
Resume() error
// Pause pauses a running container
Pause() error
RemoveProcess(string) error
// Checkpoints returns all the checkpoints for a container
// Checkpoints() ([]Checkpoint, error)
// Checkpoint creates a new checkpoint
@ -124,3 +45,183 @@ type Container interface {
// OOM signals the channel if the container received an OOM notification
// 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
}

View file

@ -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
}

View file

@ -1,6 +1,8 @@
package runtime
import (
"encoding/json"
"io"
"io/ioutil"
"os"
"path/filepath"
@ -10,6 +12,31 @@ import (
"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) {
p := &process{
root: root,
@ -17,6 +44,14 @@ func newProcess(root, id string, c *container, s specs.Process) (*process, error
container: c,
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
for name, fd := range map[string]*string{
"stdin": &p.stdin,
@ -58,7 +93,7 @@ func loadProcess(root, id string, c *container, s specs.Process) (*process, erro
}
return nil, err
}
return nil, ErrProcessExited
return p, nil
}
func getExitPipe(path string) (*os.File, error) {

View file

@ -1,6 +1,9 @@
package runtime
import "errors"
import (
"errors"
"time"
)
var (
ErrNotChildProcess = errors.New("containerd: not a child process for container")
@ -14,3 +17,46 @@ var (
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
}

View file

@ -1,5 +1,7 @@
package supervisor
import "time"
type AddProcessEvent struct {
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
// could be stopped and removed...
func (h *AddProcessEvent) Handle(e *Event) error {
/*
start := time.Now()
ci, ok := h.s.containers[e.ID]
if !ok {
return ErrContainerNotFound
}
p, io, err := h.s.runtime.StartProcess(ci.container, *e.Process, e.Console)
if err != nil {
return err
}
if e.Pid, err = p.Pid(); err != nil {
return err
}
h.s.processes[e.Pid] = &containerInfo{
container: ci.container,
}
l, err := h.s.copyIO(e.Stdin, e.Stdout, e.Stderr, io)
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)
*/
start := time.Now()
ci, ok := h.s.containers[e.ID]
if !ok {
return ErrContainerNotFound
}
process, err := ci.container.Exec(e.Pid, *e.ProcessSpec)
if err != nil {
return err
}
if err := h.s.monitorProcess(process); err != nil {
return err
}
ExecProcessTimer.UpdateSince(start)
e.StartResponse <- StartResponse{
Stdin: process.Stdin(),
Stdout: process.Stdout(),
Stderr: process.Stderr(),
}
return nil
}

View file

@ -17,11 +17,6 @@ func (h *DeleteEvent) Handle(e *Event) error {
if err := h.deleteContainer(i.container); err != nil {
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{
Type: ExitEventType,
ID: e.ID,

View file

@ -25,7 +25,9 @@ func (h *ExitEvent) Handle(e *Event) error {
if proc.ID() != runtime.InitProcessID {
ne := NewEvent(ExecExitEventType)
ne.ID = proc.Container().ID()
ne.Pid = proc.ID()
ne.Status = status
ne.Process = proc
h.s.SendEvent(ne)
return nil
@ -51,17 +53,11 @@ type ExecExitEvent struct {
}
func (h *ExecExitEvent) Handle(e *Event) error {
container := e.Process.Container()
// exec process: we remove this process without notifying the main event loop
/*
info := h.s.processes[e.Pid]
if err := info.container.RemoveProcess(e.Pid); err != nil {
logrus.WithField("error", err).Error("containerd: find container for pid")
}
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)
*/
if err := container.RemoveProcess(e.Pid); err != nil {
logrus.WithField("error", err).Error("containerd: find container for pid")
}
h.s.notifySubscribers(e)
return nil
}

View file

@ -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
}

View file

@ -11,6 +11,7 @@ var (
EventsCounter = metrics.NewCounter()
ExecProcessTimer = metrics.NewTimer()
ExitProcessTimer = metrics.NewTimer()
EpollFdCounter = metrics.NewCounter()
)
func Metrics() map[string]interface{} {
@ -23,5 +24,6 @@ func Metrics() map[string]interface{} {
"events": EventsCounter,
"exec-process-time": ExecProcessTimer,
"exit-process-time": ExitProcessTimer,
"epoll-fds": EpollFdCounter,
}
}

View file

@ -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 {
return err
}
EpollFdCounter.Inc(1)
m.processes[fd] = p
return nil
}
@ -75,6 +76,7 @@ func (m *Monitor) start() {
}); err != nil {
logrus.WithField("error", err).Fatal("containerd: epoll remove fd")
}
EpollFdCounter.Dec(1)
if err := proc.Close(); err != nil {
logrus.WithField("error", err).Error("containerd: close process IO")
}

View file

@ -5,20 +5,18 @@ type SignalEvent struct {
}
func (h *SignalEvent) Handle(e *Event) error {
/*
i, ok := h.s.containers[e.ID]
if !ok {
return ErrContainerNotFound
i, ok := h.s.containers[e.ID]
if !ok {
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
}

69
supervisor/sort_test.go Normal file
View 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)
}
}

View file

@ -3,7 +3,7 @@ package supervisor
import (
"io/ioutil"
"os"
"path/filepath"
"sort"
"sync"
"time"
@ -76,7 +76,6 @@ func New(stateDir string, tasks chan *StartTask, oom bool) (*Supervisor, error)
type containerInfo struct {
container runtime.Container
copier *copier
}
type Supervisor struct {
@ -195,14 +194,6 @@ func (s *Supervisor) restore() error {
id := d.Name()
container, err := runtime.Load(s.stateDir, id)
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
}
processes, err := container.Processes()
@ -214,11 +205,42 @@ func (s *Supervisor) restore() error {
container: container,
}
logrus.WithField("id", id).Debug("containerd: container restored")
var exitedProcesses []runtime.Process
for _, p := range processes {
if err := s.monitorProcess(p); err != nil {
return err
if _, err := p.ExitStatus(); err == nil {
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
}
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"
}

View file

@ -27,17 +27,17 @@ func (h *UpdateEvent) Handle(e *Event) error {
}
}
if e.Signal != nil {
/*
// signal the pid1/main process of the container
processes, err := container.Processes()
if err != nil {
return err
// signal the pid1/main process of the container
processes, err := container.Processes()
if err != nil {
return err
}
for _, p := range processes {
if p.ID() == runtime.InitProcessID {
return p.Signal(e.Signal)
}
if len(processes) == 0 {
return ErrProcessNotFound
}
return processes[0].Signal(e.Signal)
*/
}
return ErrProcessNotFound
}
return nil
}

View file

@ -15,7 +15,6 @@ type Worker interface {
type StartTask struct {
Container runtime.Container
Checkpoint string
IO *runtime.IO
Stdin string
Stdout string
Stderr string

View file

@ -1,3 +1,3 @@
package containerd
const Version = "0.0.4"
const Version = "0.0.5"