#/bin/sh # arch-create-system # https://github.com/rzerres/arch-create-vm # Copyright (C) 2019 Ralf Zerres # This program 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 2 of the License, or # (at your option) any later version. # This program 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 program; if not, write to the Free Software Foundation, Inc., # ------------------------------------------------------------------------- progname="${0##*/}" version="0.1.0" # global variables color=1 config_json="$progname.json" dryrun=0 quiet=0 verbose=0 # ascii color BLUE= GREEN= MAGENTA= RED= YELLOW= NO_COLOR= ### # Functions ### echo () { printf %s\\n "$*" ; } check_prerequisites () { # requested binaries: which chattr >/dev/null 2>&1 || { printf "'chattr' is not installed." && exit 1; } which btrfs >/dev/null 2>&1 || { printf "'btrfs' is not installed." && exit 1; } which fallocate >/dev/null 2>&1 || { printf "'findmnt' is not installed." && exit 1; } which gawk >/dev/null 2>&1 || { printf "'gawk' is not installed." && exit 1; } which mkfs >/dev/null 2>&1 || { printf "'mkfs' is not installed." && exit 1; } which mkswap >/dev/null 2>&1 || { printf "'mkswap' is not installed." && exit 1; } which mount >/dev/null 2>&1 || { printf "'mount' is not installed." && exit 1; } which pacman >/dev/null 2>&1 || { printf "'pacman' is not installed." && exit 1; } which pacstrap >/dev/null 2>&1 || { printf "'pacstrap' is not installed." && exit 1; } which sed >/dev/null 2>&1 || { printf "'sed' is not installed." && exit 1; } which sgdisk >/dev/null 2>&1 || { printf "'sgdisk' is not installed." && exit 1; } which umount >/dev/null 2>&1 || { printf "'umount' is not installed." && exit 1; } if [ $(id -u) -ne 0 ] ; then printf "$progname: must be run as root\n" ; exit 1 ; fi } create_bootloader () { cmd="bootctl --path=boot install" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi cmd="bootctl status" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi } create_btrfs () { local LABEL=$1 local PREFIX=${2:-BTRFS} local MOUNT_POINT=$3 if [ $dryrun -eq 1 ]; then printf "${BLUE}Would prepare filesystem ${GREEN}'%s'${NO_COLOR}\n" \ "$LABEL" else printf "${BLUE}Prepare filesystem ${GREEN}'%s'${NO_COLOR}\n" \ "$LABEL" fi if [ -h /dev/disk/by-partlabel/$LABEL ]; then # create filesystem cmd="mkfs -t btrfs --force \ --label $PREFIX-$LABEL \ --data single \ --metadata single \ /dev/disk/by-partlabel/$LABEL" cmd=`echo $cmd | tr -s "[:blank:]"` if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" \ "$cmd" else eval "$cmd" fi if [ ! -d $MOUNT_POINT ]; then cmd="mkdir -p $MOUNT_POINT" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" \ "$cmd" else eval "$cmd" fi fi fi } create_disk () { local TARGET=$1 local LABEL=$2 local PREFIX=$3 local NR_PARTITIONS=${4:-1} local MOUNT_TARGET=/mnt local SGDISK="/usr/bin/sgdisk" local PARTITION=1 # test if block-device is available test -b $TARGET || exit 1 printf "${BLUE}Prepare disc ${GREEN}'%s'${NO_COLOR}\n" "$TARGET" # Cleanup disk and create GPT-Partition cmd="sgdisk --zap-all $TARGET" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi while expr $PARTITION '<=' $NR_PARTITIONS >>/dev/null; do if [ $PARTITION '=' 1 ] && [ $NR_PARTITIONS '>' 1 ]; then if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would create ${GREEN}UEFI-Partition '%s'${NO_COLOR}\n" $PARTITION else # create UEFI partitions sgdisk --new=$PARTITION:2048:+512M $TARGET # assign label sgdisk --change-name=$PARTITION:$label_uefi $TARGET # adapt partition-type sgdisk --typecode=$PARTITION:EF00 $TARGET fi PARTITION=$(expr $PARTITION + 1) continue else if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would create ${GREEN}OS-Partition '%s'${NO_COLOR}\n" $PARTITION else # create partitions sgdisk --new=$PARTITION $TARGET # assign label sgdisk --change-name=$PARTITION:${LABEL} $TARGET # adapt partition-type sgdisk --typecode=$PARTITION:8300 $TARGET fi PARTITION=$(expr $PARTITION + 1) fi done # dump settings cmd="sgdisk -p $TARGET" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would print created partition table for target ${GREEN}'%s'${NO_COLOR}\n" $TARGET else eval "$cmd" fi } create_fs_structure () { local LABEL=$1 local PREFIX=${2:-BTRFS} local MOUNT_POINT=$3 local SUBVOL=$4 printf "${BLUE}Prepare filesystem structure${GREEN}'subvol=%s'${NO_COLOR}\n" \ "$SUBVOL" cmd="mount_target $MOUNT_POINT /dev/disk/by-partlabel/$LABEL btrfs $SUBVOL" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi if [ $LABEL="OS" ]; then printf "${BLUE}Create target filesystem structure${NO_COLOR}\n" cmd="mkdir -p $MOUNT_POINT/var/lib" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi for subdir in log cache; do cmd="btrfs subvolume create $MOUNT_POINT/var/$subdir" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi done # Subvolumes storing custom data printf "${BLUE} - Create btrfs subvolumes${NO_COLOR}\n" for subvol in boot root home data var/lib/machines; do cmd="btrfs subvolume create $MOUNT_POINT/$subvol" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" \ "$cmd" else eval "$cmd" fi done create_swapfs $PREFIX $MOUNT_POINT fi cmd="umount $MOUNT_POINT" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi } create_network_stack () { systemctl enable systemd-networkd systemctl enable systemd-resolved rm /etc/resolv.conf ln -s /run/systemd/resolve/resolv.con /etc/resolv.conf systemctl enable dropbear.service } create_swapfs () { local PREFIX=$1 local MOUNT_POINT=$2 printf "${BLUE}Create target swapfs${NO_COLOR}\n" # create a subvolume for the swapfs file cmd="btrfs subvol create $MOUNT_POINT/swap" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi # Disable COW functionality for Subvolume swap cmd="chattr +C $MOUNT_POINT/swap" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" chmod 0700 $MOUNT_POINT/swap fi # prepare the swapfile (size: 2x RAM) RamSize=`cat /proc/meminfo | gawk 'NR==1 {print $2}'` SwapSize=$(expr 2 '*' $RamSize) SwapFile=$MOUNT_POINT/swap/swapfile cmd="fallocate --length $SwapSize $SwapFile" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else touch $SwapFile chmod 0600 $SwapFile eval "$cmd" fi # create the swap filesystem cmd="mkswap --label $PREFIX-Swap $SwapFile" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi } create_fat () { local LABEL=$1 local PREFIX=${2:-BTRFS} local MOUNT_POINT=$3 if [ $dryrun -eq 1 ]; then printf "${BLUE}Would prepare filesystem ${GREEN}'%s'${NO_COLOR}\n" "$LABEL" else printf "${BLUE}Prepare filesystem ${GREEN}'%s'${NO_COLOR}\n" "$LABEL" fi if [ -h /dev/disk/by-partlabel/$LABEL ]; then # create filesystem cmd="mkfs -t fat \ -F 32 \ -n $LABEL \ /dev/disk/by-partlabel/$LABEL" cmd=`echo $cmd | tr -s "[:blank:]"` if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi fi } create_vfat () { local LABEL=$1 local PREFIX=${2:-BTRFS} local MOUNT_POINT=$3 if [ $dryrun -eq 1 ]; then printf "${BLUE}Would prepare filesystem ${GREEN}'%s'${NO_COLOR}\n" "$LABEL" else printf "${BLUE}Prepare filesystem ${GREEN}'%s'${NO_COLOR}\n" "$LABEL" fi if [ -h /dev/disk/by-partlabel/$LABEL ]; then # create filesystem cmd="mkfs -t vfat \ -n $PREFIX-$LABEL \ /dev/disk/by-partlabel/$LABEL" cmd=`echo $cmd | tr -s "[:blank:]"` if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi fi } die () { error "$@" exit 1 } error () { printf "\n==> ERROR: %s\n" "$@" } >&2 get_config_name () { local config_json=${configfile:-$config_json} local disk_name=${1} if [ $verbose -ge 1 ]; then printf "${BLUE}get_config_name ...${NO_COLOR}\n" fi if test ! -r ${config_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} config file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}\n" \ "config_json" fi exit 1 fi cmd="jq --monochrome-output --ascii-output ' .ConfigEnvironment[] \ | .ConfigName as \$MediaPoolName \ | .Disk[].DiskName \ | select(. == \"${disk_name}\") \ | \$ConfigName' ${config_json}" cmd="jq --monochrome-output --ascii-output ' .ConfigEnvironment[] \ | .ConfigName ' \ ${config_json}" config_names=$(eval $cmd) config_names=$(echo $config_names | sed -e 's/\n//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}Config environment names: ${GREEN}'%s'${NO_COLOR}\n" \ "$config_names" fi } get_config_names () { local config_json=${configfile:-$config_json} if [ $verbose -ge 1 ]; then printf "${BLUE}get_config_names ...${NO_COLOR}\n" fi if [ ! -r ${config_json} ]; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} config file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}\n" \ "config_json" fi exit 1 fi cmd="jq --monochrome-output --ascii-output ' .ConfigEnvironment[] \ | .ConfigName ' \ ${config_json}" config_names=$(eval $cmd) config_names=$(echo $config_names | sed -e 's/\n//g') } get_config_disk_names () { local config_json=${config_file:-$config_json} if [ $verbose -ge 1 ]; then printf "${BLUE}get_config_disk_names ...${NO_COLOR}\n" fi if test ! -r ${config_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} config file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}\n" \ "config_json" fi return 1 fi cmd="jq --monochrome-output --ascii-output '.ConfigEnvironment[] \ | select(.ConfigName == \"${config_name}\") \ | .Disk[].DiskName' \ ${config_json}" disk_names=$(eval $cmd) disk_names=$(echo $disk_names | sed -e 's/["\n]//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}Disks in config environment ${GREEN}'%s'${MAGENTA} are: ${NO_COLOR}%s${NO_COLOR}\n" \ "$config_name" "$disk_names" fi if [ $verbose -ge 2 ]; then i=1 for disk in $disk_names; do printf "${MAGENTA}Disk ${GREEN}'%d'${MAGENTA} with name ${GREEN}'%s'${NO_COLOR}\n" \ "$i" "$disk" i=$(expr $i + 1) done fi } mount_target_filesytems () { local LABEL=$1 local MOUNT_POINT=$2 printf "${BLUE}Install target system ${GREEN}'%s' -> '%s'${NO_COLOR}\n" "$LABEL" "$MOUNT_POINT" mount_target $MOUNT_POINT /dev/disk/by-partlabel/$LABEL btrfs root for subdir in boot data home swap var/log var/cache var/lib/machines; do mkdir -p $MOUNT_POINT/$subdir done mount_target $MOUNT_POINT/var/cache /dev/disk/by-partlabel/$LABEL btrfs var/cache mount_target $MOUNT_POINT/var/log /dev/disk/by-partlabel/$LABEL btrfs var/log mount_target $MOUNT_POINT/boot /dev/disk/by-partlabel/$label_uefi fat mount_target $MOUNT_POINT/var/lib/machines /dev/disk/by-partlabel/$label_machines btrfs / mount_target $MOUNT_POINT/data /dev/disk/by-partlabel/$label_data btrfs / # change new root to target cmd="arch-chroot $MOUNT_POINT install_target" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi } install_target () { local LABEL=$1 printf "${BLUE}Install target system ${GREEN}'%s' -> '%s'${NO_COLOR}\n" "$LABEL" "$MOUNT_POINT" # Update available packages cmd="pacman -Sy" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi # Basic packages cmd="pacstrap $MOUNT_POINT arch-install-scripts base btrfs-progs intel-ucode linux linux-firmware dosfstools iptables-nft man sudo" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi # Hyper-V packages cmd="pacstrap $MOUNT_POINT hyperv" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi # SSH-Daemon, FileManager and Editor cmd="pacstrap $MOUNT_POINT dropbear vim mc bash-completion n" if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi prepare_network_stack create_network_stack prepare_bootloader create_bootloader prepare_locale $label_prefix #systemctl enable hvkvpdaemon.service #systemctl enable hvvssdaemon.service genfstab / >/etc/fstab } mount_target () { local MOUNT_POINT=$1 local DEV_NAME=$2 local FS_TYPE=$3 local FS_SUBVOL=$4 case $FS_TYPE in "btrfs") if [ -h $DEV_NAME ]; then cmd="mount -t $FS_TYPE \ -o subvol=$FS_SUBVOL \ $DEV_NAME \ $MOUNT_POINT" printf "${BLUE}mounting subvol ${GREEN}'%s' ${BLUE}of ${GREEN}'%s' ${BLUE}at ${GREEN}'%s${NO_COLOR}\n" \ "$FS_SUBVOL" "$DEV_NAME" "$MOUNT_POINT" fi ;; "vfat") if [ -h $DEV_NAME ]; then cmd="mount -t $FS_TYPE \ $DEV_NAME \ $MOUNT_POINT" printf "${BLUE}mounting ${GREEN}'%s' ${BLUE}at ${GREEN}'%s${NO_COLOR}\n" \ "$DEV_NAME" "$MOUNT_POINT" fi ;; esac cmd=`echo $cmd | tr -s "[:blank:]"` if [ $dryrun -eq 1 ]; then printf "${MAGENTA}Would run ${GREEN}'%s'${NO_COLOR}\n" "$cmd" else eval "$cmd" fi } parse_params () { #printf "\n${BLUE}Parse arguments...${NO_COLOR}\n" # Evaluate given call parameters i=0 while [ $# -gt 0 ]; do key="$1" case $key in -h | --help | \-\? | --usage) # Call usage() function. usage ;; --color) color=1 shift 1 ;; -c | --config) config_json="$2" shift 2 ;; --get-config-name) shift 1 config_params=${*} config_params="${config_params%% -?[a-z-]*}" params=$* set -- $config_params cmd=get-config-name ;; --get-config-names) shift 1 config_params=${*} config_params="${config_params%% -?[a-z])*}" set -- $config_params cmd=get-config-names ;; --get-config-disk-names) shift 1 config_params=${*} config_params="${config_params%% -?[a-z]*}" params=$* set -- "$config_params" count=$# test $count -lt 1 && printf "missing argument: config_name\n" && exit 1 test $count -ge 1 && config_name="$1" #test $count -ge 2 && disk_name="$2" set -- $params shift $count cmd=get-config-disk-names ;; --dry-run|--dryrun) dryrun=1 shift 1 ;; --mountpoint|--MOUNTPOINT) mount_point="$2" shift 2 ;; --labelprefix) label_prefix="$2" shift 2 ;; --label_data) label_data="$2" shift 2 ;; --target_data) target_data="$2" shift 2 ;; --target_machines) target_machines="$2" shift 2 ;; --target_os) target_os="$2" shift 2 ;; --target_machines|--target_machines) target_machines="$2" shift 2 ;; --target_os|--target_os) target_os="$2" shift 2 ;; -v|--verbose) verbose=$(expr $verbose '+' 1) shift 1 ;; --version) printf "%s v%s\n" "$progname" "$version" exit 0 ;; --color=*) case ${1#*=} in yes | Yes | True | true) color=1; ;; *) ;; esac shift ;; --c=* | --config=*) config_json=${1#*=} shift ;; --mountpoint=*) mount_point=${1#*=} shift ;; --labelprefix=*) label_prefix=${1#*=} shift ;; --label_data=*|--LABEL_DATA=*) label_data=${1#*=} shift ;; --label_machines=*|--LABEL_MACHINES=*) label_machines=${1#*=} shift ;; --label_os=*|--LABEL_OS=*) label_os=${1#*=} shift ;; --target_data=*|--TARGET_DATA=*) target_data=${1#*=} shift ;; --target_machines=*|--TARGET_MACHINES=*) target_machines=${1#*=} shift ;; --target_os=*|--TARGET_OS=*) target_os=${1#*=} shift ;; --v=* | --verbose=*) verbose=${1#*=} shift ;; --) # End of all options shift break ;; -*) printf "WARN: Unknown option (ignored): $1" >&2 die "Unknown option" ;; *) printf "Unknown option: %s\nRun '%s -h' for valid options.\n" $key $progname die "Unknown option" ;; esac done # check if config is accessible in given path for config in ${config_json} ./${config_json} ${HOME}/${config_json} /etc/${progname}/${config_json}; do if [ -r $config ] ; then config_json=$config break else config_json="NONE" fi done if [ ${config_json} = "NONE" ]; then if [ $verbose -ge 1 ]; then printf "${BLUE}No config file accessible!${NO_COLOR}\n" \ # printf "${RED}Error:${MAGENTA} config file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}\n" \ # "$config_json" fi #exit 1 fi target_os=${target_os:-"/dev/sda"} mount_point=${mount_point:-"/mnt"} label_prefix=${label_prefix:-"BTRFS"} label_os=${label_os:-"OS"} label_machines=${label_machines:-"MACHINES"} label_data=${label_data:-"DATA"} label_uefi=${label_uefi:-"UEFI"} if [ $verbose -eq 0 ]; then quiet=1; fi if [ "$color" ]; then # ascii color BLUE='\033[0;34m' GREEN='\033[0;32m' MAGENTA='\033[0;35m' RED='\033[0;31m' YELLOW='\033[0;33m' NO_COLOR='\033[0m' fi if [ $verbose -ge 1 ]; then printf "${BLUE}$progname (runtime arguments)...${NO_COLOR}\n" i=0 printf "using parameters:\n" printf " Config File: '%s'\n" "$config_json" printf " TARGET OS: '%s'\n" "$target_os" printf " Mount Point: '%s'\n" "$mount_point" printf " TARGET Machines: '%s'\n" "$target_machines" printf " TARGET DATA: '%s'\n" "$target_data" printf " Label Prefix: '%s'\n" "$label_prefix" printf " Label OS: '%s'\n" "$label_os" printf " Label Machines: '%s'\n" "$label_machines" printf " Label DATA: '%s'\n" "$label_data" printf " Label UEFI: '%s'\n" "$label_uefi" if [ $verbose -ge 2 ]; then options="verbose_level=$verbose"; fi if [ $dryrun -ge 1 ]; then options="${options}dryrun=true"; fi if [ $color -ge 1 ]; then options="${options} color=true"; fi printf "Options: '%s'\n\n" "${options}" fi } prepare_bootloader () { # check for accessible uefi partition ls /sys/firmware/efi/efivars > /dev/null if [ $? -eq 0 ]; then printf "UEFI Environmint is ok'\n" mkdir -p /boot/loader/entries printf '%s\n' \ "default arch" \ "timeout 3" \ "editor yes" \ "console-mode max" \ > /boot/loader/loader.conf printf '%s\n' \ "default arch" \ "title Arch Linux (Mainline)" \ "linux /vmlinuz-linux" \ "initrd /intel-ucode.img" \ "initrd /initramfs-linux.img" \ "options rootflags=subvol=root root=LABEL=BTRFS-OS" \ > /boot/loader/entries/arch.conf bootctl status fi } prepare_locale () { local LABEL=$1 hostnamectl set-hostname $LABEL-lin01 localectl set-keymap de-latin1-nodeadkeys } prepare_network_stack () { printf '%s\n' \ "[Match]" \ "Name=eth0" \ "" \ "[Network]" \ "Description=Slave Bridge-Interface" \ "Bridge=bridge-lan" \ > /etc/systemd/network/70-eth0-bridge-slave.netdev printf '%s\n' \ "[Match]" \ "#Host=Lin01" \ "#Architecture=x86_64" \ "" \ "[NetDev]" \ "Description=Bridge for Containers" \ "Name=bridge-lan" \ "Kind=bridge" \ > /etc/systemd/network/80-bridge-lan.netdev printf '%s\n' \ "[Match]" \ "Name=bridge-lan" \ "Driver=bridge" \ "" \ "[Network]" \ "Description=Bridge for Containers" \ "IPForward=yes" \ "IPMasquerqade=yes" \ "LinkLocalAddressisng=yes" \ "IPv6AcceptRA=yes" \ "IgnoreCarrierLoss=yes" \ > /etc/systemd/network/80-bridge-lan.network } prepare_target_disks () { create_disk ${target_os} $label_os $label_prefix 2 create_disk ${target_machines} $label_machines $label_prefix create_disk ${target_data} $label_data $label_prefix } prepare_target_filesystems () { create_fat $label_uefi $label_prefix $mount_point create_btrfs $label_os $label_prefix $mount_point create_btrfs $label_machines $label_prefix $mount_point create_btrfs $label_data $label_prefix $mount_point create_fs_structure $label_os $label_prefix $mount_point / } usage () { cat < Specify the partion label prefix -t, --target_os Specify the blockdevice for the target OS (e.g /dev/sda) --target_machines Specify the blockdevice for containers/machines (e.g /dev/sdb) --target_data Specify the blockdevice to store data (e.g /dev/sdc) -v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3) --version show program version EOF exit 0 } ### # Main ### # can't be ported to dash (ERR is not supported) #trap 'traperror ${LINENO} $? "$BASH_COMMAND" $BASH_LINENO "${FUNCNAME[@]}"' ERR trap trapkill TERM INT check_prerequisites # validate commandline options, set resonable defaults parse_params $@ #get_config case $cmd in get-config-name) get_config_name if test $? -gt 0; then exit 1 else if [ $quiet -eq 0 ]; then printf "${MAGENTA}Config Environment: ${GREEN}'%s'${NO_COLOR}\n" \ "${config_name}" fi fi ;; get-config-names) get_config_names if [ $? -gt 0 ]; then exit 1 else if [ $quiet -eq 0 ]; then printf "${MAGENTA}Config environment names: ${GREEN}'%s'${NO_COLOR}\n" \ "${config_names}" fi fi ;; get-config-disk-names) valid_member=0 get_config_disk_names "${config_name}" "${disk_name}" if [ $? -gt 0 ]; then exit 1 else if [ $quiet = 0 ]; then printf "Config environment ${GREEN}'%s'${NO_COLOR} with disks: ${GREEN}'%s'${NO_COLOR}\n" \ "${config_name}" "${disk_names}" fi valid_member=${#disk_names} fi ;; get-config-partition_names) ;; esac exit 0 # prepare target prepare_target_disks prepare_target_filesystems mount_target_filesystems #install_target OS $mount_point