live-metal/blend_helpers

840 lines
28 KiB
Bash

#!/usr/bin/env zsh
# shellcheck shell=bash
# Copyright (c) 2016-2021 Ivan J. <parazyd@dyne.org>
# This file is part of libdevuansdk
#
# This source code is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
build_metal_dist() {
fn build_metal_dist
req=(arch)
req+=(workdir strapdir disk_name)
ckreq || return 1
notice "installing complete dist"
act "add release symlink to debootstrap scripts."
if [[ ! -f /usr/share/debootstrap/scripts/${release} ]]; then
ln -sf /usr/share/debootstrap/scripts/ceres \
/usr/share/debootstrap/scripts/${release}
fi
image_partition_disk_zfs || { zerr; wrapup }
image_format_partitions_zfs || { zerr; wrapup }
bootstrap_complete_base || { zerr; wrapup }
blend_preinst || { zerr; wrapup }
blend_postinst || { zerr; wrapup }
}
# Overide the post 'debootstrap stage 2' placeholder function of zlib/debootstrap bootstrap_complete_base.
# The default is just to return 0
blend_bootstrap_setup() {
fn blend_bootstrap_setup "noop"
return 0
}
## Override the helper function:
# takes the 'apt-get -f' out of the loop so that dependency provided by other debs can be resolved.
# inside the loop it just uninstalls the deb because of unfullfilled deps.
install-custdebs() {
fn install-custdebs "(override)"
req=(R strapdir custom_deb_packages)
ckreq || return 1
sudo mkdir -p ${strapdir}/debs
sudo cp $R/extra/custom-packages/*.deb ${strapdir}/debs/
cat <<-EOF | sudo tee ${strapdir}/install-debs >/dev/null
#!/bin/sh
cd /debs
for deb in ${custom_deb_packages}; do
dpkg -i \$deb
done
apt-get --yes --force-yes -f install
cd /
apt-get --yes --force-yes autoremove
#rm -rf /debs
EOF
chroot-script -d install-debs
}
## Added function:
# In the style of install-custdebs above but for a collection of arbitrary scripts placed in a
# directory alongside the blend custom debs called automate.
# The scripts are copied from the blends scripts directory to extra/custom-scripts in blend_preinst() above.
# Called after install-customdebs because some need checkinstall which disappears from archives.
install-custscripts() {
fn install-custscripts
req=(R strapdir custom_scripts)
ckreq || return 1
sudo mkdir -p ${strapdir}/var/tmp/automate
sudo cp $R/extra/custom-scripts/*.sh ${strapdir}/var/tmp/automate/
cat <<-EOF | sudo tee ${strapdir}/install-scripts >/dev/null
#!/bin/sh
cd /var/tmp/automate
for script in ${custom_scripts}; do
touch \${script}.log
bash \$script
done
apt-get --yes --force-yes -f install
cd /
apt-get --yes --force-yes autoremove
#rm -rf /var/tmp/automate
EOF
chroot-script -d install-scripts
}
## Override the helper function:
# Allow an alternative skel directory
add-user() {
fn add-user $*
local user="$1"
local pass="$2"
local skel="$3"
req=(strapdir user pass skel)
ckreq || return 1
notice "adding user $user:$pass using $skel"
cat <<-EOF | sudo tee ${strapdir}/adduser >/dev/null
#!/bin/sh
set -x
if [ $(id -u ${user} 2>&1 >/dev/null) ]; then
echo "user not present, creating account."
useradd -m ${user} -k ${userskel:-/etc/skel}
echo "${user}:${pass}" | chpasswd
fi
EOF
chroot-script adduser || { zerr; return 0; }
}
## apt related functions
# point apt at a local apt-proxy like apt-cacher-ng
enable_apt-proxy() {
fn enable_apt-proxy
req=(strapdir apt_proxy)
ckreq || return 1
cat <<-EOF | sudo tee ${strapdir}/add_apt-proxy
#!/bin/sh
cat > '/etc/apt/apt.conf.d/02proxy' << 'FOE'
Acquire::http { Proxy "${apt_proxy}"; };
FOE
EOF
chroot-script add_apt-proxy || zerr
}
disable_apt-proxy() {
fn disable_apt-proxy
req=(strapdir)
ckreq || return 1
cat <<-EOF | sudo tee ${strapdir}/del_apt-proxy
#!/bin/sh
rm -f /etc/apt/apt.conf.d/02proxy
EOF
chroot-script del_apt-proxy || zerr
}
# When the release changes its suite (ie. from stable to oldstable) by default apt asks for explicite acceptance, which you might not want in your image, turn this on and off.
enable_apt-allow-releaseinfo-change() {
fn enable_apt-allow-releaseinfo-change
req=(strapdir)
ckreq || return 1
cat <<-EOF | sudo tee ${strapdir}/add_apt-releaseinfo-change
#!/bin/sh
cat > '/etc/apt/apt.conf.d/10no-check-valid-until' << 'FOE'
Acquire::AllowReleaseInfoChange::Suite "true";
FOE
EOF
chroot-script add_apt-releaseinfo-change || zerr
}
disable_apt-allow-releaseinfo-change() {
fn disable_apt-allow-releaseinfo-change
req=(strapdir)
ckreq || return 1
cat <<-EOF | sudo tee ${strapdir}/del_apt-allow-releaseinfo-change
#!/bin/sh
#
rm -f /etc/apt/apt.conf.d/10no-check-valid-until
EOF
chroot-script del_apt-allow-releaseinfo-change || zerr
}
# apt checks the valid-util and refuses to install from repositories that are too old, which you might not want if building an old release, turn this on or off.
disable_apt-valid-until() {
fn disable_apt-valid-until
req=(strapdir)
ckreq || return 1
cat <<-EOF | sudo tee ${strapdir}/add_apt-check-valid
#!/bin/sh
cat > '/etc/apt/apt.conf.d/10no-check-valid-until' << 'FOE'
Acquire::Check-Valid-Until "false";
FOE
EOF
chroot-script add_apt-check-valid || zerr
}
enable_apt-valid-until() {
fn enable_apt-valid-until
req=(strapdir)
ckreq || return 1
cat <<-EOF | sudo tee ${strapdir}/del_apt-check-valid
#!/bin/sh
rm -f /etc/apt/apt.conf.d/10no-check-valid-until
EOF
chroot-script del_apt-check-valid || zerr
}
# Overide the sdk version of this function to prevent deletion
# prior to unpacking the cpio as we have mountpoints in place
# when installing to hardrive.
bootstrap_cpio_unpack()
{
fn bootstrap_cpio_unpack "$*"
req=(_bootstrap_cpio strapdir)
local _bootstrap_cpio="$1"
ckreq || return 1
notice "Unpacking bootstrap cpio archive: $_bootstrap_cpio"
#sudo rm -rf "${strapdir}"/*
pushd "$strapdir" || { zerr; return 1; }
zcat "$_bootstrap_cpio" | sudo cpio -idmn --format=newc || { zerr; return 1; }
popd
sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
}
image_partition_disk_zfs() {
fn image_partition_disk_zfs
req=(strapdir disk_name efi_start efi_part_size swap_part_size boot_part_size available_disks)
ckreq || return 1
notice "partitioning disks"
# See: https://didrocks.fr/2020/06/11/zfs-focus-on-ubuntu-20.04-lts-zsys-partition-layout/
for disk in "${available_disks[@]}"; do
TARGET="/dev/disk/by-id/${disk}"
act "partitioning ${TARGET}"
/sbin/sgdisk --zap-all ${TARGET}
act "Partition 1 - Create partition using start and end values for partitioning the 'Bios boot' partition."
FIRST_USABLE_SECTOR=34
((ENDSECTOR = ${efi_start} - 1))
/sbin/sgdisk --print --set-alignment=1 --new=1:${FIRST_USABLE_SECTOR}:${ENDSECTOR} ${TARGET}
/sbin/sgdisk --print --change-name=1:"BIOS_Boot_Partition" --typecode=1:EF02 ${TARGET}
act "Partition 2 - Create partition using start and end values for partitioning the 'EFI' partition."
STARTSECTOR=${efi_start}
/sbin/sgdisk --print --set-alignment=${STARTSECTOR} --mbrtogpt --new=2:${STARTSECTOR}:+${efi_part_size} ${TARGET}
/sbin/sgdisk --print --change-name=2:"EFI_System_Partition" --typecode=2:EF00 ${TARGET}
act "Partition 3 - Create partition using start and end values for partitioning the 'swap' partition."
STARTSECTOR=`/sbin/sgdisk --first-in-largest ${TARGET}|sed -sn 2p`
/sbin/sgdisk --print --new=3:${STARTSECTOR}:+${swap_part_size} ${TARGET}
/sbin/sgdisk --print --change-name=3:"Linux_swap" --typecode=3:8200 ${TARGET}
act "Partition 4 - upto 2GB partition for boot."
STARTSECTOR=`/sbin/sgdisk --first-in-largest ${TARGET}|sed -sn 2p`
/sbin/sgdisk --print --new=4:${STARTSECTOR}:+${boot_part_size} ${TARGET}
/sbin/sgdisk --print --change-name=4:boot --typecode=4:BE00 ${TARGET}
act "Partition 5 - the main partition for root."
/sbin/sgdisk --print --largest-new=5 ${TARGET}
/sbin/sgdisk --print --change-name=5:root --typecode=5:BF00 ${TARGET}
act "Reread the current partition tables with partprobe."
# the second drive fails to update the kernel until reboot so added 2>
#partprobe ${TARGET} 2>/dev/null || true
hdparm -z ${TARGET}
done
}
image_format_partitions_zfs() {
fn image_format_partitions_zfs
req=(disk_name available_disks efi_partitions swap_partitions root_part_number boot_part_number rpool_name bpool_name zpool_cache_dir strapdir)
ckreq || return 1
act "format available efi partitions to vfat."
for efi_partition in "${efi_partitions[@]}"; do
act "format the efi partition to vfat."
mkfs.fat -F32 ${efi_partition}
done
act "mkswap on available swap partitions."
for swap_partition in "${swap_partitions[@]}"; do
notice "making swap on ${swap_partition}"
mkswap ${swap_partition}
done
notice "formatting zfs partitions..."
for disk in "${available_disks[@]}"; do
gdisk -l /dev/disk/by-id/${disk}
done
act "udev is slow recognize new partition so trigger sleep for 10 seconds"
sleep 10
# create a separate boot pool for /boot with the features limited to only those that GRUB supports
# allowing the root pool to use any/all features.
if [[ ${raid} == "mirror" ]]; then
mirror_disk=${available_disks[2]};
fi
act "create the zfs boot pool"
#zpool create -f -m none \
zpool create -f \
-o cachefile=${zpool_cache_dir}/zpool.cache \
-o ashift=${ashift} -d \
-o feature@async_destroy=enabled \
-o feature@bookmarks=enabled \
-o feature@embedded_data=enabled \
-o feature@empty_bpobj=enabled \
-o feature@enabled_txg=enabled \
-o feature@extensible_dataset=enabled \
-o feature@filesystem_limits=enabled \
-o feature@hole_birth=enabled \
-o feature@large_blocks=enabled \
-o feature@lz4_compress=enabled \
-o feature@spacemap_histogram=enabled \
-o feature@zpool_checkpoint=enabled \
-O acltype=posixacl \
-O canmount=off \
-O compression=lz4 \
-O devices=off \
-O normalization=formD \
-O relatime=on \
-O xattr=sa \
-O mountpoint=/boot -o altroot=${strapdir} \
${bpool_name} ${raid} /dev/disk/by-id/${disk_name}-part${boot_part_number} ${mirror_disk}
act "create the zfs root pool"
zpool create -f \
-o cachefile=${zpool_cache_dir}/zpool.cache \
-o ashift=${ashift} \
-O acltype=posixacl \
-O canmount=off \
-O compression=lz4 \
-O dnodesize=auto \
-O normalization=formD \
-O relatime=on \
-O xattr=sa \
-O mountpoint=/ -o altroot=${strapdir} \
${rpool_name} ${raid} /dev/disk/by-id/${disk_name}-part${root_part_number} ${mirror_disk}
## Physical swap used instead.
#act "create the zfs zvol for swap"
#zfs create -V ${swap_part_size} -b $(getconf PAGESIZE) \
# -o compression=zle \
# -o logbias=throughput \
# -o sync=always \
# -o primarycache=metadata \
# -o secondarycache=none \
# -o com.sun:auto-snapshot=false \
# ${rpool_name}/swap
#mkswap -f -L "Linux swap" /dev/zvol/${rpool_name}/swap
notice "zfs system installation"
act "create filesystem datasets to act as containers"
zfs create -o canmount=off -o mountpoint=none ${rpool_name}/ROOT
zfs create -o canmount=off -o mountpoint=none ${bpool_name}/BOOT
act "create filesystem datasets for the root and boot filesystems"
# Create the initial boot environment and mount ${rpool_name} at /${rpool_name}
zfs create -o canmount=noauto -o mountpoint=/ ${rpool_name}/ROOT/${root_name}
zfs mount ${rpool_name}/ROOT/${root_name}
#zfs create -o canmount=noauto -o mountpoint=/boot ${bpool_name}/BOOT/${root_name}
zfs create -o mountpoint=/boot ${bpool_name}/BOOT/${root_name}
# At this point rpool directory is created in the workdir
#zfs set mountpoint=/${rpool_name} ${rpool_name}
TMP_EXEC_STATE=on
VAR_TMP_EXEC_STATE=on
notice "create datasets"
act "create zfs datasets for $rpool_name"
zfs create -o mountpoint=/home ${rpool_name}/home
zfs create -o mountpoint=/root ${rpool_name}/home/root
zfs create -o mountpoint=/space ${rpool_name}/space
zfs create -o mountpoint=/opt ${rpool_name}/opt
zfs create -o mountpoint=/srv ${rpool_name}/srv
zfs create -o mountpoint=/usr \
-o canmount=off \
${rpool_name}/usr
zfs create -o mountpoint=/usr/share ${rpool_name}/usr/share
zfs create -o mountpoint=/usr/local ${rpool_name}/usr/local
zfs create -o mountpoint=/tmp \
-o setuid=off \
-o exec=${TMP_EXEC_STATE} \
-o com.sun:autosnapshot=false \
${rpool_name}/tmp
zfs create -o mountpoint=/var \
-o canmount=off \
${rpool_name}/var
zfs create -o mountpoint=/var/lib ${rpool_name}/var/lib
zfs create -o mountpoint=/var/lib/virt ${rpool_name}/var/lib/virt
zfs create -o mountpoint=/var/tmp \
-o setuid=off \
-o com.sun:auto-snapshot=false \
-o exec=${VAR_TMP_EXEC_STATE} \
${rpool_name}/var/tmp
zfs create -o mountpoint=/var/cache \
-o com.sun:auto-snapshot=false \
${rpool_name}/var/cache
zfs create \
-o mountpoint=/var/lib/docker \
-o com.sun:autosnapshot=false \
${rpool_name}/docker
zfs create -o mountpoint=/var/log ${rpool_name}/var/log
zfs create -o mountpoint=/var/snap ${rpool_name}/var/snap
zfs create -o mountpoint=/var/spool ${rpool_name}/var/spool
zfs create -o mountpoint=/var/www ${rpool_name}/var/www
zfs list -t all -o name,type,mountpoint,compress,exec,setuid,atime,relatime
chmod 700 ${strapdir}/root
chmod 1777 ${strapdir}/tmp
#chmod 1777 ${strapdir}/var/tmp
act "mount the efi partition on ${grub_mount} before debootstrap."
mount /dev/disk/by-id/${disk_name}-part${efi_part_number} -t vfat ${strapdir}${grub_mount}
act "create zpool cache file"
mkdir -p ${strapdir}/etc/zfs
cp ${zpool_cache_dir}/zpool.cache ${strapdir}/etc/zfs/
}
use_swap_partition() {
fn use_swap_partition
req=(swap_partitions)
ckreq || return 1
for swap_partition in "${swap_partitions[@]}"; do
act "Using swapon on ${swap_partition}"
swapon ${swap_partition}
done
}
image_zfs_mount() {
fn image_zfs_mount
req=(strapdir disk_name rpool_name bpool_name grub_mount)
ckreq || return 1
notice "image_zfs_mount"
act "importing zfs pools without mounting the filesystem"
zpool import -N -R ${strapdir} ${rpool_name}
zpool import -N -R ${strapdir} ${bpool_name}
if [[ -n $encrypt ]]; then
act "loading encryption keys of ZFS datasets from imported pools"
zfs load-key -a
fi
act "mounting zfs datasets"
zfs mount -v ${rpool_name}/ROOT/${root_name}
zfs mount -v ${bpool_name}/BOOT/${root_name}
zfs mount -v -a
act "mount efi partition to /boot/grub"
mkdir -p ${strapdir}${grub_mount}
mount /dev/disk/by-id/${disk_name}-part${efi_part_number} -t vfat ${strapdir}${grub_mount}
act "mount system directories"
devprocsys mount ${strapdir}
}
image_zfs_umount() {
fn image_zfs_umount
req=(workdir strapdir rpool_name bpool_name)
ckreq || return 1
notice "umount system directories"
devprocsys umount ${strapdir}
act "reaping chroot processes"
PREFIX=${strapdir}
FOUND=0
reap() {
for ROOT in /proc/*/root; do
LINK=$(readlink $ROOT)
if [[ "x${LINK}" != "x" ]]; then
if [[ "x${LINK:0:${#PREFIX}}" = "x${PREFIX}" ]]; then
PID=$(basename $(dirname "$ROOT"))
act "this process is in the chroot... $PID"
kill -9 "$PID"
FOUND=1
fi
fi
done
}
reap
if [[ "x$FOUND" = "x1" ]]; then
reap
fi
act "umount efi partition"
efi_path=/dev/disk/by-id/${disk_name}-part${efi_part_number}
if [[ $(/bin/mountpoint -q -- ${efi_path}) ]]; then
umount --lazy ${efi_path}
fi
act "umount zfs partitions"
COUNT=0
while grep -q "$PREFIX" /proc/mounts; do
COUNT=$(($COUNT+1))
if [ $COUNT -ge 20 ]; then
echo "failed to umount $PREFIX"
if [ -x /usr/bin/lsof ]; then
/usr/bin/lsof "$PREFIX"
fi
exit 1
fi
grep "$PREFIX" /proc/mounts | \
cut -d\ -f2 | LANG=C sort -r | xargs -r -n 1 umount || sleep 1
done
act "export zfs pools."
zpool export ${bpool_name}
zpool export ${rpool_name}
}
get_selections() {
fn get_selections
req=(strapdir blend_release_path)
ckreq || return 1
notice "generating package list files to ${blend_release_path}"
pushd "${blend_release_path}"
dpkg --get-selections > packages.list
debconf-get-selections > debconf-settings.list
update-alternatives --get-selections > /var/tmp/alternatives-settings.list
/usr/bin/apt-mark showauto > pkgs_auto.lst
/usr/bin/apt-mark showmanual > pkgs_manual.lst
popd
}
set_selections() {
fn set_selections
req=(strapdir blend_release_path)
ckreq || return 1
pushd "${blend_release_path}"
notice "copying set selections related files to ${strapdir}/var/tmp"
if [[ -f ./packages.list ]]; then
cp ./packages.list ${strapdir}/var/tmp
else
act "no package.list found in ${blend_release_path} "
exit 0
fi
if [[ -f ./debconf-settings.list ]]; then
cp ./debconf-settings.list ${strapdir}/var/tmp
else
act "no debconf-settings.list found in ${blend_release_path} "
exit 0
fi
if [[ -f ./alternatives-settings.list ]]; then
cp ./alternatives-settings.list ${strapdir}/var/tmp
else
act "no alternatives-settings.list found in ${blend_release_path} "
exit 0
fi
if [[ -f ./pkgs_auto.lst ]]; then
cp ./pkgs_auto.lst ${strapdir}/var/tmp
else
act "no pkgs_auto.lst found in ${blend_release_path}"
fi
if [[ -f ./pkgs_auto.lst ]]; then
cp ./pkgs_manual.lst ${strapdir}/var/tmp
else
act "no pkgs_manual.lst found in ${blend_release_path}"
fi
popd
notice "upgrading using dselect"
cat <<-EOF | sudo tee "$strapdir/install-set-selections" >/dev/null
#!/bin/sh
dpkg --set-selections 2>&1 < /var/tmp/packages.list
debconfig-set-selections 2>&1 < /var/tmp/debconf-settings.list
update-alternatives --set-selections 2>&1 < /var/tmp/alternatives-settings.list
apt-get -y -u dselect-upgrade
if [[ -f /var/tmp/pkgs_auto.lst ]]; then
apt-mark auto $(cat /var/tmp/pkgs_auto.lst)
fi
if [[ -f /var/tmp/pkgs_manual.lst ]]; then
apt-mark manual $(cat /var/tmp/pkgs_manual.lst)
fi
EOF
chroot-script -d install-set-selections || { zerr; return 1; }
}
enablessh() {
fn enablessh
req=(strapdir)
ckreq || return 1
notice "enabling ssh access without password."
act "Use ssh-copy-id default@192.168.1.x to login on reboot."
act "adding or creating keys (place keys in /etc/ssh/ssh_host_rsa_key.pub)"
cat <<-EOF | sudo tee "$strapdir/etc/rc.local" >/dev/null
#!/bin/sh
# rc.local for base images
[ -f /etc/ssh/ssh_host_rsa_key.pub ] || ssh-keygen -A
exit 0
EOF
sudo chmod +x "$strapdir/etc/rc.local"
cat <<-EOF | sudo tee "$strapdir/enablessh" >/dev/null
#!/usr/bin/env zsh
set -x ; exec 2>${PWD}/enablessh.log
config_file="/tmp/sshd_config"
typeset -A rules
rules=(
"LoginGraceTime" "1m"
"PermitRootLogin" "yes"
"PasswordAuthentication" "no"
"AllowUsers" "${username}"
)
EOF
cat <<-'EOF' | sudo tee -a "$strapdir/enablessh" >/dev/null
for rule in "${(@k)rules}"; do
regex="s/^#\?\(${rule}\s*\).*$/\1 ${rules[${rule}]}/"
sed -i "${regex}" ${config_file};
done
EOF
chroot-script -d enablessh || { zerr; return 1; }
}
install_kernel_headers() {
fn install_kernel_headers
req=(strapdir kernel_version arch)
ckreq || return 1
# could go in blends/devuan-desktop-live/config $extra_packages and
# remove headers in blends/devuan-desktop-live/chimaera/config $purge_packages
notice "install kernel headers"
cat <<-EOF | sudo tee "$strapdir/install-kernel-headers" >/dev/null
#!/bin/sh
apt-get install -y linux-image-${kernel_version}-${arch}
apt-get install -y linux-headers-${kernel_version}-${arch}
apt-get -y -f install
EOF
chroot-script -d install-kernel-headers || { zerr; return 1; }
}
install_zfs() {
fn install_zfs
req=(strapdir rpool_name bpool_name root_name grubversion)
ckreq || return 1
act "install zfs to the $strapdir"
act "install the zfs packages in the correct order before dselect upgrade"
cat <<-EOF | sudo tee "$strapdir/install-zfs" >/dev/null
#!/bin/sh
apt-get remove -y live-config && apt-get -y autoremove
apt-get install -y spl-dkms dh-autoreconf
apt-get install -y zfs-dkms zfs-initramfs zfsnap zfsutils-linux ${grubversion} busybox console-setup
apt-get -y -f install
# add nouveau graphics setting before updating initramfs: add to the grub commandline with
update-initramfs -u
# zfs_autoimport_disable is now compiled as set to 1/true by default
# At module load 0=read zpool.cache 1=do not read zpool.cache
#echo '# https://openzfs.github.io/openzfs-docs/Performance and Tuning/Module Parameters.html' > /etc/modprobe.d/zfs.conf
#echo 'options zfs zfs_autoimport_disable=0' >> /etc/modprobe.d/zfs.conf
echo 'options zfs l2arc_write_max=50331648' >> /etc/modprobe.d/zfs.conf
echo 'options zfs l2arc_write_boost=100663296' >> /etc/modprobe.d/zfs.conf
# Additional datasets to /etc/default/zfs not created under ROOT
sed -i "s/#ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\"/" /etc/default/zfs
#
sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/home\"/" /etc/default/zfs
sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/space\"/" /etc/default/zfs
sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/tmp\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/opt\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/usr_share\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/usr_local\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_lib\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_lib_docker\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_lib_virt\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var_tmp\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/usr\"/" /etc/default/zfs
#sed -i "s/ZFS_INITRD_ADDITIONAL_DATASETS=\"\(.*\)\"/ZFS_INITRD_ADDITIONAL_DATASETS=\"\1 ${rpool_name}\/ROOT\/${root_name}\/var\"/" /etc/default/zfs
EOF
chroot-script -d install-zfs || { zerr; return 1; }
}
install_grub(){
fn install_grub
req=(strapdir disk_name efi_partitions swap_part_number rpool_name bpool_name root_name grub_mount grub_theme grub_gfxmode)
ckreq || return 1
notice "installing grub."
act "move the grub theme to the grub partition, stops 'update-alternatives desktop-grub-theme' from working."
mkdir -p /boot/grub/grub-themes
cp -a /usr/share/desktop-base/grub-themes/${grub_theme} /boot/grub/grub-themes/
act "replace the pool name detection with zdb command in /etc/grub.d/10_linux."
sed -i "s|rpool=.*|rpool=\`zdb -l \${GRUB_DEVICE} \| grep -E '[[:blank:]]name' \| cut -d\\\' -f 2\`|" $strapdir/etc/grub.d/10_linux
act "change the grub kernel commandline"
cat <<-EOF | sudo tee "$strapdir/write-default-grub" >/dev/null
#!/bin/sh
set -x
# GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/zvol/rpool/swap radeon:modeset=1 i915:modeset=1 cgroup_enable=memory swapaccount=1 net.ifnames=0
# set boot filesystem - duplicated by grub but misses rpool_name when grub-probe fails to read filesystem type.
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 zfs=${rpool_name}\"|" /etc/default/grub
# set swap as the resume partition.
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 resume=/dev/disk/by-id/${disk_name}-part${swap_part_number}\"|" /etc/default/grub
# set root - Not needed as the kernel and root are set before /etc/default/grub is added
#sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 root=ZFS=${rpool_name}\/ROOT\/${root_name}\"|" /etc/default/grub
# init_on_alloc=1 is a security hardening mechanism preventing a class of security issues from being exploitable.
# init_on_alloc=1 causes big performance regression for zfs: ubuntu +bug/1862822
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 init_on_alloc=0\"|" /etc/default/grub
# enable udev "info" logging for block devices
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 rd.log.block=info\"|" /etc/default/grub
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 cgroup_enable=memory\"|" /etc/default/grub
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 swapaccount=1\"|" /etc/default/grub
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 net.ifnames=0\"|" /etc/default/grub
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 nouveau.modeset=1\"|" /etc/default/grub
#sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 i915.modeset=1\"|" /etc/default/grub
#sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 radeon.modeset=1\"|" /etc/default/grub
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 noplymouth nosplash\"|" /etc/default/grub
sed -i '/^#GRUB_DISABLE_LINUX_UUID=.*/ s/.*/&\nGRUB_DISABLE_LINUX_UUID=true/' /etc/default/grub
sed -i '/^#GRUB_TIMEOUT=.*/ s/.*/&\nGRUB_RECORDFAIL_TIMEOUT=5/' /etc/default/grub
#sed -i "s|^#GRUB_DISABLE_LINUX_UUID=\"\(.*\)\"|GRUB_DISABLE_LINUX_UUID=\"\1 true\"|" /etc/default/grub
echo "" >> /etc/default/grub
echo "# Preload modules so that they are not missed." >> /etc/default/grub
echo "GRUB_PRELOAD_MODULES=part_gpt" >> /etc/default/grub
sed -i "s|^\(GRUB_GFXMODE=\).*|\1\"$grub_gfxmode\"|" /etc/default/grub
sed -i '/^GRUB_GFXMODE=.*/ s/.*/&\nGRUB_GFXPAYLOAD_LINUX=\"keep\"/' /etc/default/grub
sed -i "s|^\(GRUB_THEME=\).&|\1\"/boot/grub/grub-themes/${grub_theme}/theme.txt\"|" /etc/default/grub
# debug grub
sed -i "s/quiet//" /etc/default/grub
#sed -i "s/#GRUB_TERMINAL/GRUB_TERMINAL/" /etc/default/grub
EOF
chroot-script -d write-default-grub || { zerr; return 1; }
#umount -q ${strapdir}${grub_mount}
if [[ -v $efi ]]; then
mkdir -p ${grub_mount}
act "write grub-efi to available efi partitions."
for efi_partition in "${efi_partitions[@]}"; do
notice "writing to efi partitions: ${efi_partitions}"
act "mount the primary disks efi partition under ${grub_mount}"
mount ${disk_path}/${disk_name}-part${efi_part_number} ${strapdir}${grub_mount}
cat <<-EOF | sudo tee ${strapdir}/update-grub_${disk_name} > /dev/null
#!/bin/sh
echo "populate the ${grub_mount} with update-grub."
grub-mkconfig -o ${grub_mount}/grub.cfg
echo "install grub to disk name ${disk_name}, efi partition ${efi_partition}"
grub-install --target=${grub_efi_target} \
--no-uefi-secure-boot \
--efi-directory=${grub_mount} \
--bootloader-id="Devuan ${release} (RAID disk ${disk_name})"
--recheck \
--no-floppy
EOF
chroot-script -d update-grub_${disk_name} || { zerr; return 1; }
umount ${strapdir}${grub_mount}
done
else
mkdir -p ${grub_mount}
for disk_name in "${available_disks[@]}"; do
notice "writing grub to available disks:"
act "mount the primary disks efi partition under ${grub_mount}"
mount ${disk_path}/${disk_name}-part${efi_part_number} ${strapdir}${grub_mount}
cat <<-EOF | sudo tee ${strapdir}/update-grub_${disk_name} > /dev/null
#!/bin/sh
echo "populate the ${grub_mount} with update-grub."
grub-mkconfig -o ${grub_mount}/grub.cfg
echo "install grub-pc to ${disk_name}"
grub-install --target=i386-pc /dev/disk/by-id/${disk_name}
EOF
chroot-script -d update-grub_${disk_name} || { zerr; return 1; }
umount ${strapdir}${grub_mount}
done
fi
}