Skip to content

Commit d40cc95

Browse files
jterry75thaJeztah
authored andcommitted
Implement io.containerd.runhcs.v1 shim log opts
Signed-off-by: Justin Terry (VM) <juterry@microsoft.com> (cherry picked from commit a33ad40) Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 30ca1c5 commit d40cc95

File tree

2 files changed

+141
-116
lines changed

2 files changed

+141
-116
lines changed

runtime/v2/runhcs/service.go

Lines changed: 140 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"os"
2929
"os/exec"
3030
"path"
31+
"path/filepath"
3132
"strconv"
3233
"strings"
3334
"sync"
@@ -43,9 +44,11 @@ import (
4344
"github.com/containerd/containerd/log"
4445
"github.com/containerd/containerd/mount"
4546
"github.com/containerd/containerd/namespaces"
47+
"github.com/containerd/containerd/runtime/v2/runhcs/options"
4648
"github.com/containerd/containerd/runtime/v2/shim"
4749
taskAPI "github.com/containerd/containerd/runtime/v2/task"
4850
"github.com/containerd/go-runc"
51+
"github.com/containerd/typeurl"
4952
ptypes "github.com/gogo/protobuf/types"
5053
oci "github.com/opencontainers/runtime-spec/specs-go"
5154
"github.com/pkg/errors"
@@ -63,18 +66,6 @@ var (
6366
empty = &ptypes.Empty{}
6467
)
6568

66-
func newRunhcs(debugLog string) *runhcs.Runhcs {
67-
rhs := &runhcs.Runhcs{
68-
Debug: debugLog != "",
69-
LogFormat: runhcs.JSON,
70-
Owner: "containerd-runhcs-shim-v1",
71-
}
72-
if rhs.Debug {
73-
rhs.Log = debugLog
74-
}
75-
return rhs
76-
}
77-
7869
// forwardRunhcsLogs copies logs from c and writes them to the ctx logger
7970
// upstream.
8071
func forwardRunhcsLogs(ctx context.Context, c net.Conn, fields logrus.Fields) {
@@ -154,16 +145,31 @@ type service struct {
154145

155146
context context.Context
156147

157-
// debugLog if not "" indicates the log pipe path for runhcs.exe to write its logs to.
158-
debugLog string
148+
// debugLog if not "" indicates the log file or pipe path for runhcs.exe to
149+
// write its logs to.
150+
debugLog string
151+
// if `shimOpts.DebugType == options.Opitons_NPIPE` will hold the listener
152+
// for the runhcs.exe to connect to for sending logs.
159153
debugListener net.Listener
160154

155+
shimOpts options.Options
156+
161157
id string
162158
processes map[string]*process
163159

164160
publisher events.Publisher
165161
}
166162

163+
func (s *service) newRunhcs() *runhcs.Runhcs {
164+
return &runhcs.Runhcs{
165+
Debug: s.shimOpts.Debug,
166+
Log: s.debugLog,
167+
LogFormat: runhcs.JSON,
168+
Owner: "containerd-runhcs-shim-v1",
169+
Root: s.shimOpts.RegistryRoot,
170+
}
171+
}
172+
167173
// getProcess attempts to get a process by id.
168174
// The caller MUST NOT have locked s.mu previous to calling this function.
169175
func (s *service) getProcess(id, execID string) (*process, error) {
@@ -196,7 +202,7 @@ func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error)
196202
return nil, err
197203
}
198204
// Forcibly shut down any container in this bundle
199-
rhcs := newRunhcs("")
205+
rhcs := s.newRunhcs()
200206
dopts := &runhcs.DeleteOpts{
201207
Force: true,
202208
}
@@ -290,7 +296,7 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
290296

291297
// This is a container
292298
if p.cid == p.id {
293-
rhcs := newRunhcs(s.debugLog)
299+
rhcs := s.newRunhcs()
294300
cs, err := rhcs.State(ctx, p.id)
295301
if err != nil {
296302
return nil, err
@@ -406,6 +412,19 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
406412
s.mu.Lock()
407413
defer s.mu.Unlock()
408414

415+
_, err := namespaces.NamespaceRequired(ctx)
416+
if err != nil {
417+
return nil, errors.Wrap(err, "create namespace")
418+
}
419+
420+
if r.Options != nil {
421+
v, err := typeurl.UnmarshalAny(r.Options)
422+
if err != nil {
423+
return nil, err
424+
}
425+
s.shimOpts = *v.(*options.Options)
426+
}
427+
409428
if p := s.processes[r.ID]; p != nil {
410429
return nil, errdefs.ToGRPCf(errdefs.ErrAlreadyExists, "process %s already exists", r.ID)
411430
}
@@ -445,38 +464,41 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
445464
pr.close()
446465
}
447466
}()
448-
// TODO: Parse the real RunHcs Opts r.Options
449-
opts, ok := ctx.Value(shim.OptsKey{}).(shim.Opts)
450-
if ok && opts.Debug {
467+
468+
if s.shimOpts.Debug {
451469
if s.debugLog == "" {
452-
logPath := safePipePrefix + fmt.Sprintf("runhcs-log-%s", r.ID)
453-
l, err := winio.ListenPipe(logPath, nil)
454-
if err != nil {
455-
return nil, err
456-
}
457-
s.debugLog = logPath
458-
s.debugListener = l
459-
460-
// Accept connections and forward all logs for each runhcs.exe
461-
// invocation
462-
go func() {
463-
for {
464-
c, err := s.debugListener.Accept()
465-
if err != nil {
466-
if err == errorConnectionAborted {
467-
break
470+
if s.shimOpts.DebugType == options.Options_FILE {
471+
s.debugLog = filepath.Join(r.Bundle, fmt.Sprintf("runhcs-%s.log", r.ID))
472+
} else {
473+
logPath := safePipePrefix + fmt.Sprintf("runhcs-log-%s", r.ID)
474+
l, err := winio.ListenPipe(logPath, nil)
475+
if err != nil {
476+
return nil, err
477+
}
478+
s.debugLog = logPath
479+
s.debugListener = l
480+
481+
// Accept connections and forward all logs for each runhcs.exe
482+
// invocation
483+
go func() {
484+
for {
485+
c, err := s.debugListener.Accept()
486+
if err != nil {
487+
if err == winio.ErrPipeListenerClosed {
488+
break
489+
}
490+
log.G(ctx).WithError(err).Debug("log accept failure")
491+
// Logrus error locally?
492+
continue
468493
}
469-
log.G(ctx).WithError(err).Debug("log accept failure")
470-
// Logrus error locally?
471-
continue
472-
}
473-
fields := map[string]interface{}{
474-
"log-source": "runhcs",
475-
"task-id": r.ID,
494+
fields := map[string]interface{}{
495+
"log-source": "runhcs",
496+
"task-id": r.ID,
497+
}
498+
go forwardRunhcsLogs(ctx, c, fields)
476499
}
477-
go forwardRunhcsLogs(ctx, c, fields)
478-
}
479-
}()
500+
}()
501+
}
480502
}
481503
}
482504

@@ -485,42 +507,47 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
485507
IO: io,
486508
PidFile: pidfilePath,
487509
}
488-
rhcs := newRunhcs(s.debugLog)
510+
rhcs := s.newRunhcs()
489511
if rhcs.Debug {
490-
doForwardLogs := func(source, logPipeFmt string, opt *string) error {
491-
pipeName := fmt.Sprintf(logPipeFmt, r.ID)
492-
*opt = safePipePrefix + pipeName
493-
l, err := winio.ListenPipe(*opt, nil)
494-
if err != nil {
495-
return err
496-
}
497-
go func() {
498-
defer l.Close()
499-
c, err := l.Accept()
512+
if s.shimOpts.DebugType == options.Options_FILE {
513+
copts.ShimLog = filepath.Join(r.Bundle, fmt.Sprintf("runhcs-shim-%s.log", r.ID))
514+
copts.VMLog = filepath.Join(r.Bundle, fmt.Sprintf("runhcs-vmshim-%s.log", r.ID))
515+
} else {
516+
doForwardLogs := func(source, logPipeFmt string, opt *string) error {
517+
pipeName := fmt.Sprintf(logPipeFmt, r.ID)
518+
*opt = safePipePrefix + pipeName
519+
l, err := winio.ListenPipe(*opt, nil)
500520
if err != nil {
501-
log.G(ctx).
502-
WithField("task-id", r.ID).
503-
WithError(err).
504-
Errorf("failed to accept %s", pipeName)
505-
} else {
506-
fields := map[string]interface{}{
507-
"log-source": source,
508-
"task-id": r.ID,
509-
}
510-
go forwardRunhcsLogs(ctx, c, fields)
521+
return err
511522
}
512-
}()
513-
return nil
514-
}
523+
go func() {
524+
defer l.Close()
525+
c, err := l.Accept()
526+
if err != nil {
527+
log.G(ctx).
528+
WithField("task-id", r.ID).
529+
WithError(err).
530+
Errorf("failed to accept %s", pipeName)
531+
} else {
532+
fields := map[string]interface{}{
533+
"log-source": source,
534+
"task-id": r.ID,
535+
}
536+
go forwardRunhcsLogs(ctx, c, fields)
537+
}
538+
}()
539+
return nil
540+
}
515541

516-
err = doForwardLogs("runhcs-shim", "runhcs-shim-log-%s", &copts.ShimLog)
517-
if err != nil {
518-
return nil, err
519-
}
542+
err = doForwardLogs("runhcs-shim", "runhcs-shim-log-%s", &copts.ShimLog)
543+
if err != nil {
544+
return nil, err
545+
}
520546

521-
err = doForwardLogs("runhcs--vm-shim", "runhcs-vm-shim-log-%s", &copts.VMLog)
522-
if err != nil {
523-
return nil, err
547+
err = doForwardLogs("runhcs--vm-shim", "runhcs-vm-shim-log-%s", &copts.VMLog)
548+
if err != nil {
549+
return nil, err
550+
}
524551
}
525552
}
526553
err = rhcs.Create(ctx, r.ID, r.Bundle, copts)
@@ -571,7 +598,7 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
571598
return nil, errors.New("cannot start already started container or process")
572599
}
573600

574-
rhcs := newRunhcs(s.debugLog)
601+
rhcs := s.newRunhcs()
575602

576603
// This is a start/exec
577604
if r.ExecID != "" {
@@ -585,36 +612,40 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
585612
}
586613

587614
if rhcs.Debug {
588-
doForwardLogs := func(source, pipeName string, opt *string) error {
589-
*opt = safePipePrefix + pipeName
590-
l, err := winio.ListenPipe(*opt, nil)
591-
if err != nil {
592-
return err
593-
}
594-
go func() {
595-
defer l.Close()
596-
c, err := l.Accept()
615+
if s.shimOpts.DebugType == options.Options_FILE {
616+
eopts.ShimLog = filepath.Join(p.bundle, fmt.Sprintf("runhcs-shim-%s.log", execFmt))
617+
} else {
618+
doForwardLogs := func(source, pipeName string, opt *string) error {
619+
*opt = safePipePrefix + pipeName
620+
l, err := winio.ListenPipe(*opt, nil)
597621
if err != nil {
598-
log.G(ctx).
599-
WithField("task-id", r.ID).
600-
WithField("exec-id", r.ExecID).
601-
WithError(err).
602-
Errorf("failed to accept %s", pipeName)
603-
} else {
604-
fields := map[string]interface{}{
605-
"log-source": source,
606-
"task-id": r.ID,
607-
"exec-id": r.ExecID,
608-
}
609-
go forwardRunhcsLogs(ctx, c, fields)
622+
return err
610623
}
611-
}()
612-
return nil
613-
}
624+
go func() {
625+
defer l.Close()
626+
c, err := l.Accept()
627+
if err != nil {
628+
log.G(ctx).
629+
WithField("task-id", r.ID).
630+
WithField("exec-id", r.ExecID).
631+
WithError(err).
632+
Errorf("failed to accept %s", pipeName)
633+
} else {
634+
fields := map[string]interface{}{
635+
"log-source": source,
636+
"task-id": r.ID,
637+
"exec-id": r.ExecID,
638+
}
639+
go forwardRunhcsLogs(ctx, c, fields)
640+
}
641+
}()
642+
return nil
643+
}
614644

615-
err = doForwardLogs("runhcs-shim-exec", "runhcs-shim-log-"+execFmt, &eopts.ShimLog)
616-
if err != nil {
617-
return nil, err
645+
err = doForwardLogs("runhcs-shim-exec", "runhcs-shim-log-"+execFmt, &eopts.ShimLog)
646+
if err != nil {
647+
return nil, err
648+
}
618649
}
619650
}
620651

@@ -683,7 +714,7 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
683714

684715
// This is a container
685716
if p.cid == p.id {
686-
rhs := newRunhcs(s.debugLog)
717+
rhs := s.newRunhcs()
687718
dopts := &runhcs.DeleteOpts{
688719
Force: true,
689720
}
@@ -729,7 +760,7 @@ func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.E
729760
return nil, err
730761
}
731762

732-
rhcs := newRunhcs(s.debugLog)
763+
rhcs := s.newRunhcs()
733764
if err = rhcs.Pause(ctx, p.id); err != nil {
734765
return nil, err
735766
}
@@ -748,7 +779,7 @@ func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes
748779
return nil, err
749780
}
750781

751-
rhcs := newRunhcs(s.debugLog)
782+
rhcs := s.newRunhcs()
752783
if err = rhcs.Resume(ctx, p.id); err != nil {
753784
return nil, err
754785
}
@@ -773,9 +804,8 @@ func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Emp
773804
return nil, err
774805
}
775806

776-
// TODO: JTERRY75 runhcs needs r.Signal in string form
777807
// TODO: JTERRY75 runhcs support for r.All?
778-
rhcs := newRunhcs(s.debugLog)
808+
rhcs := s.newRunhcs()
779809
if err = rhcs.Kill(ctx, p.id, strconv.FormatUint(uint64(r.Signal), 10)); err != nil {
780810
if !strings.Contains(err.Error(), "container is stopped") {
781811
return nil, err
@@ -882,7 +912,7 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
882912
opts := runhcs.ResizeTTYOpts{
883913
Pid: &pid,
884914
}
885-
rhcs := newRunhcs(s.debugLog)
915+
rhcs := s.newRunhcs()
886916
if err = rhcs.ResizeTTY(ctx, p.cid, uint16(r.Width), uint16(r.Height), &opts); err != nil {
887917
return nil, err
888918
}

0 commit comments

Comments
 (0)