packages/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh
Ettore Di Giacinto 25cef27405 New package layout
This layout is needed to allow to build Kairos derivatives with our CRD easier.
Some of them where globbed and pieces have been refactored to allow to consume them as Kairos bundles with osbuilder.
2022-11-12 19:19:42 +01:00

279 lines
7.5 KiB
Bash
Executable File

#!/bin/bash
# cos_root_perm, cos_mounts and cos_overlay variables already processsed
#======================================
# Functions
#--------------------------------------
function getOverlayMountpoints {
local mountpoints
for path in "${rw_paths[@]}"; do
if ! hasMountpoint "${path}" "${cos_mounts[@]}"; then
mountpoints+="${path}:overlay "
fi
done
echo "${mountpoints}"
}
function getStateMountpoints {
local mountpoints=$1
local state_mounts
for path in "${state_paths[@]}"; do
if ! hasMountpoint "${path}" "${mountpoints}"; then
state_mounts+="${path} "
fi
done
echo "${state_mounts}"
}
function hasMountpoint {
local path=$1
shift
local mounts=("$@")
for mount in "${mounts[@]}"; do
if [ "${path}" = "${mount#*:}" ]; then
return 0
fi
done
return 1
}
function parseOverlay {
local overlay=$1
case "${overlay}" in
UUID=*) \
overlay="block:/dev/disk/by-uuid/${overlay#UUID=}"
;;
LABEL=*) \
overlay="block:/dev/disk/by-label/${overlay#LABEL=}"
;;
esac
echo "${overlay}"
}
function parseCOSMount {
local mount=$1
case "${mount}" in
UUID=*) \
mount="/dev/disk/by-uuid/${mount#UUID=}"
;;
LABEL=*) \
mount="/dev/disk/by-label/${mount#LABEL=}"
;;
esac
echo "${mount}"
}
function readCOSLayoutConfig {
local mounts=()
: "${MERGE:=true}"
if [ "${DEBUG_RW}" = "true" ]; then
cos_root_perm="rw"
fi
if [ -n "${VOLUMES}" ]; then
for volume in ${VOLUMES}; do
mounts+=("$(parseCOSMount ${volume})")
done
fi
if [ "${MERGE}" = "true" ]; then
if [ -n "${cos_mounts}" ]; then
for mount in ${cos_mounts}; do
if ! hasMountpoint "${mount#*:}" "${mounts[@]}"; then
mounts+=("${mount}")
fi
done
fi
fi
if [ -n "${OVERLAY}" ]; then
cos_overlay=$(parseOverlay "${OVERLAY}")
fi
if [ ${#mounts[@]} -gt 0 ]; then
cos_mounts=("${mounts[@]}")
else
cos_mounts=()
fi
state_paths=()
state_bind="${PERSISTENT_STATE_BIND:-false}"
state_target="${PERSISTENT_STATE_TARGET:-/usr/local/.state}"
# An empty RW_PATHS is a valid value, default rw_paths are only
# applied when RW_PATHS is unset.
if [ -n "${RW_PATHS+x}" ]; then
rw_paths=(${RW_PATHS})
fi
if [ -n "${PERSISTENT_STATE_PATHS}" ]; then
state_paths=(${PERSISTENT_STATE_PATHS})
fi
}
function getCOSMounts {
local mounts
for mount in "${cos_mounts[@]}"; do
mounts+="${mount#*:}:${mount%%:*} "
done
mounts+="$(getOverlayMountpoints)"
echo -e "${mounts// /\\n}" | sort -
}
function mountOverlayBase {
local fstab_line
mkdir -p "${overlay_base}"
if [ "${cos_overlay%%:*}" = "tmpfs" ]; then
overlay_size="${cos_overlay#*:}"
mount -t tmpfs -o "defaults,size=${overlay_size}" tmpfs "${overlay_base}"
fstab_line="tmpfs ${overlay_base} tmpfs defaults,size=${overlay_size} 0 0\n"
elif [ "${cos_overlay%%:*}" = "block" ]; then
overlay_block="${cos_overlay#*:}"
mount -t auto "${overlay_block}" "${overlay_base}"
fstab_line="${overlay_block} ${overlay_base} auto defaults 0 0\n"
fi
echo "${fstab_line}"
}
function mountOverlay {
local mount=$1
local base=${2:-$overlay_base}
local merged
local upperdir
local workdir
local fstab_line
mount="${mount#/}"
merged="/sysroot/${mount}"
if [ "${base##/run}" == "${base}" ]; then
base="/sysroot${base}"
fi
if ! mountpoint -q "${merged}"; then
upperdir="${base}/${mount//\//-}.overlay/upper"
workdir="${base}/${mount//\//-}.overlay/work"
mkdir -p "${merged}" "${upperdir}" "${workdir}"
if [ $? -ne 0 ]; then
>&2 echo "failed creating one of '${merged}', '${upperdir}' or '${workdir}'. Ignoring '${merged}' mount"
return
fi
mount -t overlay overlay -o "defaults,lowerdir=${merged},upperdir=${upperdir},workdir=${workdir}" "${merged}"
fstab_line="overlay /${mount} overlay defaults,lowerdir=/${mount},upperdir=${upperdir##/sysroot},workdir=${workdir##/sysroot}"
required_mount=$(findmnt -fno TARGET --target "${base}")
if [ -n "${required_mount}" ] && [ "${required_mount}" != "/" ]; then
fstab_line+=",x-systemd.requires-mounts-for=${required_mount##/sysroot}"
fi
fstab_line+="\n"
fi
echo "${fstab_line}"
}
function mountState {
local mount=$1
local base
local fstab_line
local state_dir
if [ "${state_bind}" = "true" ]; then
mount="${mount#/}"
base="/sysroot/${mount}"
state_dir="/sysroot${state_target}/${mount//\//-}.bind"
if ! mountpoint -q "${base}"; then
mkdir -p "${base}" "${state_dir}"
if [ $? -ne 0 ]; then
>&2 echo "failed creating '${base}' or '${state_dir}'. Ignoring '${base}' mount"
return
fi
rsync -aqAX "${base}/" "${state_dir}/"
mount -o defaults,bind "${state_dir}" "${base}"
fstab_line="${state_dir##/sysroot} /${mount} none defaults,bind 0 0\n"
fi
else
fstab_line=$(mountOverlay "${mount}" "${state_target}")
fi
echo "${fstab_line}"
}
function mountPersistent {
local mount=$1
if [ -e "${mount#*:}" ] && ! findmnt -rno SOURCE "${mount#*:}" > /dev/null; then
mount -t auto "${mount#*:}" "/sysroot${mount%%:*}"
else
echo "Warning: ${mount#*:} already mounted or device not found" >&2
fi
echo "${mount#*:} ${mount%%:*} auto defaults 0 0\n"
}
#======================================
# Mount the rootfs layout
#--------------------------------------
PATH=/usr/sbin:/usr/bin:/sbin:/bin
declare cos_mounts=${cos_mounts}
declare cos_overlay=${cos_overlay}
declare cos_root_perm=${cos_root_perm}
declare overlay_base="/run/overlay"
declare rw_paths=("/etc" "/root" "/home" "/opt" "/srv" "/usr/local" "/var")
declare etc_conf="/sysroot/etc/systemd/system/etc.mount.d"
declare cos_layout="/run/cos/cos-layout.env"
declare root_fstype=$(findmnt -rno FSTYPE /sysroot)
declare root=$(findmnt -rno SOURCE /sysroot)
declare fstab
declare state_label
declare state_paths
declare state_bind
declare state_target
readCOSLayoutConfig
[ -z "${cos_overlay}" ] && exit 0
# If sysroot is already an overlay do not prepare the rw overlay
if [ "${root_fstype}" != "overlay" ]; then
state_label=$(ls /tmp/cosloop-*)
state_label="${state_label##/tmp/cosloop-}"
if [ -f "/dev/disk/by-label/${state_label}" ]; then
fstab="/dev/disk/by-label/${state_label} /run/initramfs/cos-state auto ${cos_root_perm} 0 0\n"
fi
fstab+="${root} / auto ${cos_root_perm} 0 0\n"
fstab+=$(mountOverlayBase)
fi
mountpoints=($(getCOSMounts))
for mount in "${mountpoints[@]}"; do
if [ "${mount#*:}" = "overlay" ]; then
if [ "${root_fstype}" != "overlay" ]; then
fstab+=$(mountOverlay "${mount%%:*}")
fi
else
# FSCK
systemd-fsck "${mount#*:}"
fstab+=$(mountPersistent "${mount}")
fi
done
for mount in $(getStateMountpoints "${mountpoints[@]}"); do
fstab+=$(mountState "${mount}")
done
echo -e "${fstab}" > /sysroot/etc/fstab
if [ ! -f "${etc_conf}/override.conf" ]; then
mkdir -p "${etc_conf}"
{
echo "[Mount]"
echo "LazyUnmount=true"
} > "${etc_conf}/override.conf"
fi
exit 0