@@ -10,6 +10,7 @@ import (
1010 "time"
1111
1212 "github.com/Microsoft/hcsshim"
13+ "github.com/Sirupsen/logrus"
1314 "github.com/boltdb/bolt"
1415 eventsapi "github.com/containerd/containerd/api/services/events/v1"
1516 containerdtypes "github.com/containerd/containerd/api/types"
@@ -122,27 +123,7 @@ func (r *windowsRuntime) Create(ctx context.Context, id string, opts runtime.Cre
122123 createOpts .TerminateDuration = defaultTerminateDuration
123124 }
124125
125- t , err := r .newTask (ctx , r .emitter , namespace , id , spec , opts .IO , createOpts )
126- if err != nil {
127- return nil , err
128- }
129-
130- r .tasks .Add (ctx , t )
131-
132- r .emitter .Post (events .WithTopic (ctx , "/tasks/create" ), & eventsapi.TaskCreate {
133- ContainerID : id ,
134- IO : & eventsapi.TaskIO {
135- Stdin : opts .IO .Stdin ,
136- Stdout : opts .IO .Stdout ,
137- Stderr : opts .IO .Stderr ,
138- Terminal : opts .IO .Terminal ,
139- },
140- Pid : t .pid ,
141- Rootfs : t .rootfs ,
142- // TODO: what should be in Bundle for windows?
143- })
144-
145- return t , nil
126+ return r .newTask (ctx , namespace , id , spec , opts .IO , createOpts )
146127}
147128
148129func (r * windowsRuntime ) Get (ctx context.Context , id string ) (runtime.Task , error ) {
@@ -161,12 +142,29 @@ func (r *windowsRuntime) Delete(ctx context.Context, t runtime.Task) (*runtime.E
161142
162143 // TODO(mlaventure): stop monitor on this task
163144
164- state , _ := wt .State (ctx )
145+ var (
146+ err error
147+ needServicing bool
148+ state , _ = wt .State (ctx )
149+ )
165150 switch state .Status {
166- case runtime .StoppedStatus , runtime .CreatedStatus :
151+ case runtime .StoppedStatus :
152+ // Only try to service a container if it was started and it's not a
153+ // servicing task itself
154+ if wt .servicing == false {
155+ needServicing , err = wt .hcsContainer .HasPendingUpdates ()
156+ if err != nil {
157+ needServicing = false
158+ log .G (ctx ).WithError (err ).
159+ WithFields (logrus.Fields {"id" : wt .id , "pid" : wt .pid }).
160+ Error ("failed to check if container needs servicing" )
161+ }
162+ }
163+ fallthrough
164+ case runtime .CreatedStatus :
167165 // if it's stopped or in created state, we need to shutdown the
168166 // container before removing it
169- if err : = wt .stop (ctx ); err != nil {
167+ if err = wt .stop (ctx ); err != nil {
170168 return nil , err
171169 }
172170 default :
@@ -203,11 +201,18 @@ func (r *windowsRuntime) Delete(ctx context.Context, t runtime.Task) (*runtime.E
203201 ExitedAt : rtExit .Timestamp ,
204202 })
205203
204+ if needServicing {
205+ ns , _ := namespaces .Namespace (ctx )
206+ serviceCtx := log .WithLogger (context .Background (), log .GetLogger (ctx ))
207+ serviceCtx = namespaces .WithNamespace (serviceCtx , ns )
208+ r .serviceTask (serviceCtx , ns , wt .id + "_servicing" , wt .spec )
209+ }
210+
206211 // We were never started, return failure
207212 return rtExit , nil
208213}
209214
210- func (r * windowsRuntime ) newTask (ctx context.Context , emitter * events. Emitter , namespace , id string , spec * specs.Spec , io runtime.IO , createOpts * hcsshimopts.CreateOptions ) (* task , error ) {
215+ func (r * windowsRuntime ) newTask (ctx context.Context , namespace , id string , spec * specs.Spec , io runtime.IO , createOpts * hcsshimopts.CreateOptions ) (* task , error ) {
211216 var (
212217 err error
213218 pset * pipeSet
@@ -281,29 +286,45 @@ func (r *windowsRuntime) newTask(ctx context.Context, emitter *events.Emitter, n
281286 return nil , errors .Wrap (err , "hcsshim failed to spawn task" )
282287 }
283288
284- var rootfs []* containerdtypes.Mount
285- for _ , l := range append ([]string {conf .LayerFolderPath }, spec .Windows .LayerFolders ... ) {
286- rootfs = append (rootfs , & containerdtypes.Mount {
287- Type : "windows-layer" ,
288- Source : l ,
289- })
290- }
291-
292- return & task {
289+ t := & task {
293290 id : id ,
294291 namespace : namespace ,
295292 pid : pid ,
296293 io : pset ,
297294 status : runtime .CreatedStatus ,
298- initSpec : spec . Process ,
295+ spec : spec ,
299296 processes : make (map [string ]* process ),
300297 hyperV : spec .Windows .HyperV != nil ,
301- rootfs : rootfs ,
302- emitter : emitter ,
298+ emitter : r . emitter ,
299+ rwLayer : conf . LayerFolderPath ,
303300 pidPool : r .pidPool ,
304301 hcsContainer : ctr ,
305302 terminateDuration : createOpts .TerminateDuration ,
306- }, nil
303+ }
304+ r .tasks .Add (ctx , t )
305+
306+ var rootfs []* containerdtypes.Mount
307+ for _ , l := range append ([]string {t .rwLayer }, spec .Windows .LayerFolders ... ) {
308+ rootfs = append (rootfs , & containerdtypes.Mount {
309+ Type : "windows-layer" ,
310+ Source : l ,
311+ })
312+ }
313+
314+ r .emitter .Post (events .WithTopic (ctx , "/tasks/create" ), & eventsapi.TaskCreate {
315+ ContainerID : id ,
316+ IO : & eventsapi.TaskIO {
317+ Stdin : io .Stdin ,
318+ Stdout : io .Stdout ,
319+ Stderr : io .Stderr ,
320+ Terminal : io .Terminal ,
321+ },
322+ Pid : t .pid ,
323+ Rootfs : rootfs ,
324+ // TODO: what should be in Bundle for windows?
325+ })
326+
327+ return t , nil
307328}
308329
309330func (r * windowsRuntime ) cleanup (ctx context.Context ) {
@@ -354,3 +375,36 @@ func (r *windowsRuntime) cleanup(ctx context.Context) {
354375
355376 }
356377}
378+
379+ func (r * windowsRuntime ) serviceTask (ctx context.Context , namespace , id string , spec * specs.Spec ) {
380+ var (
381+ err error
382+ t * task
383+ io runtime.IO
384+ createOpts = & hcsshimopts.CreateOptions {
385+ TerminateDuration : defaultTerminateDuration ,
386+ }
387+ )
388+
389+ t , err = r .newTask (ctx , namespace , id , spec , io , createOpts )
390+ if err != nil {
391+ log .G (ctx ).WithError (err ).WithField ("id" , id ).
392+ Warn ("failed to created servicing task" )
393+ return
394+ }
395+ t .servicing = true
396+
397+ err = t .Start (ctx )
398+ switch err {
399+ case nil :
400+ <- t .getProcess (id ).exitCh
401+ default :
402+ log .G (ctx ).WithError (err ).WithField ("id" , id ).
403+ Warn ("failed to start servicing task" )
404+ }
405+
406+ if _ , err = r .Delete (ctx , t ); err != nil {
407+ log .G (ctx ).WithError (err ).WithField ("id" , id ).
408+ Warn ("failed to stop servicing task" )
409+ }
410+ }
0 commit comments