Merge pull request #2686 from jterry75/runhcs_improvements
Various containerd-shim-runhcs bug fixes/improvements
This commit is contained in:
commit
655ba65875
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/containerd/containerd/runtime/v2/task"
|
"github.com/containerd/containerd/runtime/v2/task"
|
||||||
"github.com/containerd/ttrpc"
|
"github.com/containerd/ttrpc"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func shimBinary(ctx context.Context, bundle *Bundle, runtime, containerdAddress string, events *exchange.Exchange, rt *runtime.TaskList) *binary {
|
func shimBinary(ctx context.Context, bundle *Bundle, runtime, containerdAddress string, events *exchange.Exchange, rt *runtime.TaskList) *binary {
|
||||||
@ -52,13 +53,18 @@ type binary struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *binary) Start(ctx context.Context) (_ *shim, err error) {
|
func (b *binary) Start(ctx context.Context) (_ *shim, err error) {
|
||||||
|
args := []string{"-id", b.bundle.ID}
|
||||||
|
if logrus.GetLevel() == logrus.DebugLevel {
|
||||||
|
args = append(args, "-debug")
|
||||||
|
}
|
||||||
|
args = append(args, "start")
|
||||||
|
|
||||||
cmd, err := client.Command(
|
cmd, err := client.Command(
|
||||||
ctx,
|
ctx,
|
||||||
b.runtime,
|
b.runtime,
|
||||||
b.containerdAddress,
|
b.containerdAddress,
|
||||||
b.bundle.Path,
|
b.bundle.Path,
|
||||||
"-id", b.bundle.ID,
|
args...,
|
||||||
"start",
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -22,15 +22,19 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
winio "github.com/Microsoft/go-winio"
|
||||||
"github.com/Microsoft/hcsshim/cmd/go-runhcs"
|
"github.com/Microsoft/hcsshim/cmd/go-runhcs"
|
||||||
containerd_types "github.com/containerd/containerd/api/types"
|
containerd_types "github.com/containerd/containerd/api/types"
|
||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/api/types/task"
|
||||||
@ -50,24 +54,87 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
runhcsShimVersion = "0.0.1"
|
runhcsShimVersion = "0.0.1"
|
||||||
|
safePipePrefix = `\\.\pipe\ProtectedPrefix\Administrators\`
|
||||||
|
|
||||||
|
errorConnectionAborted syscall.Errno = 1236
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
empty = &ptypes.Empty{}
|
empty = &ptypes.Empty{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func newRunhcs(bundle string) *runhcs.Runhcs {
|
func newRunhcs(debugLog string) *runhcs.Runhcs {
|
||||||
rhs := &runhcs.Runhcs{
|
rhs := &runhcs.Runhcs{
|
||||||
Debug: logrus.GetLevel() == logrus.DebugLevel,
|
Debug: debugLog != "",
|
||||||
LogFormat: runhcs.JSON,
|
LogFormat: runhcs.JSON,
|
||||||
Owner: "containerd-runhcs-shim-v1",
|
Owner: "containerd-runhcs-shim-v1",
|
||||||
}
|
}
|
||||||
if rhs.Debug {
|
if rhs.Debug {
|
||||||
rhs.Log = filepath.Join(bundle, "runhcs-debug.log")
|
rhs.Log = debugLog
|
||||||
}
|
}
|
||||||
return rhs
|
return rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// forwardRunhcsLogs copies logs from c and writes them to the ctx logger
|
||||||
|
// upstream.
|
||||||
|
func forwardRunhcsLogs(ctx context.Context, c net.Conn, fields logrus.Fields) {
|
||||||
|
defer c.Close()
|
||||||
|
j := json.NewDecoder(c)
|
||||||
|
|
||||||
|
for {
|
||||||
|
e := logrus.Entry{}
|
||||||
|
err := j.Decode(&e.Data)
|
||||||
|
if err == io.EOF || err == errorConnectionAborted {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// Likely the last message wasn't complete at closure. Just read all
|
||||||
|
// data and forward as error.
|
||||||
|
data, _ := ioutil.ReadAll(io.MultiReader(j.Buffered(), c))
|
||||||
|
if len(data) != 0 {
|
||||||
|
log.G(ctx).WithFields(fields).Error(string(data))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := e.Data[logrus.FieldKeyMsg]
|
||||||
|
delete(e.Data, logrus.FieldKeyMsg)
|
||||||
|
|
||||||
|
level, err := logrus.ParseLevel(e.Data[logrus.FieldKeyLevel].(string))
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithFields(fields).WithError(err).Debug("invalid log level")
|
||||||
|
level = logrus.DebugLevel
|
||||||
|
}
|
||||||
|
delete(e.Data, logrus.FieldKeyLevel)
|
||||||
|
|
||||||
|
// TODO: JTERRY75 maybe we need to make this configurable so we know
|
||||||
|
// that runhcs is using the same one we are deserializing.
|
||||||
|
ti, err := time.Parse(logrus.DefaultTimestampFormat, e.Data[logrus.FieldKeyTime].(string))
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithFields(fields).WithError(err).Debug("invalid time stamp format")
|
||||||
|
ti = time.Time{}
|
||||||
|
}
|
||||||
|
delete(e.Data, logrus.FieldKeyTime)
|
||||||
|
|
||||||
|
etr := log.G(ctx).WithFields(fields).WithFields(e.Data)
|
||||||
|
etr.Time = ti
|
||||||
|
switch level {
|
||||||
|
case logrus.PanicLevel:
|
||||||
|
etr.Panic(msg)
|
||||||
|
case logrus.FatalLevel:
|
||||||
|
etr.Fatal(msg)
|
||||||
|
case logrus.ErrorLevel:
|
||||||
|
etr.Error(msg)
|
||||||
|
case logrus.WarnLevel:
|
||||||
|
etr.Warn(msg)
|
||||||
|
case logrus.InfoLevel:
|
||||||
|
etr.Info(msg)
|
||||||
|
case logrus.DebugLevel:
|
||||||
|
etr.Debug(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// New returns a new runhcs shim service that can be used via GRPC
|
// New returns a new runhcs shim service that can be used via GRPC
|
||||||
func New(ctx context.Context, id string, publisher events.Publisher) (shim.Shim, error) {
|
func New(ctx context.Context, id string, publisher events.Publisher) (shim.Shim, error) {
|
||||||
return &service{
|
return &service{
|
||||||
@ -87,6 +154,10 @@ 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 string
|
||||||
|
debugListener net.Listener
|
||||||
|
|
||||||
id string
|
id string
|
||||||
processes map[string]*process
|
processes map[string]*process
|
||||||
|
|
||||||
@ -160,8 +231,13 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
|
|||||||
"-address", containerdAddress,
|
"-address", containerdAddress,
|
||||||
"-publish-binary", containerdBinary,
|
"-publish-binary", containerdBinary,
|
||||||
"-socket", socketAddress,
|
"-socket", socketAddress,
|
||||||
"-debug",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts, ok := ctx.Value(shim.OptsKey{}).(shim.Opts)
|
||||||
|
if ok && opts.Debug {
|
||||||
|
args = append(args, "-debug")
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command(self, args...)
|
cmd := exec.Command(self, args...)
|
||||||
cmd.Dir = cwd
|
cmd.Dir = cwd
|
||||||
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
|
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
|
||||||
@ -190,6 +266,8 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
|
|||||||
|
|
||||||
// State returns runtime state information for a process
|
// State returns runtime state information for a process
|
||||||
func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.StateResponse, error) {
|
func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.StateResponse, error) {
|
||||||
|
log.G(ctx).Debugf("State: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
@ -199,14 +277,26 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rhcs := newRunhcs(p.bundle)
|
var tstatus string
|
||||||
cs, err := rhcs.State(ctx, p.id)
|
|
||||||
if err != nil {
|
// This is a container
|
||||||
return nil, err
|
if p.cid == p.id {
|
||||||
|
rhcs := newRunhcs(s.debugLog)
|
||||||
|
cs, err := rhcs.State(ctx, p.id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tstatus = cs.Status
|
||||||
|
} else {
|
||||||
|
if p.started {
|
||||||
|
tstatus = "running"
|
||||||
|
} else {
|
||||||
|
tstatus = "created"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status := task.StatusUnknown
|
status := task.StatusUnknown
|
||||||
switch cs.Status {
|
switch tstatus {
|
||||||
case "created":
|
case "created":
|
||||||
status = task.StatusCreated
|
status = task.StatusCreated
|
||||||
case "running":
|
case "running":
|
||||||
@ -219,8 +309,8 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
|
|||||||
pe := p.stat()
|
pe := p.stat()
|
||||||
return &taskAPI.StateResponse{
|
return &taskAPI.StateResponse{
|
||||||
ID: p.id,
|
ID: p.id,
|
||||||
Bundle: cs.Bundle,
|
Bundle: p.bundle,
|
||||||
Pid: uint32(cs.InitProcessPid),
|
Pid: p.pid,
|
||||||
Status: status,
|
Status: status,
|
||||||
Stdin: p.stdin,
|
Stdin: p.stdin,
|
||||||
Stdout: p.stdout,
|
Stdout: p.stdout,
|
||||||
@ -301,7 +391,7 @@ func writeMountsToConfig(bundle string, mounts []*containerd_types.Mount) error
|
|||||||
|
|
||||||
// Create a new initial process and container with runhcs
|
// Create a new initial process and container with runhcs
|
||||||
func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*taskAPI.CreateTaskResponse, error) {
|
func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*taskAPI.CreateTaskResponse, error) {
|
||||||
log.G(ctx).Infof("Create: %s", r.ID)
|
log.G(ctx).Debugf("Create: %s", r.ID)
|
||||||
|
|
||||||
// Hold the lock for the entire duration to avoid duplicate process creation.
|
// Hold the lock for the entire duration to avoid duplicate process creation.
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
@ -346,16 +436,84 @@ 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 ok && opts.Debug {
|
||||||
|
if s.debugLog == "" {
|
||||||
|
logPath := safePipePrefix + fmt.Sprintf("runhcs-log-%s", r.ID)
|
||||||
|
l, err := winio.ListenPipe(logPath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.debugLog = logPath
|
||||||
|
s.debugListener = l
|
||||||
|
|
||||||
|
// Accept connections and forward all logs for each runhcs.exe
|
||||||
|
// invocation
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
c, err := s.debugListener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
if err == errorConnectionAborted {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
log.G(ctx).WithError(err).Debug("log accept failure")
|
||||||
|
// Logrus error locally?
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"log-source": "runhcs",
|
||||||
|
"task-id": r.ID,
|
||||||
|
}
|
||||||
|
go forwardRunhcsLogs(ctx, c, fields)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
ShimLog: path.Join(r.Bundle, "runhcs-shim.log"),
|
|
||||||
VMLog: path.Join(r.Bundle, "runhcs-vm-shim.log"),
|
|
||||||
}
|
}
|
||||||
|
rhcs := newRunhcs(s.debugLog)
|
||||||
|
if rhcs.Debug {
|
||||||
|
doForwardLogs := func(source, logPipeFmt string, opt *string) error {
|
||||||
|
pipeName := fmt.Sprintf(logPipeFmt, r.ID)
|
||||||
|
*opt = safePipePrefix + pipeName
|
||||||
|
l, err := winio.ListenPipe(*opt, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer l.Close()
|
||||||
|
c, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).
|
||||||
|
WithField("task-id", r.ID).
|
||||||
|
WithError(err).
|
||||||
|
Errorf("failed to accept %s", pipeName)
|
||||||
|
} else {
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"log-source": source,
|
||||||
|
"task-id": r.ID,
|
||||||
|
}
|
||||||
|
go forwardRunhcsLogs(ctx, c, fields)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
rhcs := newRunhcs(r.Bundle)
|
err = doForwardLogs("runhcs-shim", "runhcs-shim-log-%s", &copts.ShimLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = doForwardLogs("runhcs--vm-shim", "runhcs-vm-shim-log-%s", &copts.VMLog)
|
||||||
|
if err != nil {
|
||||||
|
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
|
||||||
@ -391,7 +549,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
|
|||||||
|
|
||||||
// Start a process
|
// Start a process
|
||||||
func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.StartResponse, error) {
|
func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.StartResponse, error) {
|
||||||
log.G(ctx).Infof("Start: %s: %s", r.ID, r.ExecID)
|
log.G(ctx).Debugf("Start: %s: %s", r.ID, r.ExecID)
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
||||||
@ -404,7 +562,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(p.bundle)
|
rhcs := newRunhcs(s.debugLog)
|
||||||
|
|
||||||
// This is a start/exec
|
// This is a start/exec
|
||||||
if r.ExecID != "" {
|
if r.ExecID != "" {
|
||||||
@ -414,10 +572,43 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
|
|||||||
eopts := &runhcs.ExecOpts{
|
eopts := &runhcs.ExecOpts{
|
||||||
IO: p.relay.io,
|
IO: p.relay.io,
|
||||||
PidFile: pidfilePath,
|
PidFile: pidfilePath,
|
||||||
ShimLog: path.Join(p.bundle, fmt.Sprintf("runhcs-%s-shim.log", execFmt)),
|
|
||||||
Detach: true,
|
Detach: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rhcs.Debug {
|
||||||
|
doForwardLogs := func(source, pipeName string, opt *string) error {
|
||||||
|
*opt = safePipePrefix + pipeName
|
||||||
|
l, err := winio.ListenPipe(*opt, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer l.Close()
|
||||||
|
c, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).
|
||||||
|
WithField("task-id", r.ID).
|
||||||
|
WithField("exec-id", r.ExecID).
|
||||||
|
WithError(err).
|
||||||
|
Errorf("failed to accept %s", pipeName)
|
||||||
|
} else {
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"log-source": source,
|
||||||
|
"task-id": r.ID,
|
||||||
|
"exec-id": r.ExecID,
|
||||||
|
}
|
||||||
|
go forwardRunhcsLogs(ctx, c, fields)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = doForwardLogs("runhcs-shim-exec", "runhcs-shim-log-"+execFmt, &eopts.ShimLog)
|
||||||
|
if err != nil {
|
||||||
|
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)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -473,7 +664,7 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
|
|||||||
|
|
||||||
// Delete the initial process and container
|
// Delete the initial process and container
|
||||||
func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAPI.DeleteResponse, error) {
|
func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAPI.DeleteResponse, error) {
|
||||||
log.G(ctx).Infof("Delete: %s: %s", r.ID, r.ExecID)
|
log.G(ctx).Debugf("Delete: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
@ -481,13 +672,15 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rhs := newRunhcs(p.bundle)
|
// This is a container
|
||||||
|
if p.cid == p.id {
|
||||||
dopts := &runhcs.DeleteOpts{
|
rhs := newRunhcs(s.debugLog)
|
||||||
Force: true,
|
dopts := &runhcs.DeleteOpts{
|
||||||
}
|
Force: true,
|
||||||
if err := rhs.Delete(ctx, p.id, dopts); err != nil {
|
}
|
||||||
return nil, errors.Wrapf(err, "failed to delete container: %s", p.id)
|
if err := rhs.Delete(ctx, p.id, dopts); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to delete container: %s", p.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@ -511,11 +704,15 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
|
|||||||
|
|
||||||
// Pids returns all pids inside the container
|
// Pids returns all pids inside the container
|
||||||
func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.PidsResponse, error) {
|
func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.PidsResponse, error) {
|
||||||
|
log.G(ctx).Debugf("Pids: %s", r.ID)
|
||||||
|
|
||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pause the container
|
// Pause the container
|
||||||
func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.Empty, error) {
|
func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.Empty, error) {
|
||||||
|
log.G(ctx).Debugf("Pause: %s", r.ID)
|
||||||
|
|
||||||
// TODO: Validate that 'id' is actually a valid parent container ID
|
// TODO: Validate that 'id' is actually a valid parent container ID
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
@ -523,7 +720,7 @@ func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.E
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rhcs := newRunhcs(p.bundle)
|
rhcs := newRunhcs(s.debugLog)
|
||||||
if err = rhcs.Pause(ctx, p.id); err != nil {
|
if err = rhcs.Pause(ctx, p.id); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -533,6 +730,8 @@ func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.E
|
|||||||
|
|
||||||
// Resume the container
|
// Resume the container
|
||||||
func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes.Empty, error) {
|
func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes.Empty, error) {
|
||||||
|
log.G(ctx).Debugf("Resume: %s", r.ID)
|
||||||
|
|
||||||
// TODO: Validate that 'id' is actually a valid parent container ID
|
// TODO: Validate that 'id' is actually a valid parent container ID
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
@ -540,7 +739,7 @@ func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rhcs := newRunhcs(p.bundle)
|
rhcs := newRunhcs(s.debugLog)
|
||||||
if err = rhcs.Resume(ctx, p.id); err != nil {
|
if err = rhcs.Resume(ctx, p.id); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -550,12 +749,14 @@ func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes
|
|||||||
|
|
||||||
// Checkpoint the container
|
// Checkpoint the container
|
||||||
func (s *service) Checkpoint(ctx context.Context, r *taskAPI.CheckpointTaskRequest) (*ptypes.Empty, error) {
|
func (s *service) Checkpoint(ctx context.Context, r *taskAPI.CheckpointTaskRequest) (*ptypes.Empty, error) {
|
||||||
|
log.G(ctx).Debugf("Checkpoint: %s", r.ID)
|
||||||
|
|
||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill a process with the provided signal
|
// Kill a process with the provided signal
|
||||||
func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Empty, error) {
|
func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Empty, error) {
|
||||||
log.G(ctx).Infof("Kill: %s: %s", r.ID, r.ExecID)
|
log.G(ctx).Debugf("Kill: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
@ -565,7 +766,7 @@ func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Emp
|
|||||||
|
|
||||||
// TODO: JTERRY75 runhcs needs r.Signal in string form
|
// 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(p.bundle)
|
rhcs := newRunhcs(s.debugLog)
|
||||||
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
|
||||||
@ -577,7 +778,7 @@ func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Emp
|
|||||||
|
|
||||||
// Exec an additional process inside the container
|
// Exec an additional process inside the container
|
||||||
func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*ptypes.Empty, error) {
|
func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*ptypes.Empty, error) {
|
||||||
log.G(ctx).Infof("Exec: %s: %s", r.ID, r.ExecID)
|
log.G(ctx).Debugf("Exec: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
@ -660,6 +861,8 @@ func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*pty
|
|||||||
|
|
||||||
// ResizePty of a process
|
// ResizePty of a process
|
||||||
func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*ptypes.Empty, error) {
|
func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*ptypes.Empty, error) {
|
||||||
|
log.G(ctx).Debugf("ResizePty: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
||||||
@ -670,7 +873,7 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
|
|||||||
opts := runhcs.ResizeTTYOpts{
|
opts := runhcs.ResizeTTYOpts{
|
||||||
Pid: &pid,
|
Pid: &pid,
|
||||||
}
|
}
|
||||||
rhcs := newRunhcs(p.bundle)
|
rhcs := newRunhcs(s.debugLog)
|
||||||
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
|
||||||
}
|
}
|
||||||
@ -680,6 +883,8 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
|
|||||||
|
|
||||||
// CloseIO of a process
|
// CloseIO of a process
|
||||||
func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptypes.Empty, error) {
|
func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptypes.Empty, error) {
|
||||||
|
log.G(ctx).Debugf("CloseIO: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
||||||
@ -691,11 +896,15 @@ func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptyp
|
|||||||
|
|
||||||
// Update a running container
|
// Update a running container
|
||||||
func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*ptypes.Empty, error) {
|
func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*ptypes.Empty, error) {
|
||||||
|
log.G(ctx).Debugf("Update: %s", r.ID)
|
||||||
|
|
||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for a process to exit
|
// Wait for a process to exit
|
||||||
func (s *service) Wait(ctx context.Context, r *taskAPI.WaitRequest) (*taskAPI.WaitResponse, error) {
|
func (s *service) Wait(ctx context.Context, r *taskAPI.WaitRequest) (*taskAPI.WaitResponse, error) {
|
||||||
|
log.G(ctx).Debugf("Wait: %s: %s", r.ID, r.ExecID)
|
||||||
|
|
||||||
var p *process
|
var p *process
|
||||||
var err error
|
var err error
|
||||||
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
if p, err = s.getProcess(r.ID, r.ExecID); err != nil {
|
||||||
@ -710,11 +919,15 @@ func (s *service) Wait(ctx context.Context, r *taskAPI.WaitRequest) (*taskAPI.Wa
|
|||||||
|
|
||||||
// Stats returns statistics about the running container
|
// Stats returns statistics about the running container
|
||||||
func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.StatsResponse, error) {
|
func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.StatsResponse, error) {
|
||||||
|
log.G(ctx).Debugf("Stats: %s", r.ID)
|
||||||
|
|
||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect returns the runhcs shim information
|
// Connect returns the runhcs shim information
|
||||||
func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*taskAPI.ConnectResponse, error) {
|
func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*taskAPI.ConnectResponse, error) {
|
||||||
|
log.G(ctx).Debugf("Connect: %s", r.ID)
|
||||||
|
|
||||||
return &taskAPI.ConnectResponse{
|
return &taskAPI.ConnectResponse{
|
||||||
ShimPid: uint32(os.Getpid()),
|
ShimPid: uint32(os.Getpid()),
|
||||||
TaskPid: s.processes[s.id].pid,
|
TaskPid: s.processes[s.id].pid,
|
||||||
@ -724,7 +937,11 @@ func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*task
|
|||||||
|
|
||||||
// Shutdown stops this instance of the runhcs shim
|
// Shutdown stops this instance of the runhcs shim
|
||||||
func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*ptypes.Empty, error) {
|
func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*ptypes.Empty, error) {
|
||||||
log.G(ctx).Infof("Shutdown: %s", r.ID)
|
log.G(ctx).Debugf("Shutdown: %s", r.ID)
|
||||||
|
|
||||||
|
if s.debugListener != nil {
|
||||||
|
s.debugListener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
return empty, nil
|
return empty, nil
|
||||||
|
@ -53,6 +53,14 @@ type Shim interface {
|
|||||||
StartShim(ctx context.Context, id, containerdBinary, containerdAddress string) (string, error)
|
StartShim(ctx context.Context, id, containerdBinary, containerdAddress string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OptsKey is the context key for the Opts value.
|
||||||
|
type OptsKey struct{}
|
||||||
|
|
||||||
|
// Opts are context options associated with the shim invocation.
|
||||||
|
type Opts struct {
|
||||||
|
Debug bool
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
debugFlag bool
|
debugFlag bool
|
||||||
idFlag string
|
idFlag string
|
||||||
@ -133,6 +141,7 @@ func run(id string, initFunc Init) error {
|
|||||||
return fmt.Errorf("shim namespace cannot be empty")
|
return fmt.Errorf("shim namespace cannot be empty")
|
||||||
}
|
}
|
||||||
ctx := namespaces.WithNamespace(context.Background(), namespaceFlag)
|
ctx := namespaces.WithNamespace(context.Background(), namespaceFlag)
|
||||||
|
ctx = context.WithValue(ctx, OptsKey{}, Opts{Debug: debugFlag})
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id))
|
ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id))
|
||||||
|
|
||||||
service, err := initFunc(ctx, idFlag, publisher)
|
service, err := initFunc(ctx, idFlag, publisher)
|
||||||
|
39
runtime/v2/shim/shim_test.go
Normal file
39
runtime/v2/shim/shim_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
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 shim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShimOptWithValue(t *testing.T) {
|
||||||
|
ctx := context.TODO()
|
||||||
|
ctx = context.WithValue(ctx, OptsKey{}, Opts{Debug: true})
|
||||||
|
|
||||||
|
o := ctx.Value(OptsKey{})
|
||||||
|
if o == nil {
|
||||||
|
t.Fatal("opts nil")
|
||||||
|
}
|
||||||
|
op, ok := o.(Opts)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("opts not of type Opts")
|
||||||
|
}
|
||||||
|
if !op.Debug {
|
||||||
|
t.Fatal("opts.Debug should be true")
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
|||||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
||||||
github.com/Microsoft/go-winio v0.4.10
|
github.com/Microsoft/go-winio v0.4.10
|
||||||
github.com/Microsoft/hcsshim v0.7.4
|
github.com/Microsoft/hcsshim v0.7.6
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
|
github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
|
||||||
|
17
vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs.go
generated
vendored
17
vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs.go
generated
vendored
@ -6,6 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/go-runc"
|
"github.com/containerd/go-runc"
|
||||||
@ -21,7 +23,8 @@ const (
|
|||||||
// JSON is the JSON formatted log output.
|
// JSON is the JSON formatted log output.
|
||||||
JSON Format = "json"
|
JSON Format = "json"
|
||||||
|
|
||||||
command = "runhcs"
|
command = "runhcs"
|
||||||
|
safePipePrefix = `\\.\pipe\ProtectedPrefix\Administrators\`
|
||||||
)
|
)
|
||||||
|
|
||||||
var bytesBufferPool = sync.Pool{
|
var bytesBufferPool = sync.Pool{
|
||||||
@ -43,7 +46,7 @@ func putBuf(b *bytes.Buffer) {
|
|||||||
type Runhcs struct {
|
type Runhcs struct {
|
||||||
// Debug enables debug output for logging.
|
// Debug enables debug output for logging.
|
||||||
Debug bool
|
Debug bool
|
||||||
// Log sets the log file path where internal debug information is written.
|
// Log sets the log file path or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-log) where internal debug information is written.
|
||||||
Log string
|
Log string
|
||||||
// LogFormat sets the format used by logs.
|
// LogFormat sets the format used by logs.
|
||||||
LogFormat Format
|
LogFormat Format
|
||||||
@ -59,8 +62,14 @@ func (r *Runhcs) args() []string {
|
|||||||
out = append(out, "--debug")
|
out = append(out, "--debug")
|
||||||
}
|
}
|
||||||
if r.Log != "" {
|
if r.Log != "" {
|
||||||
// TODO: JTERRY75 - Should we do abs here?
|
if strings.HasPrefix(r.Log, safePipePrefix) {
|
||||||
out = append(out, "--log", r.Log)
|
out = append(out, "--log", r.Log)
|
||||||
|
} else {
|
||||||
|
abs, err := filepath.Abs(r.Log)
|
||||||
|
if err == nil {
|
||||||
|
out = append(out, "--log", abs)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if r.LogFormat != none {
|
if r.LogFormat != none {
|
||||||
out = append(out, "--log-format", string(r.LogFormat))
|
out = append(out, "--log-format", string(r.LogFormat))
|
||||||
|
29
vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_create.go
generated
vendored
29
vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_create.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
)
|
)
|
||||||
@ -13,9 +14,9 @@ type CreateOpts struct {
|
|||||||
runc.IO
|
runc.IO
|
||||||
// PidFile is the path to the file to write the process id to.
|
// PidFile is the path to the file to write the process id to.
|
||||||
PidFile string
|
PidFile string
|
||||||
// ShimLog is the path to the log file for the launched shim process.
|
// ShimLog is the path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-shim-log) for the launched shim process.
|
||||||
ShimLog string
|
ShimLog string
|
||||||
// VMLog is the path to the log file for the launched VM shim process.
|
// VMLog is the path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-vm-log) for the launched VM shim process.
|
||||||
VMLog string
|
VMLog string
|
||||||
// VMConsole is the path to the pipe for the VM's console (e.g. \\.\pipe\debugpipe)
|
// VMConsole is the path to the pipe for the VM's console (e.g. \\.\pipe\debugpipe)
|
||||||
VMConsole string
|
VMConsole string
|
||||||
@ -31,18 +32,26 @@ func (opt *CreateOpts) args() ([]string, error) {
|
|||||||
out = append(out, "--pid-file", abs)
|
out = append(out, "--pid-file", abs)
|
||||||
}
|
}
|
||||||
if opt.ShimLog != "" {
|
if opt.ShimLog != "" {
|
||||||
abs, err := filepath.Abs(opt.ShimLog)
|
if strings.HasPrefix(opt.ShimLog, safePipePrefix) {
|
||||||
if err != nil {
|
out = append(out, "--shim-log", opt.ShimLog)
|
||||||
return nil, err
|
} else {
|
||||||
|
abs, err := filepath.Abs(opt.ShimLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, "--shim-log", abs)
|
||||||
}
|
}
|
||||||
out = append(out, "--shim-log", abs)
|
|
||||||
}
|
}
|
||||||
if opt.VMLog != "" {
|
if opt.VMLog != "" {
|
||||||
abs, err := filepath.Abs(opt.VMLog)
|
if strings.HasPrefix(opt.VMLog, safePipePrefix) {
|
||||||
if err != nil {
|
out = append(out, "--vm-log", opt.VMLog)
|
||||||
return nil, err
|
} else {
|
||||||
|
abs, err := filepath.Abs(opt.VMLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, "--vm-log", abs)
|
||||||
}
|
}
|
||||||
out = append(out, "--vm-log", abs)
|
|
||||||
}
|
}
|
||||||
if opt.VMConsole != "" {
|
if opt.VMConsole != "" {
|
||||||
out = append(out, "--vm-console", opt.VMConsole)
|
out = append(out, "--vm-console", opt.VMConsole)
|
||||||
|
15
vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_exec.go
generated
vendored
15
vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_exec.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/go-runc"
|
"github.com/containerd/go-runc"
|
||||||
)
|
)
|
||||||
@ -15,7 +16,7 @@ type ExecOpts struct {
|
|||||||
Detach bool
|
Detach bool
|
||||||
// PidFile is the path to the file to write the process id to.
|
// PidFile is the path to the file to write the process id to.
|
||||||
PidFile string
|
PidFile string
|
||||||
// ShimLog is the path to the log file for the launched shim process.
|
// ShimLog is the path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-<exec-id>-log) for the launched shim process.
|
||||||
ShimLog string
|
ShimLog string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,11 +33,15 @@ func (opt *ExecOpts) args() ([]string, error) {
|
|||||||
out = append(out, "--pid-file", abs)
|
out = append(out, "--pid-file", abs)
|
||||||
}
|
}
|
||||||
if opt.ShimLog != "" {
|
if opt.ShimLog != "" {
|
||||||
abs, err := filepath.Abs(opt.ShimLog)
|
if strings.HasPrefix(opt.ShimLog, safePipePrefix) {
|
||||||
if err != nil {
|
out = append(out, "--shim-log", opt.ShimLog)
|
||||||
return nil, err
|
} else {
|
||||||
|
abs, err := filepath.Abs(opt.ShimLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, "--shim-log", abs)
|
||||||
}
|
}
|
||||||
out = append(out, "--shim-log", abs)
|
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
generated
vendored
@ -6,6 +6,8 @@ import (
|
|||||||
|
|
||||||
// HNSEndpoint represents a network endpoint in HNS
|
// HNSEndpoint represents a network endpoint in HNS
|
||||||
type HNSEndpoint = hns.HNSEndpoint
|
type HNSEndpoint = hns.HNSEndpoint
|
||||||
|
// Namespace represents a Compartment.
|
||||||
|
type Namespace = hns.Namespace
|
||||||
|
|
||||||
//SystemType represents the type of the system on which actions are done
|
//SystemType represents the type of the system on which actions are done
|
||||||
type SystemType string
|
type SystemType string
|
||||||
|
Loading…
Reference in New Issue
Block a user