@@ -17,8 +17,11 @@ package containerdshim
1717import (
1818 "context"
1919 "errors"
20+ "fmt"
21+ "path/filepath"
2022
2123 taskAPI "github.com/containerd/containerd/api/runtime/task/v2"
24+ "github.com/containerd/containerd/namespaces"
2225 "github.com/containerd/log"
2326 "github.com/containerd/ttrpc"
2427 containerdShim "github.com/urunc-dev/urunc/pkg/containerd-shim/containerd"
@@ -31,6 +34,8 @@ type taskService struct {
3134 taskAPI.TaskService
3235
3336 containerdAddress string
37+ // Used on Delete, where cwd may no longer be the bundle.
38+ stateRoot string
3439}
3540
3641func (s * taskService ) Create (ctx context.Context , r * taskAPI.CreateTaskRequest ) (* taskAPI.CreateTaskResponse , error ) {
@@ -53,9 +58,8 @@ func (s *taskService) Create(ctx context.Context, r *taskAPI.CreateTaskRequest)
5358 return resp , err
5459 }
5560
56- // ChooseRootfs after inner task Create so bundle rootfs is mounted;
57- // params are persisted in bundle config.json for runtime Exec.
58- if err := chooseGuestRootfs (r ); err != nil {
61+ rootfsChoice , err := chooseGuestRootfs (r )
62+ if err != nil {
5963 if errors .Is (err , errGuestRootfsChoiceSkipped ) {
6064 log .G (ctx ).WithError (err ).Debug ("urunc(shim): guest rootfs choice skipped" )
6165 return resp , nil
@@ -64,14 +68,90 @@ func (s *taskService) Create(ctx context.Context, r *taskAPI.CreateTaskRequest)
6468 return nil , err
6569 }
6670
71+ log .G (ctx ).WithFields (map [string ]any {
72+ "rootfs_type" : rootfsChoice .Type ,
73+ "rootfs_path" : rootfsChoice .Path ,
74+ "mon_rootfs" : rootfsChoice .MonRootfs ,
75+ }).Debug ("urunc(shim): guest rootfs chosen" )
76+
77+ if session != nil {
78+ rootfsViewAccessor := containerdShim .NewRootfsViewAccessor (session )
79+ if rootfsViewAccessor .ShouldPrepare (rootfsChoice ) {
80+ if err := rootfsViewAccessor .Prepare (ctx , r .Bundle ); err != nil {
81+ log .G (ctx ).WithError (err ).Warn ("urunc(shim): failed to prepare rootfs view; falling back to legacy boot artifact extraction" )
82+ } else {
83+ log .G (ctx ).Debug ("urunc(shim): rootfs view prepared" )
84+ }
85+ } else {
86+ log .G (ctx ).WithField ("rootfs_type" , rootfsChoice .Type ).Debug ("urunc(shim): rootfs view prepare skipped" )
87+ }
88+ }
89+
6790 return resp , nil
6891}
6992
7093func (s * taskService ) Delete (ctx context.Context , r * taskAPI.DeleteRequest ) (* taskAPI.DeleteResponse , error ) {
71- return s .TaskService .Delete (ctx , r )
94+ shouldCleanup := false
95+ snapshotter := ""
96+ var loadErr error
97+
98+ if r .ExecID == "" {
99+ bundle , err := s .bundlePathFor (ctx , r .ID )
100+ if err != nil {
101+ log .G (ctx ).WithError (err ).Warn ("urunc(shim): resolve bundle path during Delete failed" )
102+ loadErr = err
103+ } else {
104+ shouldCleanup , snapshotter , loadErr = containerdShim .ShouldCleanupRootfsView (bundle )
105+ }
106+ }
107+
108+ // Delete tears down the monitor namespace before removing the view it may pin.
109+ resp , err := s .TaskService .Delete (ctx , r )
110+
111+ if loadErr != nil {
112+ if err != nil {
113+ return resp , err
114+ }
115+ return resp , loadErr
116+ }
117+
118+ if shouldCleanup {
119+ session , sessionErr := containerdShim .OpenSession (ctx , s .containerdAddress , r .ID )
120+ if sessionErr != nil {
121+ log .G (ctx ).WithError (sessionErr ).Warn ("urunc(shim): open containerd session for rootfs view cleanup failed" )
122+ if err == nil {
123+ err = sessionErr
124+ }
125+ } else {
126+ defer func () {
127+ if err := session .Close (); err != nil {
128+ log .G (ctx ).WithError (err ).Warn ("urunc(shim): failed to close containerd session after rootfs view cleanup" )
129+ }
130+ }()
131+ if cleanupErr := containerdShim .NewRootfsViewAccessor (session ).Cleanup (ctx , snapshotter ); cleanupErr != nil {
132+ log .G (ctx ).WithError (cleanupErr ).Warn ("urunc(shim): delete rootfs view during Delete failed" )
133+ if err == nil {
134+ err = cleanupErr
135+ }
136+ }
137+ }
138+ }
139+
140+ return resp , err
72141}
73142
74143func (s * taskService ) RegisterTTRPC (server * ttrpc.Server ) error {
75144 taskAPI .RegisterTaskService (server , s )
76145 return nil
77146}
147+
148+ func (s * taskService ) bundlePathFor (ctx context.Context , containerID string ) (string , error ) {
149+ if s .stateRoot == "" {
150+ return "" , fmt .Errorf ("task service state root is empty (shim cwd layout assumption violated)" )
151+ }
152+ ns , err := namespaces .NamespaceRequired (ctx )
153+ if err != nil {
154+ return "" , fmt .Errorf ("namespace required: %w" , err )
155+ }
156+ return filepath .Join (s .stateRoot , ns , containerID ), nil
157+ }
0 commit comments