2024-03-20 10:48:51 +00:00
package op
2023-02-01 21:33:44 +00:00
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/containerd/containerd/mount"
2023-02-09 09:12:11 +00:00
internalUtils "github.com/kairos-io/immucore/internal/utils"
2024-03-20 10:48:51 +00:00
"github.com/kairos-io/immucore/pkg/schema"
2023-02-01 21:33:44 +00:00
)
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L129
2024-03-20 10:48:51 +00:00
func BaseOverlay ( overlay schema . Overlay ) ( MountOperation , error ) {
2023-03-01 20:45:32 +00:00
var dat [ ] string
2023-02-01 21:33:44 +00:00
if err := os . MkdirAll ( overlay . Base , 0700 ) ; err != nil {
2024-03-20 10:48:51 +00:00
return MountOperation { } , err
2023-02-01 21:33:44 +00:00
}
2023-03-01 20:45:32 +00:00
// BackingBase can be a device (LABEL=COS_PERSISTENT) or a tmpfs+size (tmpfs:20%)
// We need to properly parse to understand what it is
// We probably should deprecate changing the overlay but leave the size, I don't see much use of this
2023-02-01 21:33:44 +00:00
2023-03-01 20:45:32 +00:00
// Load both separated
datTmpfs := strings . Split ( overlay . BackingBase , ":" )
datDevice := strings . Split ( overlay . BackingBase , "=" )
// Add whichever has 2 len as that indicates that it's the correct one
if len ( datDevice ) == 2 {
dat = datDevice
}
if len ( datTmpfs ) == 2 {
dat = datTmpfs
}
2023-02-01 21:33:44 +00:00
if len ( dat ) != 2 {
2024-03-20 10:48:51 +00:00
return MountOperation { } , fmt . Errorf ( "invalid backing base. must be a tmpfs with a size or a LABEL/UUID device. e.g. tmpfs:30%%, LABEL:COS_PERSISTENT. Input: %s" , overlay . BackingBase )
2023-02-01 21:33:44 +00:00
}
t := dat [ 0 ]
switch t {
case "tmpfs" :
2023-02-06 15:20:18 +00:00
tmpMount := mount . Mount { Type : "tmpfs" , Source : "tmpfs" , Options : [ ] string { fmt . Sprintf ( "size=%s" , dat [ 1 ] ) } }
2023-02-09 09:12:11 +00:00
tmpFstab := internalUtils . MountToFstab ( tmpMount )
2023-02-09 09:34:43 +00:00
tmpFstab . File = internalUtils . CleanSysrootForFstab ( overlay . Base )
2024-03-20 10:48:51 +00:00
return MountOperation {
2023-02-01 21:33:44 +00:00
MountOption : tmpMount ,
2023-02-06 15:20:18 +00:00
FstabEntry : * tmpFstab ,
2023-02-01 21:33:44 +00:00
Target : overlay . Base ,
2023-02-09 11:35:45 +00:00
} , nil
2023-03-01 20:45:32 +00:00
case "LABEL" , "UUID" :
fsType := internalUtils . DiskFSType ( internalUtils . ParseMount ( overlay . BackingBase ) )
blockMount := mount . Mount { Type : fsType , Source : internalUtils . ParseMount ( overlay . BackingBase ) }
2023-02-09 09:12:11 +00:00
tmpFstab := internalUtils . MountToFstab ( blockMount )
2023-02-09 09:29:26 +00:00
// TODO: Check if this is properly written to fstab, currently have no examples
2023-02-09 09:34:43 +00:00
tmpFstab . File = internalUtils . CleanSysrootForFstab ( overlay . Base )
2023-02-06 15:20:18 +00:00
tmpFstab . MntOps [ "default" ] = ""
2023-02-01 21:33:44 +00:00
2024-03-20 10:48:51 +00:00
return MountOperation {
2023-02-01 21:33:44 +00:00
MountOption : blockMount ,
2023-02-06 15:20:18 +00:00
FstabEntry : * tmpFstab ,
2023-02-01 21:33:44 +00:00
Target : overlay . Base ,
2023-02-09 11:35:45 +00:00
} , nil
2023-02-01 21:33:44 +00:00
default :
2024-03-20 10:48:51 +00:00
return MountOperation { } , fmt . Errorf ( "invalid overlay backing base type" )
2023-02-01 21:33:44 +00:00
}
}
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L183
2024-03-20 10:48:51 +00:00
func MountBind ( mountpoint , root , stateTarget string ) MountOperation {
2023-02-01 21:33:44 +00:00
mountpoint = strings . TrimLeft ( mountpoint , "/" ) // normalize, remove / upfront as we are going to re-use it in subdirs
rootMount := filepath . Join ( root , mountpoint )
bindMountPath := strings . ReplaceAll ( mountpoint , "/" , "-" )
stateDir := filepath . Join ( root , stateTarget , fmt . Sprintf ( "%s.bind" , bindMountPath ) )
2023-02-08 13:43:58 +00:00
tmpMount := mount . Mount {
Type : "overlay" ,
Source : stateDir ,
Options : [ ] string {
"bind" ,
} ,
}
2023-03-08 10:45:11 +00:00
internalUtils . Log . Debug ( ) . Str ( "where" , rootMount ) . Str ( "what" , stateDir ) . Msg ( "Bind mount" )
2023-02-09 09:12:11 +00:00
tmpFstab := internalUtils . MountToFstab ( tmpMount )
2023-02-09 09:29:26 +00:00
tmpFstab . File = internalUtils . CleanSysrootForFstab ( fmt . Sprintf ( "/%s" , mountpoint ) )
2023-03-01 10:42:46 +00:00
tmpFstab . Spec = internalUtils . CleanSysrootForFstab ( tmpFstab . Spec )
2024-03-20 10:48:51 +00:00
return MountOperation {
2023-02-08 13:43:58 +00:00
MountOption : tmpMount ,
FstabEntry : * tmpFstab ,
Target : rootMount ,
PrepareCallback : func ( ) error {
2023-02-09 09:12:11 +00:00
if err := internalUtils . CreateIfNotExists ( rootMount ) ; err != nil {
2023-02-08 13:43:58 +00:00
return err
}
2023-02-09 09:12:11 +00:00
if err := internalUtils . CreateIfNotExists ( stateDir ) ; err != nil {
2023-02-08 13:43:58 +00:00
return err
}
2023-02-09 09:12:11 +00:00
return internalUtils . SyncState ( internalUtils . AppendSlash ( rootMount ) , internalUtils . AppendSlash ( stateDir ) )
2023-02-08 13:43:58 +00:00
} ,
2023-02-01 21:33:44 +00:00
}
}
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L145
2024-03-20 10:48:51 +00:00
func MountWithBaseOverlay ( mountpoint , root , base string ) MountOperation {
2023-02-01 21:33:44 +00:00
mountpoint = strings . TrimLeft ( mountpoint , "/" ) // normalize, remove / upfront as we are going to re-use it in subdirs
rootMount := filepath . Join ( root , mountpoint )
bindMountPath := strings . ReplaceAll ( mountpoint , "/" , "-" )
2023-02-09 09:12:11 +00:00
// TODO: Should we error out if we cant create the target to mount to?
_ = internalUtils . CreateIfNotExists ( rootMount )
2023-02-09 12:48:35 +00:00
upperdir := filepath . Join ( base , bindMountPath , ".overlay" , "upper" )
workdir := filepath . Join ( base , bindMountPath , ".overlay" , "work" )
2023-02-01 21:33:44 +00:00
2023-02-09 12:48:35 +00:00
tmpMount := mount . Mount {
Type : "overlay" ,
Source : "overlay" ,
Options : [ ] string {
//"defaults",
fmt . Sprintf ( "lowerdir=%s" , rootMount ) ,
fmt . Sprintf ( "upperdir=%s" , upperdir ) ,
fmt . Sprintf ( "workdir=%s" , workdir ) ,
} ,
2023-02-01 21:33:44 +00:00
}
2023-02-09 12:48:35 +00:00
tmpFstab := internalUtils . MountToFstab ( tmpMount )
tmpFstab . File = internalUtils . CleanSysrootForFstab ( rootMount )
// TODO: update fstab with x-systemd info
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L170
2024-03-20 10:48:51 +00:00
return MountOperation {
2023-02-09 12:48:35 +00:00
MountOption : tmpMount ,
FstabEntry : * tmpFstab ,
Target : rootMount ,
PrepareCallback : func ( ) error {
// Make sure workdir and/or upper exists
_ = os . MkdirAll ( upperdir , os . ModePerm )
_ = os . MkdirAll ( workdir , os . ModePerm )
return nil
} ,
}
2023-02-01 21:33:44 +00:00
}