@@ -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"
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.
8071func 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.
169175func (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