mirror of
https://github.com/kairos-io/packages.git
synced 2025-08-23 08:08:38 +00:00
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.
279 lines
7.5 KiB
Bash
Executable File
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
|