@@ -238,33 +238,37 @@ func (u *Unikontainer) SetupNet() (types.NetDevParams, error) {
238238// 3. Container rootfs as block device (if MountRootfs=true and supported)
239239// 4. Container rootfs as shared-fs: virtiofs > 9pfs (if MountRootfs=true and supported)
240240// 5. No rootfs
241- func ( u * Unikontainer ) chooseRootfs ( ) (types.RootfsParams , error ) {
242- bundleDir := filepath .Clean (u . State . Bundle )
243- rootfsDir := filepath .Clean (u . Spec . Root . Path )
241+ func ChooseRootfs ( bundle , specRoot string , annot map [ string ] string , cfg * UruncConfig ) (types.RootfsParams , error ) {
242+ bundleDir := filepath .Clean (bundle )
243+ rootfsDir := filepath .Clean (specRoot )
244244 rootfsDir , err := resolveAgainstBase (bundleDir , rootfsDir )
245245 if err != nil {
246246 uniklog .Errorf ("could not resolve rootfs directory %s: %v" , rootfsDir , err )
247247 return types.RootfsParams {}, err
248248 }
249249
250- unikernelType := u .State .Annotations [annotType ]
250+ if cfg == nil {
251+ return types.RootfsParams {}, fmt .Errorf ("urunc config is required for guest rootfs selection" )
252+ }
253+
254+ unikernelType := annot [annotType ]
251255 unikernel , err := unikernels .New (unikernelType )
252256 if err != nil {
253257 return types.RootfsParams {}, err
254258 }
255259
256- vmmType := u . State . Annotations [annotHypervisor ]
257- vmm , err := hypervisors .NewVMM (hypervisors .VmmType (vmmType ), u . UruncCfg .Monitors )
260+ vmmType := annot [annotHypervisor ]
261+ vmm , err := hypervisors .NewVMM (hypervisors .VmmType (vmmType ), cfg .Monitors )
258262 if err != nil {
259263 return types.RootfsParams {}, err
260264 }
261265
262- virtiofsdConfig := u . UruncCfg .ExtraBins ["virtiofsd" ]
266+ virtiofsdConfig := cfg .ExtraBins ["virtiofsd" ]
263267
264268 selector := & rootfsSelector {
265269 bundle : bundleDir ,
266270 cntrRootfs : rootfsDir ,
267- annot : u . State . Annotations ,
271+ annot : annot ,
268272 unikernel : unikernel ,
269273 vmm : vmm ,
270274 vfsdPath : virtiofsdConfig .Path ,
@@ -285,7 +289,7 @@ func (u *Unikontainer) chooseRootfs() (types.RootfsParams, error) {
285289 // Priority 3 & 4: Container rootfs (block or shared-fs)
286290 result , ok = selector .tryContainerRootfs ()
287291 if ok {
288- return switchMonRootfs (result , bundleDir )
292+ return switchMonRootfs (result , bundleDir ), nil
289293 }
290294
291295 if selector .shouldMountContainerRootfs () {
@@ -426,11 +430,39 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {
426430 // if the respective annotation is set then, depending on the guest
427431 // (supports block or 9pfs), it will use the supported option. In case
428432 // both ae supported, then the block option will be used by default.
429- rootfsParams , err := u .chooseRootfs ()
430- if err != nil {
431- uniklog .Errorf ("could not choose guest rootfs: %v" , err )
432- return err
433+ var rootfsParams types.RootfsParams
434+ // Read annotRootfsParams: shim writes it to config.json after inner Create;
435+ // state.json may not have it yet during reexec, so fall back to spec.
436+ rootfsParamsJSON := ""
437+ if u .State .Annotations != nil {
438+ rootfsParamsJSON = u .State .Annotations [annotRootfsParams ]
439+ }
440+ if rootfsParamsJSON == "" && u .Spec .Annotations != nil {
441+ rootfsParamsJSON = u .Spec .Annotations [annotRootfsParams ]
442+ }
443+ if rootfsParamsJSON != "" {
444+ // Shim (or a prior run) already called ChooseRootfs; decode and use as-is.
445+ if err := json .Unmarshal ([]byte (rootfsParamsJSON ), & rootfsParams ); err != nil {
446+ return fmt .Errorf ("could not decode guest rootfs params: %w" , err )
447+ }
448+ } else {
449+ // No annotRootfsParams (e.g. podman, urunc CLI): same path as legacy
450+ // u.chooseRootfs(), including no-guest-rootfs when mountRootfs is unset.
451+ specRoot := ""
452+ if u .Spec .Root != nil {
453+ specRoot = u .Spec .Root .Path
454+ }
455+ rootfsParams , err = ChooseRootfs (u .State .Bundle , specRoot , u .State .Annotations , u .UruncCfg )
456+ if err != nil {
457+ uniklog .Errorf ("could not choose guest rootfs: %v" , err )
458+ return err
459+ }
433460 }
461+ uniklog .WithFields (logrus.Fields {
462+ "rootfs_type" : rootfsParams .Type ,
463+ "rootfs_path" : rootfsParams .Path ,
464+ "mon_rootfs" : rootfsParams .MonRootfs ,
465+ }).Debug ("guest rootfs params" )
434466
435467 // TODO: Add support for using both an existing
436468 // block based snapshot of the container's rootfs
@@ -479,6 +511,15 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {
479511 }
480512 }
481513
514+ if _ , err = os .Stat (rootfsParams .MonRootfs ); err != nil {
515+ if ! os .IsNotExist (err ) {
516+ return fmt .Errorf ("failed to stat monitor rootfs directory %s: %w" , rootfsParams .MonRootfs , err )
517+ }
518+ if err = os .MkdirAll (rootfsParams .MonRootfs , 0o755 ); err != nil {
519+ return fmt .Errorf ("failed to create monitor rootfs directory %s: %w" , rootfsParams .MonRootfs , err )
520+ }
521+ }
522+
482523 err = rfsBuilder .preSetup ()
483524 if err != nil {
484525 return fmt .Errorf ("pre setup step for rootfs failed: %w" , err )
0 commit comments