diff options
author | bill-auger <mr.j.spam.me@gmail.com> | 2023-08-16 13:58:08 -0400 |
---|---|---|
committer | bill-auger <mr.j.spam.me@gmail.com> | 2023-08-17 21:20:52 -0400 |
commit | 32078c3bfac9cb7d46dafb814a385efbd993da3e (patch) | |
tree | d839fd571c1ac92b5080049a0e092bbd8ed52865 | |
parent | 8bc826fb0d662204c98517a4b2968447c3af44bd (diff) |
-rw-r--r-- | src/pvm-common.sh.inc | 57 | ||||
-rwxr-xr-x | src/pvmbootstrap.sh | 277 |
2 files changed, 195 insertions, 139 deletions
diff --git a/src/pvm-common.sh.inc b/src/pvm-common.sh.inc index 6da7685..1e37408 100644 --- a/src/pvm-common.sh.inc +++ b/src/pvm-common.sh.inc @@ -1,23 +1,24 @@ #!/bin/bash -############################################################################### -# parabola-vmbootstrap -- create and start parabola virtual machines # -# # -# Copyright (C) 2017 - 2019 Andreas Grapentin # -# Copyright (C) 2019 - 2020 bill-auger # -# # -# 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 3 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, see <http://www.gnu.org/licenses/>. # -############################################################################### + +########################################################################### +# parabola-vmbootstrap -- create and start parabola virtual machines # +# # +# Copyright (C) 2017-2019 Andreas Grapentin # +# Copyright (C) 2019-2020,2023 bill-auger # +# # +# 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 3 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, see <http://www.gnu.org/licenses/>. # +########################################################################### # readonly DATA_IMG=./pvmdata.img # optional large qemu disk @@ -34,7 +35,7 @@ source "$(librelib messages)" pvm_get_script() # (script_name) { local script_name=$1 - local intree_script=$THIS_DIR/$script_name.sh + local intree_script="$THIS_DIR"/$script_name.sh local installed_script=$script_name [[ -f "$intree_script" ]] && echo "$intree_script" && return "$EXIT_SUCCESS" @@ -44,16 +45,18 @@ pvm_get_script() # (script_name) pvm_get_hook() # ( hook_name ) { - local hook_name=$1 - local intree_dir=$THIS_DIR/hooks + local hook_name="$1" + local intree_dir="$THIS_DIR"/hooks local installed_dir=/usr/lib/parabola-vmbootstrap local hook_filename=hook-$hook_name.sh - local locations=( "$intree_dir/$hook_filename" "$installed_dir/$hook_filename" "$hook_name" '' ) - local location + local paths=( "$intree_dir/$hook_filename" "$installed_dir/$hook_filename" "$hook_name" '' ) + local filename_warning="hook filenames must not contain spaces" + local hook path + + (( $# == 1 )) && [[ ! "$1" =~ ' ' ]] || ! warning "$filename_warning" || paths=() - for location in "${locations[@]}" ; do [[ -f "$location" ]] && break ; done ; - [[ "$location" ]] && echo "$location" || warning "no such hook: '%s'" "$hook_name" - [[ "$location" ]] && return "$EXIT_SUCCESS" || return "$EXIT_FAILURE" + hook="$(for path in "${paths[@]}" ; do ls "$hook" ; done | head -n 1 ;)" + [[ -f "$hook" ]] && echo "$hook" || ! warning "no such hook: '%s'" "$hook_name" } pvm_find_part_n() # ( imagefile fs_types ) , sets: $part_n diff --git a/src/pvmbootstrap.sh b/src/pvmbootstrap.sh index 16ce955..8ca2ad8 100755 --- a/src/pvmbootstrap.sh +++ b/src/pvmbootstrap.sh @@ -1,58 +1,65 @@ #!/bin/bash -############################################################################### -# parabola-vmbootstrap -- create and start parabola virtual machines # -# # -# Copyright (C) 2017 - 2019 Andreas Grapentin # -# Copyright (C) 2019 - 2020 bill-auger # -# # -# 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 3 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, see <http://www.gnu.org/licenses/>. # -############################################################################### + +########################################################################### +# parabola-vmbootstrap -- create and start parabola virtual machines # +# # +# Copyright (C) 2017-2020 Andreas Grapentin # +# Copyright (C) 2019-2020,2023 bill-auger # +# # +# 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 3 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, see <http://www.gnu.org/licenses/>. # +########################################################################### # defaults -readonly PKG_SET_MIN='minimal' -readonly PKG_SET_STD='standard' -readonly PKG_SET_DEV='devel' ; readonly DEF_PKG_SET=$PKG_SET_STD ; -readonly MIN_PKGS=('base' ) ; readonly ROOT_MB_MIN=1125 ; # 841 (pacstrap) -readonly STD_PKGS=('base' 'parabola-base' ) ; readonly ROOT_MB_STD=1250 ; # 898 (pacstrap) -readonly DEV_PKGS=('base' 'parabola-base' 'base-devel') ; readonly ROOT_MB_DEV=1500 ; # 1163 (pacstrap) -readonly DEF_PKGS=(${STD_PKGS[@]} ) ; readonly DEF_MIN_MB=$ROOT_MB_STD ; -readonly DEF_KERNEL='linux-libre' # ASSERT: must be 'linux-libre', per 'parabola-base' +readonly PKG_SET_MIN=minimal +readonly PKG_SET_STD=standard +readonly PKG_SET_DEV=devel ; readonly DEF_PKG_SET=$PKG_SET_STD ; +readonly MIN_PKGS=( base ) ; readonly ROOT_MB_MIN=1125 ; # 841 (pacstrap) +readonly STD_PKGS=( base parabola-base ) ; readonly ROOT_MB_STD=1250 ; # 898 (pacstrap) +readonly DEV_PKGS=( base parabola-base base-devel ) ; readonly ROOT_MB_DEV=1500 ; # 1163 (pacstrap) +readonly DEF_PKGS=( ${STD_PKGS[*]} ) ; readonly DEF_MIN_MB=$ROOT_MB_STD ; +readonly DEF_KERNEL=linux-libre # ASSERT: must be 'linux-libre', per 'parabola-base' readonly DEF_MIRROR=https://repo.parabola.nu readonly DEF_ROOT_MB=32000 readonly DEF_BOOT_MB=150 readonly DEF_SWAP_MB=0 -readonly PKGS_MANDATORY_ALL=( ) -readonly PKGS_MANDATORY_armv7h=( haveged net-tools ) -readonly PKGS_MANDATORY_i686=( haveged net-tools grub ) -readonly PKGS_MANDATORY_ppc64le=( haveged net-tools ) -readonly PKGS_MANDATORY_riscv64=( ) -readonly PKGS_MANDATORY_x86_64=( haveged net-tools grub ) - -# misc -readonly PKGS_GUEST_CACHED=('ca-certificates-utils') +readonly PKGS_ALL=( haveged net-tools ) +readonly PKGS_armv7h=( ) +readonly PKGS_i686=( grub ) +readonly PKGS_ppc64le=( ) +readonly PKGS_riscv64=( ) +readonly PKGS_x86_64=( grub ) + +# misc constants +readonly PKGS_NETWORKING=( dhcpcd ) +readonly PKGS_NONSYSTEMD=( libelogind ) # resolve conflicts in 'nonsystemd/base' +readonly PKGS_GUEST_CACHED=( ca-certificates-utils ) +readonly REPOS_STANDARD=( libre core extra ) +readonly REPOS_NONSYSTEMD=( nonsystemd ) +readonly CACHE_DIR=/var/cache/pacman/pkg # in-chroot readonly PVM_HOOKS_SUCCESS_MSG="[hooks.sh] pre-init hooks successful" -# options + +# options (over-ride defaults per CLI args) BasePkgSet=$DEF_PKG_SET MinRootMb=$DEF_MIN_MB Hooks=() -Kernels=($DEF_KERNEL) +Kernels=( $DEF_KERNEL ) Mirror=$DEF_MIRROR IsNonsystemd=0 -Pkgs=(${DEF_PKGS[@]}) -PkgsCached=(${PKGS_GUEST_CACHED[@]}) +Pkgs=( ${DEF_PKGS[*]} ) +PkgsCached=( ${PKGS_GUEST_CACHED[*]} ) PkgsOptional=() RootSizeMb=$DEF_ROOT_MB BootSizeMb=$DEF_BOOT_MB @@ -93,7 +100,7 @@ usage() echo " (default: $DEF_MIRROR)" echo " -O Bootstrap an openrc system instead of a systemd one" echo " NOTE: This option is currently ignored; because" - echo " the 'preinit' hook is implemented as a systemd service." + echo " the 'pre-init' hook is implemented as a systemd service." echo " -p <package> Specify an additional package to be installed in the image." echo " This option can be specified multiple times;" echo " but note that these will be ignored if -s <root_size> is 0." @@ -177,6 +184,7 @@ pvm_bootstrap() # assumes: $arch $imagefile $loopdev $workdir , traps: INT TERM i686|x86_64 ) boot_mkfs_cmd='mkfs.ext2' ;; ppc64le|riscv64) boot_mkfs_cmd='mkfs.ext2' ;; esac + msg "creating target filesystems" sudo $boot_mkfs_cmd "$boot_loopdev" || return "$EXIT_FAILURE" ! (( $HasSwap )) || \ @@ -213,19 +221,24 @@ pvm_bootstrap() # assumes: $arch $imagefile $loopdev $workdir , traps: INT TERM # prepare pacstrap config local pacconf="$(mktemp -t pvm-pacconf-XXXXXXXXXX)" || return "$EXIT_FAILURE" - local repos=(libre core extra community pcr) - (( $IsNonsystemd )) && repos=('nonsystemd' ${repos[@]}) - echo -e "[options]\nArchitecture = $arch" > "$pacconf" - for repo in ${repos[@]}; do echo "[$repo]" >> "$pacconf"; - for mirror_n in {1..5}; do echo "Server = $Mirror/\$repo/os/\$arch" >> "$pacconf"; done; + local repos=( ${REPOS_STANDARD[*]} $((( $IsNonsystemd )) && echo ${REPOS_NONSYSTEMD[*]}) ) + echo -e "[options]\nArchitecture = $arch" > "$pacconf" + for repo in ${repos[*]} ; do echo "[$repo]" >> "$pacconf" ; + for n in {1..5} ; do echo "Server = $Mirror/\$repo/os/\$arch" >> "$pacconf" ; done ; done # pacstrap! :) - msg "installing packages into the work chroot" - sudo pacstrap -GMc -C "$pacconf" "$workdir" "${Pkgs[@]}" || return "$EXIT_FAILURE" - sudo pacman -Sw --config "$pacconf" --root "$workdir" \ - --cachedir "$workdir"/var/cache/pacman/pkg --noconfirm \ - "${PkgsCached[@]}" || return "$EXIT_FAILURE" + local pacstrap_msg="installing (${#Pkgs[*]}) packages into the work chroot:" + local cache_msg="caching (${#PkgsCached[*]}) packages into the work chroot:" + local cachedir="$workdir/$CACHE_DIR" + msg "$pacstrap_msg" ; prose "${Pkgs[*]}" ; + sudo pacstrap -GMc -C "$pacconf" "$workdir" ${Pkgs[*]} || return "$EXIT_FAILURE" + if (( ${#PkgsCached[*]} )) + then msg2 "${cache_msg}" ; prose "${PkgsCached[*]}" ; + sudo pacman -S --config "$pacconf" --downloadonly \ + --root "$workdir" --cachedir "$cachedir" \ + --noconfirm ${PkgsCached[*]} || return "$EXIT_FAILURE" + fi # generate list of installed packages msg2 "generating a list of installed packages" @@ -288,7 +301,7 @@ pvm_bootstrap() # assumes: $arch $imagefile $loopdev $workdir , traps: INT TERM esac # regenerate the initcpio(s), to skip the 'autodetect' hook - for kernel in ${Kernels[@]} + for kernel in ${Kernels[*]} do local preset_file="$workdir"/etc/mkinitcpio.d/${kernel}.preset local default_options="default_options=\"-S autodetect\"" @@ -304,15 +317,17 @@ pvm_bootstrap() # assumes: $arch $imagefile $loopdev $workdir , traps: INT TERM done # initialize the pacman keyring + local keyrings=( $(for pkg in ${Pkgs[*]} ; + do [[ "$pkg" =~ -keyring$ ]] && echo ${pkg%-keyring} ; + done) ) msg "initializing the pacman keyring" sudo arch-chroot "$workdir" pacman-key --init - sudo arch-chroot "$workdir" pacman-key --populate archlinux archlinux32 archlinuxarm parabola + sudo arch-chroot "$workdir" pacman-key --populate ${keyrings[*]} # push hooks into the image msg "preparing hooks" sudo mkdir -p "$workdir"/root/hooks - [ "${#Hooks[@]}" -eq 0 ] || sudo cp -v "${Hooks[@]}" "$workdir"/root/hooks/ - (( $IsNonsystemd )) && sudo rm "$workdir"/root/hooks/hook-ethernet-dhcp.sh # systemd-only hook + for hook in ${Hooks[@]} ; do sudo cp -v "$hook" "$workdir"/root/hooks/ ; done ; # create a master hook script msg2 "hooks.sh:" @@ -324,10 +339,17 @@ echo "[hooks.sh] boot successful - configuring ...." locale-gen # fix the mkinitcpio -for kernel in ${Kernels[@]} ; do mkinitcpio -p \$kernel ; done ; +for kernel in ${Kernels[*]} ; do mkinitcpio -p \$kernel ; done ; # fix ca-certificates -pacman -U --noconfirm /var/cache/pacman/pkg/ca-certificates-utils-*.pkg.tar.zst +certs_pkg=\$(ls ${CACHE_DIR}/ca-certificates-utils-*.pkg.tar.zst) +if [[ -f \$certs_pkg ]] +then pacman -U --noconfirm \$certs_pkg || + ! echo "[hooks.sh] ERROR: 'ca-certificates-utils' install failed" || + exit "$EXIT_FAILURE" +else echo "[hooks.sh] ERROR: could not find 'ca-certificates-utils' package" + exit "$EXIT_FAILURE" +fi # run the hooks shopt -s nullglob @@ -339,22 +361,25 @@ done shopt -u nullglob # clean up after yourself -systemctl disable preinit.service +systemctl disable pre-init.service +#rm -f /etc/init.d/pre-init # TODO: non-systemd hooks NYI rm -f /root/.bash_history rm -rf /root/hooks -rm -f /root/hooks.sh -rm -f /usr/lib/systemd/system/preinit.service -rm -f /var/cache/pacman/pkg/* +rm -f /root/hooks.sh # this file +rm -f /usr/lib/systemd/system/pre-init.service +rm -f $CACHE_DIR/* # report success :) echo "$PVM_HOOKS_SUCCESS_MSG - powering off" EOF # create a pre-init service to run the hooks - msg2 "preinit.service:" - sudo tee "$workdir"/usr/lib/systemd/system/preinit.service << 'EOF' + msg2 "pre-init.service:" + if (( IsNonsystemd )) + then ; + else sudo tee "$workdir"/usr/lib/systemd/system/pre-init.service << 'EOF' [Unit] -Description=Oneshot VM Preinit +Description=Oneshot VM Pre-init After=multi-user.target [Service] @@ -367,15 +392,19 @@ ExecStopPost=shutdown -r now [Install] WantedBy=multi-user.target EOF + fi # configure services msg "configuring services" - # disable audit - sudo arch-chroot "$workdir" systemctl mask systemd-journald-audit.socket - # enable the entropy daemon, to avoid stalling https - sudo arch-chroot "$workdir" systemctl enable haveged.service - # enable the pre-init service - sudo arch-chroot "$workdir" systemctl enable preinit.service || return "$EXIT_FAILURE" + if (( IsNonsystemd )) + then ; + else # disable audit + sudo arch-chroot "$workdir" systemctl mask systemd-journald-audit.socket + # enable the entropy daemon, to avoid stalling https + sudo arch-chroot "$workdir" systemctl enable haveged.service + # enable the pre-init service + sudo arch-chroot "$workdir" systemctl enable pre-init.service || return "$EXIT_FAILURE" + fi # unmount everything pvm_bootstrap_cleanup @@ -392,7 +421,7 @@ pvm_bootstrap_preinit() # assumes: $imagefile pvm_boot "$imagefile" | tee /dev/fd/3 | grep -q -F "$PVM_HOOKS_SUCCESS_MSG" local res=$? exec 3>&- - ! (( $res )) || error "%s: failed to complete preinit hooks" "$imagefile" + ! (( $res )) || error "%s: failed to complete pre-init hooks" "$imagefile" return $res } @@ -412,15 +441,20 @@ pvm_bootstrap_cleanup() # unsets: $pacconf , untraps: INT TERM RETURN main() # ( [cli_options] imagefile arch ) { + msg "validating build parameters" + pvm_check_unprivileged # exits on failure + + ## parse CLI args ## + # parse options while getopts 'b:hH:k:M:Op:s:S:' arg; do case "$arg" in b) case $OPTARG in - $PKG_SET_MIN) BasePkgSet=$OPTARG ; Pkgs=(${MIN_PKGS[@]}) ; MinRootMb=$ROOT_MB_MIN ;; - $PKG_SET_STD) BasePkgSet=$OPTARG ; Pkgs=(${STD_PKGS[@]}) ; MinRootMb=$ROOT_MB_STD ;; - $PKG_SET_DEV) BasePkgSet=$OPTARG ; Pkgs=(${DEV_PKGS[@]}) ; MinRootMb=$ROOT_MB_DEV ;; + $PKG_SET_MIN) BasePkgSet=$OPTARG ; Pkgs=(${MIN_PKGS[*]}) ; MinRootMb=$ROOT_MB_MIN ;; + $PKG_SET_STD) BasePkgSet=$OPTARG ; Pkgs=(${STD_PKGS[*]}) ; MinRootMb=$ROOT_MB_STD ;; + $PKG_SET_DEV) BasePkgSet=$OPTARG ; Pkgs=(${DEV_PKGS[*]}) ; MinRootMb=$ROOT_MB_DEV ;; * ) warning "invalid base set: %s" "$OPTARG" ;; esac ;; c) PkgsCached+=($OPTARG) ;; @@ -428,7 +462,7 @@ main() # ( [cli_options] imagefile arch ) H) Hooks+=( "$(pvm_get_hook $OPTARG)" ) ;; k) Kernels+=($OPTARG) ;; M) Mirror="$OPTARG" ;; - O) IsNonsystemd=0 ;; # TODO: + O) IsNonsystemd=0 ;; # TODO: non-systemd hooks NYI p) PkgsOptional+=($OPTARG) ;; s) RootSizeMb="$(sed 's|[^0-9]||g' <<<$OPTARG)" ;; S) SwapSizeMb="$(sed 's|[^0-9]||g' <<<$OPTARG)" ;; @@ -437,65 +471,84 @@ main() # ( [cli_options] imagefile arch ) done local shiftlen=$(( OPTIND - 1 )) shift $shiftlen + + # validate CLI args local imagefile="$1" local arch="$2" - (( $# < 2 )) && error "insufficient arguments" && usage >&2 && exit "$EXIT_INVALIDARGUMENT" + (( $# != 2 )) && error "insufficient arguments" && usage >&2 && exit "$EXIT_INVALIDARGUMENT" + case "$arch" in + i686|x86_64|armv7h) ;; + ppc64le|riscv64 ) warning "arch is experimental: %s" "$arch" ;; + * ) error "arch is unsupported: %s" "$arch" + exit "$EXIT_INVALIDARGUMENT" ;; + esac + + + ## calculate options-dependent config vars ## - # vaidate options and calculate options-dependent vars - (( $RootSizeMb > 0 )) && \ - (( $RootSizeMb < $MinRootMb )) && warning "specified root FS size too small - ignoring -c and -p packages" - (( $RootSizeMb < $MinRootMb )) && RootSizeMb=$MinRootMb PkgsCached=() PkgsOptional=() - RootSizeMb=$(( $RootSizeMb + (${#Kernels[@]} * 75) )) - ImgSizeMb=$(( $BootSizeMb + $SwapSizeMb + $RootSizeMb )) - HasSwap=$( (( $SwapSizeMb > 0 )) && echo 1 || echo 0 ) + # normalize target image filename + [[ -d "$imagefile" ]] && imagefile="$imagefile/parabola-$(date -I).img" + [[ "$imagefile" =~ \.img$ ]] || imagefile="$imagefile.img" + + # calculate target filesystem sizes + local n_extra_kernels=$((( ${#Kernels[*]} )) && echo ${#Kernels[*]} - 1 || echo 0) + MinBootMb=$(( MinBootMb + (n_extra_kernels * 75) )) + MinRootMb=$(( MinRootMb + (n_extra_kernels * 75) )) + local opt_msg="optimizing root FS size - ignoring -c and -p packages" + local warn_msg="specified root FS size too small - ignoring -c and -p packages" + (( RootSizeMb == 0 )) && msg2 "$opt_msg" || warning "$warn_msg" + (( BootSizeMb < MinBootMb )) && BootSizeMb=$MinBootMb + (( RootSizeMb < MinRootMb )) && RootSizeMb=$MinRootMb PkgsOptional=() && + PkgsCached=( ${PKGS_GUEST_CACHED[*]} ) + ImgSizeMb=$(( BootSizeMb + SwapSizeMb + RootSizeMb )) + HasSwap=$( echo $(( SwapSizeMb > 0 )) ) # prepare package lists - local kernels=( ${Kernels[@]} ) - local pkgs=( ${Pkgs[@]} ${Kernels[@]} ${PkgsOptional[@]} ${PKGS_MANDATORY_ALL[@]} ) - local pkgs_cached=( ${PkgsCached[@]} ) + local kernels=( ${Kernels[*]} ) + local pkgs=( ${Kernels[*]} ${Pkgs[*]} ${PkgsOptional[*]} \ + ${PKGS_ALL[*]} $(eval "echo \${PKGS_$arch[*]}") ) + local pkgs_cached=( ${PkgsCached[*]} ) + pkgs+=( archlinux-keyring parabola-keyring ) case "$arch" in - armv7h ) pkgs+=( ${PKGS_MANDATORY_armv7h[@]} ) ;; - i686 ) pkgs+=( ${PKGS_MANDATORY_i686[@]} ) ;; - ppc64le) pkgs+=( ${PKGS_MANDATORY_ppc64le[@]} ) ;; - riscv64) pkgs+=( ${PKGS_MANDATORY_riscv64[@]} ) ;; - x86_64 ) pkgs+=( ${PKGS_MANDATORY_x86_64[@]} ) ;; + armv7h) pkgs+=( archlinuxarm-keyring ) ;; + i686 ) pkgs+=( archlinux32-keyring ) ;; esac - (( $IsNonsystemd )) && [[ "$BasePkgSet" == "$PKG_SET_MIN" ]] && pkgs+=(libelogind) - (( ! $IsNonsystemd )) && [[ "${Hooks[@]}" =~ hook-ethernet-dhcp.sh ]] && pkgs+=(dhcpcd ) + (( IsNonsystemd )) && Hooks=( ${Hooks[*]/*ethernet-dhcp*/} ) # TODO: non-systemd hooks NYI + (( IsNonsystemd )) && pkgs+=( ${PKGS_NONSYSTEMD[*]} ) + [[ "${Hooks[@]}" =~ ethernet-dhcp ]] && pkgs+=( ${PKGS_NETWORKING[*]} ) # minimize package lists - local kernel ; local pkg ; Kernels=() ; Pkgs=() ; PkgsCached=() ; - for kernel in $(printf "%s\n" "${kernels[@]}" | sort -u) ; do Kernels+=($kernel) ; done ; - for pkg in $(printf "%s\n" "${pkgs[@]}" | sort -u) ; do Pkgs+=($pkg) ; done ; - for pkg in $(printf "%s\n" "${pkgs_cached[@]}" | sort -u) ; do PkgsCached+=($pkg) ; done ; + local kernel pkg ; Kernels=() ; Pkgs=() ; PkgsCached=() ; + for kernel in $(printf "%s\n" "${kernels[*]}" | sort -u) ; do Kernels+=($kernel) ; done ; + for pkg in $(printf "%s\n" "${pkgs[*]}" | sort -u) ; do Pkgs+=($pkg) ; done ; + for pkg in $(printf "%s\n" "${pkgs_cached[*]}" | sort -u) ; do PkgsCached+=($pkg) ; done ; - msg "making $arch image: $imagefile" - # determine if the target arch is supported - case "$arch" in - i686|x86_64|armv7h) ;; - ppc64le|riscv64 ) warning "arch is experimental: %s" "$arch" ;; - * ) error "arch is unsupported: %s" "$arch" - exit "$EXIT_INVALIDARGUMENT" ;; - esac + ## build ## + + msg "making $arch image (${ImgSizeMb}MB): $imagefile" # create the virtual machine + declare -i was_err=0 + local err_msg=" - renaming to $imagefile-failed.img" if pvm_bootstrap; then if pvm_bootstrap_preinit; then - msg "bootstrap complete for image: %s" "$imagefile" - exit "$EXIT_SUCCESS" + was_err="$EXIT_SUCCESS" ; msg "bootstrap complete" ; else - error "bootstrap complete, but preinit failed for image: %s" "$imagefile" - exit "$EXIT_FAILURE" + was_err="$EXIT_FAILURE" ; error "bootstrap complete, but pre-init failed$err_msg" ; fi else - error "bootstrap failed for image: %s" "$imagefile" - exit "$EXIT_FAILURE" + was_err="$EXIT_FAILURE" ; error "bootstrap failed$err_msg" ; fi + + # cleanup + (( ! was_err )) || mv "$imagefile" "$imagefile"-failed.img &> /dev/null + + return $was_err } -if source "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"/pvm-common.sh.inc 2> /dev/null || \ +if source "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"/pvm-common.sh.inc 2> /dev/null || source /usr/lib/parabola-vmbootstrap/pvm-common.sh.inc 2> /dev/null then main "$@" else echo "can not find pvm-common.sh.inc" && exit 1 |