Merge pull request #2756 from jterry75/runhcs_opts

Implement io.containerd.runhcs.v1 runtime activation options
This commit is contained in:
Michael Crosby 2018-11-05 13:33:32 -05:00 committed by GitHub
commit 0535fa60fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 662 additions and 120 deletions

View File

@ -116,11 +116,11 @@ AUTHORS: .mailmap .git/HEAD
generate: protos generate: protos
@echo "$(WHALE) $@" @echo "$(WHALE) $@"
@PATH=${ROOTDIR}/bin:${PATH} go generate -x ${PACKAGES} @PATH="${ROOTDIR}/bin:${PATH}" go generate -x ${PACKAGES}
protos: bin/protoc-gen-gogoctrd ## generate protobuf protos: bin/protoc-gen-gogoctrd ## generate protobuf
@echo "$(WHALE) $@" @echo "$(WHALE) $@"
@PATH=${ROOTDIR}/bin:${PATH} protobuild --quiet ${PACKAGES} @PATH="${ROOTDIR}/bin:${PATH}" protobuild --quiet ${PACKAGES}
check-protos: protos ## check if protobufs needs to be generated again check-protos: protos ## check if protobufs needs to be generated again
@echo "$(WHALE) $@" @echo "$(WHALE) $@"

View File

@ -66,6 +66,14 @@ ignore_files = [
"gogoproto/gogo.proto" "gogoproto/gogo.proto"
] ]
[[descriptors]]
prefix = "github.com/containerd/containerd/runtime/v2/runhcs/options"
target = "runtime/v2/runhcs/options/next.pb.txt"
ignore_files = [
"google/protobuf/descriptor.proto",
"gogoproto/gogo.proto"
]
[[descriptors]] [[descriptors]]
prefix = "github.com/containerd/containerd/windows/hcsshimtypes" prefix = "github.com/containerd/containerd/windows/hcsshimtypes"
target = "windows/hcsshimtypes/next.pb.txt" target = "windows/hcsshimtypes/next.pb.txt"

View File

@ -23,6 +23,7 @@ import (
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands"
"github.com/containerd/containerd/oci" "github.com/containerd/containerd/oci"
"github.com/containerd/containerd/runtime/v2/runhcs/options"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/urfave/cli"
@ -100,7 +101,14 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
} }
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label")))) cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
cOpts = append(cOpts, containerd.WithRuntime(context.String("runtime"), nil)) runtime := context.String("runtime")
var runtimeOpts interface{}
if runtime == "io.containerd.runhcs.v1" {
runtimeOpts = &options.Options{
Debug: context.GlobalBool("debug"),
}
}
cOpts = append(cOpts, containerd.WithRuntime(runtime, runtimeOpts))
var s specs.Spec var s specs.Spec
spec = containerd.WithSpec(&s, opts...) spec = containerd.WithSpec(&s, opts...)

View File

@ -0,0 +1,17 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package options

View File

@ -0,0 +1,46 @@
file {
name: "github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto"
package: "containerd.runhcs.v1"
dependency: "gogoproto/gogo.proto"
message_type {
name: "Options"
field {
name: "debug"
number: 1
label: LABEL_OPTIONAL
type: TYPE_BOOL
json_name: "debug"
}
field {
name: "debug_type"
number: 2
label: LABEL_OPTIONAL
type: TYPE_ENUM
type_name: ".containerd.runhcs.v1.Options.DebugType"
json_name: "debugType"
}
field {
name: "registry_root"
number: 3
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "registryRoot"
}
enum_type {
name: "DebugType"
value {
name: "NPIPE"
number: 0
}
value {
name: "FILE"
number: 1
}
}
}
options {
go_package: "github.com/containerd/containerd/runtime/v2/runhcs/options;options"
}
weak_dependency: 0
syntax: "proto3"
}

View File

@ -0,0 +1,418 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
/*
Package options is a generated protocol buffer package.
It is generated from these files:
github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
It has these top-level messages:
Options
*/
package options
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
import strings "strings"
import reflect "reflect"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type Options_DebugType int32
const (
Options_NPIPE Options_DebugType = 0
Options_FILE Options_DebugType = 1
)
var Options_DebugType_name = map[int32]string{
0: "NPIPE",
1: "FILE",
}
var Options_DebugType_value = map[string]int32{
"NPIPE": 0,
"FILE": 1,
}
func (x Options_DebugType) String() string {
return proto.EnumName(Options_DebugType_name, int32(x))
}
func (Options_DebugType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRunhcs, []int{0, 0} }
type Options struct {
// enable debug tracing
Debug bool `protobuf:"varint,1,opt,name=debug,proto3" json:"debug,omitempty"`
// debug tracing output type
DebugType Options_DebugType `protobuf:"varint,2,opt,name=debug_type,json=debugType,proto3,enum=containerd.runhcs.v1.Options_DebugType" json:"debug_type,omitempty"`
// registry key root for storage of the runhcs container state
RegistryRoot string `protobuf:"bytes,3,opt,name=registry_root,json=registryRoot,proto3" json:"registry_root,omitempty"`
}
func (m *Options) Reset() { *m = Options{} }
func (*Options) ProtoMessage() {}
func (*Options) Descriptor() ([]byte, []int) { return fileDescriptorRunhcs, []int{0} }
func init() {
proto.RegisterType((*Options)(nil), "containerd.runhcs.v1.Options")
proto.RegisterEnum("containerd.runhcs.v1.Options_DebugType", Options_DebugType_name, Options_DebugType_value)
}
func (m *Options) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Options) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Debug {
dAtA[i] = 0x8
i++
if m.Debug {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.DebugType != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintRunhcs(dAtA, i, uint64(m.DebugType))
}
if len(m.RegistryRoot) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.RegistryRoot)))
i += copy(dAtA[i:], m.RegistryRoot)
}
return i, nil
}
func encodeVarintRunhcs(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *Options) Size() (n int) {
var l int
_ = l
if m.Debug {
n += 2
}
if m.DebugType != 0 {
n += 1 + sovRunhcs(uint64(m.DebugType))
}
l = len(m.RegistryRoot)
if l > 0 {
n += 1 + l + sovRunhcs(uint64(l))
}
return n
}
func sovRunhcs(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozRunhcs(x uint64) (n int) {
return sovRunhcs(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *Options) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&Options{`,
`Debug:` + fmt.Sprintf("%v", this.Debug) + `,`,
`DebugType:` + fmt.Sprintf("%v", this.DebugType) + `,`,
`RegistryRoot:` + fmt.Sprintf("%v", this.RegistryRoot) + `,`,
`}`,
}, "")
return s
}
func valueToStringRunhcs(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *Options) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Options: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Options: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Debug", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Debug = bool(v != 0)
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DebugType", wireType)
}
m.DebugType = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.DebugType |= (Options_DebugType(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field RegistryRoot", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRunhcs
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RegistryRoot = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipRunhcs(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthRunhcs
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipRunhcs(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRunhcs
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRunhcs
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRunhcs
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthRunhcs
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowRunhcs
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipRunhcs(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthRunhcs = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowRunhcs = fmt.Errorf("proto: integer overflow")
)
func init() {
proto.RegisterFile("github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto", fileDescriptorRunhcs)
}
var fileDescriptorRunhcs = []byte{
// 265 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x4f, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d,
0x4a, 0x41, 0x66, 0x16, 0x95, 0xe6, 0x95, 0x64, 0xe6, 0xa6, 0xea, 0x97, 0x19, 0x81, 0x98, 0x19,
0xc9, 0xc5, 0xfa, 0xf9, 0x05, 0x25, 0x99, 0xf9, 0x79, 0xc5, 0x50, 0xae, 0x5e, 0x41, 0x51, 0x7e,
0x49, 0xbe, 0x90, 0x08, 0x42, 0x8b, 0x1e, 0x54, 0xa2, 0xcc, 0x50, 0x4a, 0x24, 0x3d, 0x3f, 0x3d,
0x1f, 0xac, 0x40, 0x1f, 0xc4, 0x82, 0xa8, 0x55, 0x5a, 0xc7, 0xc8, 0xc5, 0xee, 0x0f, 0x31, 0x44,
0x48, 0x84, 0x8b, 0x35, 0x25, 0x35, 0xa9, 0x34, 0x5d, 0x82, 0x51, 0x81, 0x51, 0x83, 0x23, 0x08,
0xc2, 0x11, 0x72, 0xe3, 0xe2, 0x02, 0x33, 0xe2, 0x4b, 0x2a, 0x0b, 0x52, 0x25, 0x98, 0x14, 0x18,
0x35, 0xf8, 0x8c, 0xd4, 0xf5, 0xb0, 0x59, 0xa1, 0x07, 0x35, 0x48, 0xcf, 0x05, 0xa4, 0x3e, 0xa4,
0xb2, 0x20, 0x35, 0x88, 0x33, 0x05, 0xc6, 0x14, 0x52, 0xe6, 0xe2, 0x2d, 0x4a, 0x4d, 0xcf, 0x2c,
0x2e, 0x29, 0xaa, 0x8c, 0x2f, 0xca, 0xcf, 0x2f, 0x91, 0x60, 0x56, 0x60, 0xd4, 0xe0, 0x0c, 0xe2,
0x81, 0x09, 0x06, 0xe5, 0xe7, 0x97, 0x28, 0x29, 0x70, 0x71, 0xc2, 0x35, 0x0b, 0x71, 0x72, 0xb1,
0xfa, 0x05, 0x78, 0x06, 0xb8, 0x0a, 0x30, 0x08, 0x71, 0x70, 0xb1, 0xb8, 0x79, 0xfa, 0xb8, 0x0a,
0x30, 0x3a, 0xc5, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6,
0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0xca, 0x89, 0xfc,
0xf0, 0xb3, 0x86, 0xd2, 0x11, 0x0c, 0x49, 0x6c, 0xe0, 0x70, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff,
0xff, 0x91, 0x7a, 0xda, 0xa5, 0x8e, 0x01, 0x00, 0x00,
}

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package containerd.runhcs.v1;
import weak "gogoproto/gogo.proto";
option go_package = "github.com/containerd/containerd/runtime/v2/runhcs/options;options";
message Options {
// enable debug tracing
bool debug = 1;
enum DebugType {
NPIPE = 0;
FILE = 1;
}
// debug tracing output type
DebugType debug_type = 2;
// registry key root for storage of the runhcs container state
string registry_root = 3;
}

View File

@ -28,6 +28,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -43,9 +44,11 @@ import (
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/runtime/v2/runhcs/options"
"github.com/containerd/containerd/runtime/v2/shim" "github.com/containerd/containerd/runtime/v2/shim"
taskAPI "github.com/containerd/containerd/runtime/v2/task" taskAPI "github.com/containerd/containerd/runtime/v2/task"
"github.com/containerd/go-runc" "github.com/containerd/go-runc"
"github.com/containerd/typeurl"
ptypes "github.com/gogo/protobuf/types" ptypes "github.com/gogo/protobuf/types"
oci "github.com/opencontainers/runtime-spec/specs-go" oci "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -63,18 +66,6 @@ var (
empty = &ptypes.Empty{} empty = &ptypes.Empty{}
) )
func newRunhcs(debugLog string) *runhcs.Runhcs {
rhs := &runhcs.Runhcs{
Debug: debugLog != "",
LogFormat: runhcs.JSON,
Owner: "containerd-runhcs-shim-v1",
}
if rhs.Debug {
rhs.Log = debugLog
}
return rhs
}
// forwardRunhcsLogs copies logs from c and writes them to the ctx logger // forwardRunhcsLogs copies logs from c and writes them to the ctx logger
// upstream. // upstream.
func forwardRunhcsLogs(ctx context.Context, c net.Conn, fields logrus.Fields) { func forwardRunhcsLogs(ctx context.Context, c net.Conn, fields logrus.Fields) {
@ -154,16 +145,31 @@ type service struct {
context context.Context context context.Context
// debugLog if not "" indicates the log pipe path for runhcs.exe to write its logs to. // debugLog if not "" indicates the log file or pipe path for runhcs.exe to
// write its logs to.
debugLog string debugLog string
// if `shimOpts.DebugType == options.Opitons_NPIPE` will hold the listener
// for the runhcs.exe to connect to for sending logs.
debugListener net.Listener debugListener net.Listener
shimOpts options.Options
id string id string
processes map[string]*process processes map[string]*process
publisher events.Publisher publisher events.Publisher
} }
func (s *service) newRunhcs() *runhcs.Runhcs {
return &runhcs.Runhcs{
Debug: s.shimOpts.Debug,
Log: s.debugLog,
LogFormat: runhcs.JSON,
Owner: "containerd-runhcs-shim-v1",
Root: s.shimOpts.RegistryRoot,
}
}
// getProcess attempts to get a process by id. // getProcess attempts to get a process by id.
// The caller MUST NOT have locked s.mu previous to calling this function. // The caller MUST NOT have locked s.mu previous to calling this function.
func (s *service) getProcess(id, execID string) (*process, error) { func (s *service) getProcess(id, execID string) (*process, error) {
@ -196,7 +202,7 @@ func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error)
return nil, err return nil, err
} }
// Forcibly shut down any container in this bundle // Forcibly shut down any container in this bundle
rhcs := newRunhcs("") rhcs := s.newRunhcs()
dopts := &runhcs.DeleteOpts{ dopts := &runhcs.DeleteOpts{
Force: true, Force: true,
} }
@ -290,7 +296,7 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
// This is a container // This is a container
if p.cid == p.id { if p.cid == p.id {
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
cs, err := rhcs.State(ctx, p.id) cs, err := rhcs.State(ctx, p.id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -406,6 +412,19 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
_, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return nil, errors.Wrap(err, "create namespace")
}
if r.Options != nil {
v, err := typeurl.UnmarshalAny(r.Options)
if err != nil {
return nil, err
}
s.shimOpts = *v.(*options.Options)
}
if p := s.processes[r.ID]; p != nil { if p := s.processes[r.ID]; p != nil {
return nil, errdefs.ToGRPCf(errdefs.ErrAlreadyExists, "process %s already exists", r.ID) return nil, errdefs.ToGRPCf(errdefs.ErrAlreadyExists, "process %s already exists", r.ID)
} }
@ -445,10 +464,12 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
pr.close() pr.close()
} }
}() }()
// TODO: Parse the real RunHcs Opts r.Options
opts, ok := ctx.Value(shim.OptsKey{}).(shim.Opts) if s.shimOpts.Debug {
if ok && opts.Debug {
if s.debugLog == "" { if s.debugLog == "" {
if s.shimOpts.DebugType == options.Options_FILE {
s.debugLog = filepath.Join(r.Bundle, fmt.Sprintf("runhcs-%s.log", r.ID))
} else {
logPath := safePipePrefix + fmt.Sprintf("runhcs-log-%s", r.ID) logPath := safePipePrefix + fmt.Sprintf("runhcs-log-%s", r.ID)
l, err := winio.ListenPipe(logPath, nil) l, err := winio.ListenPipe(logPath, nil)
if err != nil { if err != nil {
@ -463,7 +484,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
for { for {
c, err := s.debugListener.Accept() c, err := s.debugListener.Accept()
if err != nil { if err != nil {
if err == errorConnectionAborted { if err == winio.ErrPipeListenerClosed {
break break
} }
log.G(ctx).WithError(err).Debug("log accept failure") log.G(ctx).WithError(err).Debug("log accept failure")
@ -479,14 +500,19 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
}() }()
} }
} }
}
pidfilePath := path.Join(r.Bundle, "runhcs-pidfile.pid") pidfilePath := path.Join(r.Bundle, "runhcs-pidfile.pid")
copts := &runhcs.CreateOpts{ copts := &runhcs.CreateOpts{
IO: io, IO: io,
PidFile: pidfilePath, PidFile: pidfilePath,
} }
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
if rhcs.Debug { if rhcs.Debug {
if s.shimOpts.DebugType == options.Options_FILE {
copts.ShimLog = filepath.Join(r.Bundle, fmt.Sprintf("runhcs-shim-%s.log", r.ID))
copts.VMLog = filepath.Join(r.Bundle, fmt.Sprintf("runhcs-vmshim-%s.log", r.ID))
} else {
doForwardLogs := func(source, logPipeFmt string, opt *string) error { doForwardLogs := func(source, logPipeFmt string, opt *string) error {
pipeName := fmt.Sprintf(logPipeFmt, r.ID) pipeName := fmt.Sprintf(logPipeFmt, r.ID)
*opt = safePipePrefix + pipeName *opt = safePipePrefix + pipeName
@ -523,6 +549,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
return nil, err return nil, err
} }
} }
}
err = rhcs.Create(ctx, r.ID, r.Bundle, copts) err = rhcs.Create(ctx, r.ID, r.Bundle, copts)
if err != nil { if err != nil {
return nil, err return nil, err
@ -571,7 +598,7 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
return nil, errors.New("cannot start already started container or process") return nil, errors.New("cannot start already started container or process")
} }
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
// This is a start/exec // This is a start/exec
if r.ExecID != "" { if r.ExecID != "" {
@ -585,6 +612,9 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
} }
if rhcs.Debug { if rhcs.Debug {
if s.shimOpts.DebugType == options.Options_FILE {
eopts.ShimLog = filepath.Join(p.bundle, fmt.Sprintf("runhcs-shim-%s.log", execFmt))
} else {
doForwardLogs := func(source, pipeName string, opt *string) error { doForwardLogs := func(source, pipeName string, opt *string) error {
*opt = safePipePrefix + pipeName *opt = safePipePrefix + pipeName
l, err := winio.ListenPipe(*opt, nil) l, err := winio.ListenPipe(*opt, nil)
@ -617,6 +647,7 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
return nil, err return nil, err
} }
} }
}
// ID here is the containerID to exec the process in. // ID here is the containerID to exec the process in.
err = rhcs.Exec(ctx, r.ID, procConfig, eopts) err = rhcs.Exec(ctx, r.ID, procConfig, eopts)
@ -683,7 +714,7 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
// This is a container // This is a container
if p.cid == p.id { if p.cid == p.id {
rhs := newRunhcs(s.debugLog) rhs := s.newRunhcs()
dopts := &runhcs.DeleteOpts{ dopts := &runhcs.DeleteOpts{
Force: true, Force: true,
} }
@ -729,7 +760,7 @@ func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.E
return nil, err return nil, err
} }
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
if err = rhcs.Pause(ctx, p.id); err != nil { if err = rhcs.Pause(ctx, p.id); err != nil {
return nil, err return nil, err
} }
@ -748,7 +779,7 @@ func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes
return nil, err return nil, err
} }
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
if err = rhcs.Resume(ctx, p.id); err != nil { if err = rhcs.Resume(ctx, p.id); err != nil {
return nil, err return nil, err
} }
@ -773,9 +804,8 @@ func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Emp
return nil, err return nil, err
} }
// TODO: JTERRY75 runhcs needs r.Signal in string form
// TODO: JTERRY75 runhcs support for r.All? // TODO: JTERRY75 runhcs support for r.All?
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
if err = rhcs.Kill(ctx, p.id, strconv.FormatUint(uint64(r.Signal), 10)); err != nil { if err = rhcs.Kill(ctx, p.id, strconv.FormatUint(uint64(r.Signal), 10)); err != nil {
if !strings.Contains(err.Error(), "container is stopped") { if !strings.Contains(err.Error(), "container is stopped") {
return nil, err return nil, err
@ -882,7 +912,7 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
opts := runhcs.ResizeTTYOpts{ opts := runhcs.ResizeTTYOpts{
Pid: &pid, Pid: &pid,
} }
rhcs := newRunhcs(s.debugLog) rhcs := s.newRunhcs()
if err = rhcs.ResizeTTY(ctx, p.cid, uint16(r.Width), uint16(r.Height), &opts); err != nil { if err = rhcs.ResizeTTY(ctx, p.cid, uint16(r.Width), uint16(r.Height), &opts); err != nil {
return nil, err return nil, err
} }

View File

@ -27,7 +27,6 @@ import (
"os" "os"
"os/exec" "os/exec"
"sync" "sync"
"syscall"
"unsafe" "unsafe"
winio "github.com/Microsoft/go-winio" winio "github.com/Microsoft/go-winio"
@ -40,10 +39,6 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
const (
errorConnectionAborted syscall.Errno = 1236
)
// setupSignals creates a new signal handler for all signals // setupSignals creates a new signal handler for all signals
func setupSignals() (chan os.Signal, error) { func setupSignals() (chan os.Signal, error) {
signals := make(chan os.Signal, 32) signals := make(chan os.Signal, 32)
@ -209,7 +204,7 @@ func (dswl *deferredShimWriteLogger) beginAccept() {
dswl.mu.Unlock() dswl.mu.Unlock()
c, err := dswl.l.Accept() c, err := dswl.l.Accept()
if err == errorConnectionAborted { if err == winio.ErrPipeListenerClosed {
dswl.mu.Lock() dswl.mu.Lock()
dswl.aborted = true dswl.aborted = true
dswl.l.Close() dswl.l.Close()