@@ -25,7 +25,6 @@ import (
2525 cntrtypes "github.com/containerd/containerd/api/types"
2626 "github.com/containerd/containerd/errdefs"
2727 "github.com/containerd/containerd/mount"
28- "github.com/sirupsen/logrus"
2928 "github.com/urunc-dev/urunc/pkg/unikontainers"
3029 "github.com/urunc-dev/urunc/pkg/unikontainers/types"
3130 "google.golang.org/grpc/metadata"
@@ -37,10 +36,7 @@ const (
3736 rootfsViewAnnotation = "com.urunc.internal.rootfs.view"
3837)
3938
40- var (
41- ErrRootfsViewNotPrepared = errors .New ("rootfs view not prepared" )
42- rootfsViewLog = logrus .WithField ("subsystem" , "containerd-shim-rootfs-view" )
43- )
39+ var ErrRootfsViewNotPrepared = errors .New ("rootfs view not prepared" )
4440
4541type rootfsViewState struct {
4642 Snapshotter string `json:"snapshotter"`
@@ -79,33 +75,34 @@ func (a *RootfsViewAccessor) leaseID() string {
7975 return rootfsViewLeasePrefix + a .containerID
8076}
8177
82- func (a * RootfsViewAccessor ) ShouldPrepare (rootfs types.RootfsParams ) bool {
78+ func (a * RootfsViewAccessor ) ShouldPrepare (rootfs types.RootfsParams ) ( bool , error ) {
8379 if a == nil ||
8480 a .snapshotter == "" ||
8581 a .snapshotKey == "" ||
8682 (a .snapshotter != "devmapper" && a .snapshotter != "blockfile" ) ||
8783 rootfs .Type != "block" ||
8884 rootfs .MountedPath == "" {
89- return false
85+ return false , nil
9086 }
9187
9288 uruncCfg , cfgErr := unikontainers .LoadUruncConfig (unikontainers .UruncConfigPath )
9389 if cfgErr != nil {
94- rootfsViewLog .WithError (cfgErr ).Warn ("failed to load urunc config; rootfs view disabled" )
95- return false
90+ return false , cfgErr
9691 }
97- return uruncCfg .RootfsView .Enabled
92+ return uruncCfg .RootfsView .Enabled , nil
9893}
9994
10095// Prepare records a read-only view of the committed rootfs snapshot for runtime use.
101- func (a * RootfsViewAccessor ) Prepare (ctx context.Context , bundle string ) error {
96+ // On success it returns JSON-encoded view state for the caller to persist in bundle
97+ // config.json together with other shim Create annotations.
98+ func (a * RootfsViewAccessor ) Prepare (ctx context.Context ) (string , error ) {
10299 if a == nil {
103- return fmt .Errorf ("rootfs view accessor is nil" )
100+ return "" , fmt .Errorf ("rootfs view accessor is nil" )
104101 }
105102
106103 snapshotKey , err := a .resolveCommittedSnapshotBase (ctx , a .snapshotter , a .snapshotKey )
107104 if err != nil {
108- return err
105+ return "" , err
109106 }
110107
111108 viewKey := a .viewKey ()
@@ -115,17 +112,15 @@ func (a *RootfsViewAccessor) Prepare(ctx context.Context, bundle string) error {
115112 if _ , err := a .leases .Create (nsCtx , & leasesapi.CreateRequest {ID : leaseID }); err != nil {
116113 err = containerdErr (err )
117114 if err != nil && ! errdefs .IsAlreadyExists (err ) {
118- return fmt .Errorf ("create rootfs view lease %s: %w" , leaseID , err )
115+ return "" , fmt .Errorf ("create rootfs view lease %s: %w" , leaseID , err )
119116 }
120117 }
121118
122119 leaseCtx := metadata .AppendToOutgoingContext (nsCtx , "containerd-lease" , leaseID )
123120 mounts , err := a .createRootfsView (leaseCtx , viewKey , snapshotKey )
124121 if err != nil {
125- if cleanupErr := cleanupRootfsViewLease (ctx , a .namespace , a .leaseID (), a .leases ); cleanupErr != nil {
126- rootfsViewLog .WithError (cleanupErr ).Warn ("failed to clean up rootfs view lease after prepare failure" )
127- }
128- return err
122+ _ = cleanupRootfsViewLease (ctx , a .namespace , a .leaseID (), a .leases )
123+ return "" , err
129124 }
130125
131126 state := & rootfsViewState {
@@ -135,26 +130,28 @@ func (a *RootfsViewAccessor) Prepare(ctx context.Context, bundle string) error {
135130
136131 encoded , err := json .Marshal (state )
137132 if err != nil {
138- return fmt .Errorf ("marshal rootfs view state: %w" , err )
133+ return "" , fmt .Errorf ("marshal rootfs view state: %w" , err )
139134 }
140- if err := unikontainers .PatchBundleRootfsView (bundle , string (encoded )); err != nil {
141- if cleanupErr := cleanupRootfsView (ctx , a .namespace , a .containerID , a .snapshotter , a .snapshots , a .leases ); cleanupErr != nil {
142- rootfsViewLog .WithError (cleanupErr ).Warn ("failed to clean up rootfs view after state persistence failure" )
143- return fmt .Errorf ("persist rootfs view state: %w (cleanup also failed: %v)" , err , cleanupErr )
144- }
145- return fmt .Errorf ("persist rootfs view state: %w" , err )
146- }
147-
148- return nil
135+ return string (encoded ), nil
149136}
150137
138+ // Cleanup removes the per-container rootfs view snapshot and lease.
139+ // snapshotter names the devmapper/blockfile plugin that owns the view; callers
140+ // on Delete should pass the value persisted in bundle config.json at Prepare
141+ // time (see ShouldCleanupRootfsView). After inner task Delete, containerd
142+ // container metadata may no longer be loadable, so do not rely on a.snapshotter
143+ // alone on that path. When snapshotter is empty, a.snapshotter from the session
144+ // is used (Create-time rollback while the container record still exists).
151145func (a * RootfsViewAccessor ) Cleanup (ctx context.Context , snapshotter string ) error {
152146 if a == nil {
153147 return fmt .Errorf ("rootfs view accessor is nil" )
154148 }
155149 if a .containerID == "" {
156150 return fmt .Errorf ("container id is empty" )
157151 }
152+ if snapshotter == "" {
153+ snapshotter = a .snapshotter
154+ }
158155 if snapshotter == "" {
159156 return fmt .Errorf ("snapshotter is empty" )
160157 }
@@ -300,7 +297,6 @@ func cleanupRootfsView(
300297 Key : rootfsViewKey (containerID ),
301298 })
302299 if err = containerdErr (err ); err != nil && ! errdefs .IsNotFound (err ) {
303- rootfsViewLog .WithError (err ).Warn ("failed to remove rootfs view from containerd" )
304300 return err
305301 }
306302 return cleanupRootfsViewLease (ctx , namespace , rootfsViewLeaseID (containerID ), leases )
@@ -312,7 +308,6 @@ func cleanupRootfsViewLease(ctx context.Context, namespace, leaseID string, leas
312308 }
313309 _ , err := leases .Delete (withNamespace (ctx , namespace ), & leasesapi.DeleteRequest {ID : leaseID })
314310 if err = containerdErr (err ); err != nil && ! errdefs .IsNotFound (err ) {
315- rootfsViewLog .WithError (err ).Warn ("failed to remove rootfs view lease from containerd" )
316311 return err
317312 }
318313 return nil
0 commit comments