immucore/pkg/mount/fs.go
Itxaka aa5939da89
Rework workflow (#77)
This makes immucore run more in parallel rather than block everything
else. We just tell sysroot.mount that eventually it will be mounted and
to wait for a bit.

This allows us to be more flexible where to run and run in parallel in
cases like cdrom in which we may do things but we need the sysroot to be
mounted already but not from us.

Also adds the initramfs stage directly in immucore and merges all the dracut config into one

    Dont create sysroot, just add a timeout override so it waits for us
    Dont block on the service, just make sure to finish before
    initrd.target
    Fix mounts from cmdline
    More proper log
    Store logs under the /run/immucore dir
    Store rootfs and initramfs logs separated
    Do not log the full stages in INFO level
    Run initramfs stage in immucore directly on boot and cd/netboot
    Drop systemd requirement from dracut module

Signed-off-by: Itxaka itxaka.garcia@spectrocloud.com
2023-03-08 11:45:11 +01:00

142 lines
5.2 KiB
Go

package mount
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/containerd/containerd/mount"
internalUtils "github.com/kairos-io/immucore/internal/utils"
)
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L129
func baseOverlay(overlay Overlay) (mountOperation, error) {
var dat []string
if err := os.MkdirAll(overlay.Base, 0700); err != nil {
return mountOperation{}, err
}
// 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
// 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
}
if len(dat) != 2 {
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)
}
t := dat[0]
switch t {
case "tmpfs":
tmpMount := mount.Mount{Type: "tmpfs", Source: "tmpfs", Options: []string{fmt.Sprintf("size=%s", dat[1])}}
tmpFstab := internalUtils.MountToFstab(tmpMount)
tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base)
return mountOperation{
MountOption: tmpMount,
FstabEntry: *tmpFstab,
Target: overlay.Base,
}, nil
case "LABEL", "UUID":
fsType := internalUtils.DiskFSType(internalUtils.ParseMount(overlay.BackingBase))
blockMount := mount.Mount{Type: fsType, Source: internalUtils.ParseMount(overlay.BackingBase)}
tmpFstab := internalUtils.MountToFstab(blockMount)
// TODO: Check if this is properly written to fstab, currently have no examples
tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base)
tmpFstab.MntOps["default"] = ""
return mountOperation{
MountOption: blockMount,
FstabEntry: *tmpFstab,
Target: overlay.Base,
}, nil
default:
return mountOperation{}, fmt.Errorf("invalid overlay backing base type")
}
}
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L183
func mountBind(mountpoint, root, stateTarget string) mountOperation {
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))
tmpMount := mount.Mount{
Type: "overlay",
Source: stateDir,
Options: []string{
"bind",
},
}
internalUtils.Log.Debug().Str("where", rootMount).Str("what", stateDir).Msg("Bind mount")
tmpFstab := internalUtils.MountToFstab(tmpMount)
tmpFstab.File = internalUtils.CleanSysrootForFstab(fmt.Sprintf("/%s", mountpoint))
tmpFstab.Spec = internalUtils.CleanSysrootForFstab(tmpFstab.Spec)
return mountOperation{
MountOption: tmpMount,
FstabEntry: *tmpFstab,
Target: rootMount,
PrepareCallback: func() error {
if err := internalUtils.CreateIfNotExists(rootMount); err != nil {
return err
}
if err := internalUtils.CreateIfNotExists(stateDir); err != nil {
return err
}
return internalUtils.SyncState(internalUtils.AppendSlash(rootMount), internalUtils.AppendSlash(stateDir))
},
}
}
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L145
func mountWithBaseOverlay(mountpoint, root, base string) mountOperation {
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, "/", "-")
// TODO: Should we error out if we cant create the target to mount to?
_ = internalUtils.CreateIfNotExists(rootMount)
upperdir := filepath.Join(base, bindMountPath, ".overlay", "upper")
workdir := filepath.Join(base, bindMountPath, ".overlay", "work")
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),
},
}
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
return mountOperation{
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
},
}
}