housekeeping

This commit is contained in:
bill-auger 2019-12-19 00:15:37 -05:00
parent 164b5b98b9
commit 68fb5be67a
3 changed files with 155 additions and 175 deletions

@ -19,10 +19,10 @@
############################################################################### ###############################################################################
# shellcheck source=/usr/lib/libretools/messages.sh # shellcheck source=/usr/lib/libretools/messages.sh
. "$(librelib messages)" source "$(librelib messages)"
usage() { usage() {
print "usage: %s [-h] [-o FILE] IMG" "${0##*/}" print "USAGE: %s [-h] [-o FILE] IMG" "${0##*/}"
prose "Produce a parabola release tarball from IMG." prose "Produce a parabola release tarball from IMG."
echo echo
prose "IMG is expected to be a valid parabola image, ideally freshly bootstrapped prose "IMG is expected to be a valid parabola image, ideally freshly bootstrapped
@ -39,18 +39,18 @@ usage() {
} }
pvm_mount() { pvm_mount() {
if ! file "$1" | grep -q ' DOS/MBR '; then if ! file "$imagefile" | grep -q ' DOS/MBR '; then
error "%s: does not seem to be a raw qemu image." "$1" error "%s: does not seem to be a raw qemu image." "$imagefile"
return "$EXIT_FAILURE" return "$EXIT_FAILURE"
fi fi
trap 'pvm_umount' INT TERM EXIT trap 'pvm_umount' INT TERM EXIT
workdir="$(mktemp -d -t pvm-XXXXXXXXXX)" || return workdir="$(mktemp -d -t pvm-XXXXXXXXXX)" || return
loopdev="$(sudo losetup -fLP --show "$1")" || return loopdev="$(sudo losetup -fLP --show "$imagefile")" || return
# find the root partition # find the root partition
local part rootpart local part rootpart bootpart
for part in "$loopdev"p*; do for part in "$loopdev"p*; do
sudo mount "$part" "$workdir" || continue sudo mount "$part" "$workdir" || continue
if [ -f "$workdir"/etc/fstab ]; then if [ -f "$workdir"/etc/fstab ]; then
@ -61,7 +61,7 @@ pvm_mount() {
done done
if [ -z "$rootpart" ]; then if [ -z "$rootpart" ]; then
error "%s: unable to determine root partition." "$1" error "%s: unable to determine root partition." "$imagefile"
return "$EXIT_FAILURE" return "$EXIT_FAILURE"
fi fi
@ -69,7 +69,7 @@ pvm_mount() {
bootpart="$(findmnt -senF "$workdir"/etc/fstab /boot | awk '{print $2}')" bootpart="$(findmnt -senF "$workdir"/etc/fstab /boot | awk '{print $2}')"
if [ -z "$bootpart" ]; then if [ -z "$bootpart" ]; then
error "%s: unable to determine boot partition." "$1" error "%s: unable to determine boot partition." "$imagefile"
return "$EXIT_FAILURE" return "$EXIT_FAILURE"
fi fi
@ -105,8 +105,8 @@ main() {
shift $shiftlen shift $shiftlen
if [ "$#" -ne 1 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi if [ "$#" -ne 1 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi
local imagebase imagefile="$1" local image_filename imagefile="$1"
imagebase="$(basename "$imagefile")" image_filename="$(basename "$imagefile")"
shift shift
# check for input file presence # check for input file presence
@ -116,7 +116,7 @@ main() {
fi fi
# determine output file # determine output file
[ -n "$output" ] || output="${imagebase%.*}.tar.gz" [ -n "$output" ] || output="${image_filename%.img*}.tar.gz"
# check for output file presence # check for output file presence
if [ -e "$output" ]; then if [ -e "$output" ]; then
@ -131,9 +131,15 @@ main() {
# mount the root filesystem # mount the root filesystem
local workdir loopdev local workdir loopdev
pvm_mount "$imagefile" || exit pvm_mount || exit
# tar the root filesystem, excluding unneeded things # tar the root filesystem, excluding unneeded things
# HACKING:
# to update the exclude list, one can download the latest archlinuxarm
# release tarball, and scroll over the diff generated by running both the
# archlinuxarm and the generated parabola tarball through:
#
# `tar -tf <tarball> | sort`
sudo tar -c -f "$output" -C "$workdir" -X - . << EOF sudo tar -c -f "$output" -C "$workdir" -X - . << EOF
./boot/lost+found ./boot/lost+found
./etc/.updated ./etc/.updated
@ -146,13 +152,6 @@ main() {
./var/log/tallylog ./var/log/tallylog
EOF EOF
# HACKING:
# to update the exclude list above, one can download the latest archlinuxarm
# release tarball, and scroll over the diff generated by running both the
# archlinuxarm and the generated parabola tarball through:
#
# `tar -tf <tarball> | sort`
# give the archive back to the user # give the archive back to the user
sudo chown "$(id -u)":"$(id -g)" "$output" sudo chown "$(id -u)":"$(id -g)" "$output"
@ -161,4 +160,3 @@ EOF
} }
main "$@" main "$@"

@ -19,29 +19,30 @@
############################################################################### ###############################################################################
# shellcheck source=/usr/lib/libretools/messages.sh # shellcheck source=/usr/lib/libretools/messages.sh
. "$(librelib messages)" source "$(librelib messages)"
usage() { usage() {
print "usage: %s [-h] IMG [ARG]..." "${0##*/}" print "USAGE: %s [-h] <img> [qemu-args ...]" "${0##*/}"
prose "Determine the architecture of IMG and boot it using qemu. IMG is assumed prose "Determine the architecture of <img> and boot it using qemu. <img> is assumed
to be a valid, raw-formatted parabola virtual machine image, ideally to be a valid, raw-formatted parabola virtual machine image, ideally
created using pvmbootstrap. The started instances are assigned 1GiB of created using pvmbootstrap. The started instance is assigned 1G of
RAM and one SMP core." RAM and one SMP core."
echo echo
prose "When a graphical desktop environment is available, start the machine prose "When a graphical desktop environment is available, start the machine
normally, otherwise append -nographic to the qemu options. This behavior normally, otherwise append -nographic to the qemu options. This behavior
can be forced by unsetting DISPLAY manually, for example through:" can be forced by unsetting DISPLAY manually, for example through:"
echo echo
echo " DISPLAY= ${0##*/} IMG ..." echo " DISPLAY= ${0##*/} ./an.img"
echo echo
prose "When the architecture of IMG is compatible with the host architecture, prose "When the architecture of <img> is compatible with the host architecture,
append -enable-kvm to the qemu arguments." append -enable-kvm to the qemu arguments."
echo echo
prose "Further arguments provided after IMG will be passed unmodified to the prose "Further arguments provided after <img> will be passed unmodified to the
qemu invocation. This can be used to allocate more resources to the virtual qemu invocation. This can be used to allocate more resources to the virtual
machine, for example:" machine, for example:"
echo echo
echo " ${0##*/} IMG -m 2G -smp 2" echo " ${0##*/} ./an.img -m 2G -smp 2"
echo echo
echo "Supported options:" echo "Supported options:"
echo " -h Display this help and exit" echo " -h Display this help and exit"
@ -124,38 +125,36 @@ pvm_guess_qemu_args() {
# if we're running a supported arch, enable kvm # if we're running a supported arch, enable kvm
if pvm_native_arch "$2"; then qemu_args+=(-enable-kvm); fi if pvm_native_arch "$2"; then qemu_args+=(-enable-kvm); fi
# otherwise, decide by target arch # set arch-specific args
local kernel_console
case "$2" in case "$2" in
i386|x86_64|ppc64) i386|x86_64|ppc64)
qemu_args+=(-m 2G "$1") qemu_args+=(-m 1G -hda "$1")
# unmount the unneeded virtual drive early # unmount the unneeded virtual drive early
pvm_umount ;; pvm_umount ;;
arm) arm)
qemu_args+=( kernel_console="console=tty0 console=ttyAMA0 "
-machine virt qemu_args+=(-machine virt
-m 2G -m 1G
-kernel "$workdir"/vmlinuz-linux-libre -kernel "$workdir"/vmlinuz-linux-libre
-initrd "$workdir"/initramfs-linux-libre.img -initrd "$workdir"/initramfs-linux-libre.img
-append "console=tty0 console=ttyAMA0 rw root=/dev/vda3" -append "${kernel_console}rw root=/dev/vda3"
-drive "if=none,file=$1,format=raw,id=hd" -drive "if=none,file=$1,format=raw,id=hd"
-device "virtio-blk-device,drive=hd" -device "virtio-blk-device,drive=hd"
-netdev "user,id=mynet" -netdev "user,id=mynet"
-device "virtio-net-device,netdev=mynet") ;; -device "virtio-net-device,netdev=mynet") ;;
riscv64) riscv64)
qemu_args+=( kernel_console=$( [ -z "$DISPLAY" ] && echo "console=ttyS0 " )
-machine virt qemu_args+=(-machine virt
-m 2G -m 1G
-kernel "$workdir"/bbl -kernel "$workdir"/bbl
-append "rw root=/dev/vda" -append "${kernel_console}rw root=/dev/vda"
-drive "file=${loopdev}p3,format=raw,id=hd0" -drive "file=${loopdev}p3,format=raw,id=hd0"
-device "virtio-blk-device,drive=hd0" -device "virtio-blk-device,drive=hd0"
-object "rng-random,filename=/dev/urandom,id=rng0" -object "rng-random,filename=/dev/urandom,id=rng0"
-device "virtio-rng-device,rng=rng0" -device "virtio-rng-device,rng=rng0"
-device "virtio-net-device,netdev=usernet" -netdev "user,id=usernet"
-netdev "user,id=usernet") -device "virtio-net-device,netdev=usernet") ;;
if [ -z "$DISPLAY" ]; then
qemu_args+=(-append "console=ttyS0 rw root=/dev/vda");
fi ;;
*) *)
error "%s: unable to determine default qemu args" "$1" error "%s: unable to determine default qemu args" "$1"
return "$EXIT_FAILURE" ;; return "$EXIT_FAILURE" ;;
@ -177,15 +176,9 @@ main() {
done done
local shiftlen=$(( OPTIND - 1 )) local shiftlen=$(( OPTIND - 1 ))
shift $shiftlen shift $shiftlen
if [ "$#" -lt 1 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi
local imagefile="$1" local imagefile="$1"
shift shift
[ ! -e "$imagefile" ] && error "%s: file not found" "$imagefile" && exit "$EXIT_FAILURE"
if [ ! -e "$imagefile" ]; then
error "%s: file not found" "$imagefile"
exit "$EXIT_FAILURE"
fi
local workdir loopdev local workdir loopdev
pvm_mount "$imagefile" || exit pvm_mount "$imagefile" || exit

@ -18,44 +18,52 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # # along with this program. If not, see <http://www.gnu.org/licenses/>. #
############################################################################### ###############################################################################
# shellcheck source=/usr/lib/libretools/messages.sh # shellcheck source=/usr/lib/libretools/messages.sh
. "$(librelib messages)" source "$(librelib messages)"
readonly DEF_MIRROR="https://repo.parabola.nu/\$repo/os/\$arch"
readonly DEF_IMG_GB=64
Hooks=()
Mirror=$DEF_MIRROR
ImgSizeGb=$DEF_IMG_GB
Init=''
usage() { usage() {
print "usage: %s [-hO] [-s SIZE] [-M MIRROR] [-H HOOK]... IMG ARCH" "${0##*/}" print "USAGE:"
print " pvmbootstrap [-h] [-H <hook>] [-M <mirror>] [-O] [-s <img_size>] <img> <arch>"
echo
prose "Produce preconfigured parabola GNU/Linux-libre virtual machine instances." prose "Produce preconfigured parabola GNU/Linux-libre virtual machine instances."
echo echo
prose "The produced image file is written to IMG, and is configured and prose "The produced image file is written to <img>, and is configured and
bootstrapped for the achitecture specified in ARCH. ARCH can ether be bootstrapped for the achitecture specified in <arch>. <arch> can be any
one of the officially supported architectures x86_64, i686 or armv7h, one of the supported architectures: 'x86_64', 'i686' or 'armv7h',
or one of the unofficial arches ppc64le and riscv64 (refer to -M for or one of the experimental arches: 'ppc64le' or 'riscv64'."
custom package mirrors)"
echo echo
echo "Supported options:" echo "Supported options:"
echo " -O bootstrap an openrc system instead of a systemd one" echo " -h Display this help and exit"
echo " -s SIZE Set the size of the VM image (default: 64GiB)" echo " -H <hook> Enable a hook to customize the created image. This can be"
echo " -M MIRROR Choose a different mirror to pacstrap from" echo " the path to a script, which will be executed once within"
echo " default: <https://repo.parabola.nu/\$repo/os/\$arch>" echo " the running VM, or one of the pre-defined hooks described"
echo " -H HOOK Enable a hook to customize the created image. This can be" echo " below. This option can be specified multiple times."
echo " the path to a script, which will be executed once within" echo " -M <mirror> Specify a different mirror from which to fetch packages"
echo " the running VM, or one of the predefined hooks described" echo " (default: $DEF_MIRROR)"
echo " below. This option can be specified multiple times." echo " -O Bootstrap an openrc system instead of a systemd one"
echo " -h Display this help and exit" echo " -s <img_size> Set the size (in GB) of the VM image (default: $DEF_IMG_GB)"
echo echo
echo "Predefined hooks:" echo "Pre-defined hooks:"
echo " ethernet-dhcp: configure and enable an ethernet device in the virtual" echo " ethernet-dhcp: Configure and enable an ethernet device in the virtual"
echo " machine, using openresolv, dhcp and systemd-networkd" echo " machine, using openresolv, dhcpcd, and systemd-networkd"
echo echo
echo "This script is part of parabola-vmbootstrap. source code available at:" echo "This script is part of parabola-vmbootstrap. source code available at:"
echo " <https://git.parabola.nu/~oaken-source/parabola-vmbootstrap.git>" echo " <https://git.parabola.nu/~oaken-source/parabola-vmbootstrap.git>"
} }
pvm_native_arch() { pvm_native_arch() {
local arch local arch=$( [[ "$1" =~ arm.* ]] && echo 'armv7l' || echo "$1" )
case "$1" in
arm*) arch=armv7l;;
*) arch="$1";;
esac
setarch "$arch" /bin/true 2>/dev/null || return setarch "$arch" /bin/true 2>/dev/null || return
} }
@ -64,17 +72,15 @@ pvm_bootstrap() {
msg "%s: starting image creation for %s" "$file" "$arch" msg "%s: starting image creation for %s" "$file" "$arch"
# create the raw image file # create the raw image file
qemu-img create -f raw "$file" "$size" || return qemu-img create -f raw "$file" "${ImgSizeGb}G" || return
# prepare for cleanup # prepare for cleanup
trap 'pvm_cleanup' INT TERM RETURN trap 'pvm_cleanup' INT TERM RETURN
# mount the virtual disk # mount the virtual disk
local workdir loopdev local workdir loopdev
workdir="$(mktemp -d -t pvm-rootfs-XXXXXXXXXX)" || return workdir="$(mktemp -d -t pvm-rootfs-XXXXXXXXXX)" || return
loopdev="$(sudo losetup -fLP --show "$file")" || return loopdev="$(sudo losetup -fLP --show "$file")" || return
# clean out the first 8MiB
sudo dd if=/dev/zero of="$loopdev" bs=1M count=8 || return sudo dd if=/dev/zero of="$loopdev" bs=1M count=8 || return
# partition # partition
@ -111,17 +117,17 @@ pvm_bootstrap() {
case "$arch" in case "$arch" in
i686|x86_64) i686|x86_64)
sudo mkfs.ext2 "$loopdev"p2 || return sudo mkfs.ext2 "$loopdev"p2 || return
sudo mkswap "$loopdev"p3 || return sudo mkswap "$loopdev"p3 || return
sudo mkfs.ext4 "$loopdev"p4 || return sudo mkfs.ext4 "$loopdev"p4 || return
swapdev="$loopdev"p3 ;; swapdev="$loopdev"p3 ;;
armv7h) armv7h)
sudo mkfs.vfat -F 32 "$loopdev"p1 || return sudo mkfs.vfat -F 32 "$loopdev"p1 || return
sudo mkswap "$loopdev"p2 || return sudo mkswap "$loopdev"p2 || return
sudo mkfs.ext4 "$loopdev"p3 || return sudo mkfs.ext4 "$loopdev"p3 || return
swapdev="$loopdev"p2 ;; swapdev="$loopdev"p2 ;;
ppc64le|riscv64) ppc64le|riscv64)
sudo mkfs.ext2 "$loopdev"p1 || return sudo mkfs.ext2 "$loopdev"p1 || return
sudo mkswap "$loopdev"p2 || return sudo mkswap "$loopdev"p2 || return
sudo mkfs.ext4 "$loopdev"p3 || return sudo mkfs.ext4 "$loopdev"p3 || return
swapdev="$loopdev"p2 ;; swapdev="$loopdev"p2 ;;
esac esac
@ -129,13 +135,13 @@ pvm_bootstrap() {
# mount partitions # mount partitions
case "$arch" in case "$arch" in
i686|x86_64) i686|x86_64)
sudo mount "$loopdev"p4 "$workdir" || return sudo mount "$loopdev"p4 "$workdir" || return
sudo mkdir -p "$workdir"/boot || return sudo mkdir -p "$workdir"/boot || return
sudo mount "$loopdev"p2 "$workdir"/boot || return sudo mount "$loopdev"p2 "$workdir"/boot || return
;; ;;
armv7h|ppc64le|riscv64) armv7h|ppc64le|riscv64)
sudo mount "$loopdev"p3 "$workdir" || return sudo mount "$loopdev"p3 "$workdir" || return
sudo mkdir -p "$workdir"/boot || return sudo mkdir -p "$workdir"/boot || return
sudo mount "$loopdev"p1 "$workdir"/boot || return sudo mount "$loopdev"p1 "$workdir"/boot || return
;; ;;
esac esac
@ -149,66 +155,56 @@ pvm_bootstrap() {
*) qemu_arch="$arch" ;; *) qemu_arch="$arch" ;;
esac esac
if [[ -z $(sudo grep -l -F \ local qemu_user_static=$(sudo grep -l -F -e "interpreter /usr/bin/qemu-$qemu_arch-" \
-e "interpreter /usr/bin/qemu-$qemu_arch-" \ -r -- /proc/sys/fs/binfmt_misc 2>/dev/null | \
-r -- /proc/sys/fs/binfmt_misc 2>/dev/null \ xargs -r sudo grep -xF 'enabled' )
| xargs -r sudo grep -xF 'enabled') ]] if [[ -z "$qemu_user_static" ]]; then
then
error "%s: missing qemu-user-static for %s" "$file" "$arch" error "%s: missing qemu-user-static for %s" "$file" "$arch"
return "$EXIT_FAILURE" return "$EXIT_FAILURE"
fi fi
sudo mkdir -p "$workdir"/usr/bin sudo mkdir -p "$workdir"/usr/bin
sudo cp -v "/usr/bin/qemu-$qemu_arch-"* "$workdir"/usr/bin || return sudo cp -v "/usr/bin/qemu-$qemu_arch-"* "$workdir"/usr/bin || return
fi fi
# prepare pacstrap config # prepare pacstrap config
local pacconf local pacconf repos
pacconf="$(mktemp -t pvm-pacconf-XXXXXXXXXX)" || return pacconf="$(mktemp -t pvm-pacconf-XXXXXXXXXX)" || return
cat > "$pacconf" << EOF repos=('libre' 'core' 'extra' 'community' 'pcr')
[options] echo -e "[options]\nArchitecture = $arch\n\n" > "$pacconf"
Architecture = $arch for repo in ${repos[@]}; do echo -e "[$repo]\nServer = $Mirror\n" >> "$pacconf"; done;
[libre]
Server = $mirror
[core]
Server = $mirror
[extra]
Server = $mirror
[community]
Server = $mirror
[pcr]
Server = $mirror
EOF
# prepare lists of packages # prepare lists of packages
local pkg=("base$init" "openssh$init" openresolv ldns) # FIXME: [nonsystemd] is in a transitional phase
# package name suffices such as '-opernrc' will be removed soon
# ideally, the install process will be identical for either systemd or openrc
# depending only on which repos are enabled
local pkgs=("base$Init" "openssh$Init" openresolv ldns)
case "$arch" in case "$arch" in
i686|x86_64) pkg+=(grub) ;; i686|x86_64) pkgs+=(grub) ;;
esac esac
case "$arch" in case "$arch" in
riscv64) ;; riscv64) ;;
*) pkg+=("haveged$init" net-tools) ;; *) pkgs+=("haveged$Init" net-tools) ;;
esac esac
if [[ ! $Init ]]; then
# Add back in base packages that the switch from base group # FIXME: Add back in base packages that the switch from base group
# to base PKG yanked and be specific on OpenRC to avoid conflicts # to base PKG yanked and be specific on OpenRC to avoid conflicts
if [[ ! $init ]]; then # ideally, we will assign these to a new 'base-extras' group
pkgs+=(cryptsetup device-mapper dhcpcd e2fsprogs inetutils \
pkg+=(cryptsetup device-mapper dhcpcd e2fsprogs inetutils \ jfsutils linux-libre logrotate lvm2 man-db mdadm nano \
jfsutils linux-libre logrotate lvm2 man-db mdadm nano \ netctl pacman-mirrorlist perl reiserfsprogs s-nail sysfsutils \
netctl pacman-mirrorlist perl reiserfsprogs s-nail sysfsutils \ texinfo usbutils vi xfsprogs your-freedom systemd-udev \
texinfo usbutils vi xfsprogs your-freedom systemd-udev \ systemd-libudev )
systemd-libudev)
else else
pkg+=(systemd-libs-dummy) pkgs+=(systemd-libs-dummy)
fi fi
local pkg_guest_cache=(ca-certificates-utils) local pkg_guest_cache=(ca-certificates-utils)
# pacstrap! :) # pacstrap! :)
sudo pacstrap -GMc -C "$pacconf" "$workdir" "${pkg[@]}" || return sudo pacstrap -GMc -C "$pacconf" "$workdir" "${pkgs[@]}" || return
sudo pacstrap -GM -C "$pacconf" "$workdir" "${pkg_guest_cache[@]}" || return sudo pacstrap -GM -C "$pacconf" "$workdir" "${pkg_guest_cache[@]}" || return
# create an fstab # create an fstab
case "$arch" in case "$arch" in
@ -231,35 +227,35 @@ EOF
# install a boot loader # install a boot loader
case "$arch" in case "$arch" in
i686|x86_64) i686|x86_64)
local grub_def_file="$workdir"/etc/default/grub
local grub_cfg_file=/boot/grub/grub.cfg
# enable serial console # enable serial console
local field=GRUB_CMDLINE_LINUX_DEFAULT local field=GRUB_CMDLINE_LINUX_DEFAULT
local value="console=tty0 console=ttyS0" local value="console=tty0 console=ttyS0"
sudo sed -i "s/.*$field=.*/$field=\"$value\"/" \ sudo sed -i "s/.*$field=.*/$field=\"$value\"/" "$grub_def_file" || return
"$workdir"/etc/default/grub || return
# disable boot menu timeout # disable boot menu timeout
local field=GRUB_TIMEOUT local field=GRUB_TIMEOUT
local value=0 local value=0
sudo sed -i "s/.*$field=.*/$field=$value/" \ sudo sed -i "s/.*$field=.*/$field=$value/" "$grub_def_file" || return
"$workdir"/etc/default/grub || return
# install grub to the VM # install grub to the VM
sudo arch-chroot "$workdir" grub-install --target=i386-pc "$loopdev" || return sudo arch-chroot "$workdir" grub-install "$loopdev" || return
sudo arch-chroot "$workdir" grub-mkconfig -o /boot/grub/grub.cfg || return sudo arch-chroot "$workdir" grub-mkconfig -o $grub_cfg_file || return
;; ;;
riscv64) riscv64)
# FIXME: for the time being, use fedora bbl to boot # FIXME: for the time being, use fedora bbl to boot
sudo wget https://fedorapeople.org/groups/risc-v/disk-images/bbl \ local bbl_url=https://fedorapeople.org/groups/risc-v/disk-images/bbl
-O "$workdir"/boot/bbl || return sudo wget $bbl_url -O "$workdir"/boot/bbl || return
;; ;;
# armv7h has no boot loader. # armv7h has no boot loader.
# FIXME: what about ppc64le # FIXME: what about ppc64le
esac esac
# regenerate the initcpio, skipping the autodetect hook # regenerate the initcpio, skipping the autodetect hook
sudo cp "$workdir"/etc/mkinitcpio.d/linux-libre.preset{,.backup} || return local preset_file="$workdir"/etc/mkinitcpio.d/linux-libre.preset
echo "default_options=\"-S autodetect\"" \ sudo cp "$preset_file"{,.backup} || return
| sudo tee -a "$workdir"/etc/mkinitcpio.d/linux-libre.preset || return echo "default_options=\"-S autodetect\"" | sudo tee -a "$preset_file" || return
sudo arch-chroot "$workdir" mkinitcpio -p linux-libre || return sudo arch-chroot "$workdir" mkinitcpio -p linux-libre || return
sudo mv "$workdir"/etc/mkinitcpio.d/linux-libre.preset{.backup,} || return sudo mv "$preset_file"{.backup,} || return
# disable audit # disable audit
sudo arch-chroot "$workdir" systemctl mask systemd-journald-audit.socket sudo arch-chroot "$workdir" systemctl mask systemd-journald-audit.socket
@ -273,7 +269,7 @@ EOF
# push hooks into the image # push hooks into the image
sudo mkdir -p "$workdir/root/hooks" sudo mkdir -p "$workdir/root/hooks"
[ "${#hooks[@]}" -eq 0 ] || sudo cp -v "${hooks[@]}" "$workdir"/root/hooks/ [ "${#Hooks[@]}" -eq 0 ] || sudo cp -v "${Hooks[@]}" "$workdir"/root/hooks/
# create a master hook script # create a master hook script
sudo tee "$workdir"/root/hooks.sh << 'EOF' sudo tee "$workdir"/root/hooks.sh << 'EOF'
@ -292,7 +288,7 @@ pacman -U --noconfirm /var/cache/pacman/pkg/ca-certificates-utils-*.pkg.tar.xz
# run the hooks # run the hooks
for hook in /root/hooks/*; do for hook in /root/hooks/*; do
echo "running hook \"$hook\"" echo "running hook \"$hook\""
. "$hook" || return source "$hook" || return
done done
# clean up after yourself # clean up after yourself
@ -329,28 +325,26 @@ EOF
# unmount everything # unmount everything
pvm_cleanup pvm_cleanup
# boot the machine, and run the preinit scripts # boot the machine to run the preinit hooks
local pvmboot_cmd
local qemu_flags=(-no-reboot) local qemu_flags=(-no-reboot)
local pvmboot
if [ -f "./src/pvmboot.sh" ]; then if [ -f "./src/pvmboot.sh" ]; then
pvmboot=(bash ./src/pvmboot.sh) pvmboot_cmd=(bash ./src/pvmboot.sh)
elif type -p pvmboot &>/dev/null; then elif type -p pvmboot &>/dev/null; then
pvmboot=(pvmboot) pvmboot_cmd=('pvmboot')
else else
error "%s: pvmboot not available -- unable to run hooks" "$file" error "%s: pvmboot not available -- unable to run hooks" "$file"
return "$EXIT_FAILURE" return "$EXIT_FAILURE"
fi fi
pvmboot_cmd+=("$file" "${qemu_flags[@]}")
exec 3>&1 exec 3>&1
DISPLAY='' "${pvmboot[@]}" "$file" "${qemu_flags[@]}" \ msg "booting the machine to run the pre-init hooks"
| tee /dev/fd/3 | grep -q "preinit hooks successful" DISPLAY='' "${pvmboot_cmd[@]}" | tee /dev/fd/3 | grep -q "preinit hooks successful"
local res=$? local res=$?
exec 3>&- exec 3>&-
! (( $res )) || error "%s: failed to complete preinit hooks" "$file"
if [ "$res" -ne 0 ]; then return $res
error "%s: failed to complete preinit hooks" "$file"
return "$res"
fi
} }
pvm_cleanup() { pvm_cleanup() {
@ -360,7 +354,7 @@ pvm_cleanup() {
unset pacconf unset pacconf
if [ -n "$workdir" ]; then if [ -n "$workdir" ]; then
sudo rm -f "$workdir"/usr/bin/qemu-* sudo rm -f "$workdir"/usr/bin/qemu-*
sudo umount -R "$workdir" sudo umount -R "$workdir" 2> /dev/null
rmdir "$workdir" rmdir "$workdir"
fi fi
unset workdir unset workdir
@ -374,34 +368,29 @@ main() {
exit "$EXIT_NOPERMISSION" exit "$EXIT_NOPERMISSION"
fi fi
local size="64G"
local mirror="https://repo.parabola.nu/\$repo/os/\$arch"
local hooks=()
local init
# parse options # parse options
while getopts 'hOs:M:H:' arg; do while getopts 'hOs:M:H:' arg; do
case "$arg" in case "$arg" in
O) init="-openrc";;
h) usage; return "$EXIT_SUCCESS";; h) usage; return "$EXIT_SUCCESS";;
s) size="$OPTARG";;
M) mirror="$OPTARG";;
H) if [ -e "/usr/lib/libretools/pvmbootstrap/hook-$OPTARG.sh" ]; then H) if [ -e "/usr/lib/libretools/pvmbootstrap/hook-$OPTARG.sh" ]; then
hooks+=("/usr/lib/libretools/pvmbootstrap/hook-$OPTARG.sh") hooks+=("/usr/lib/libretools/pvmbootstrap/hook-$OPTARG.sh")
elif [ -e "./src/hooks/hook-$OPTARG.sh" ]; then elif [ -e "./src/hooks/hook-$OPTARG.sh" ]; then
hooks+=("./src/hooks/hook-$OPTARG.sh") hooks+=("./src/hooks/hook-$OPTARG.sh")
elif [ -e "$OPTARG" ]; then elif [ -e "$OPTARG" ]; then
hooks+=("$OPTARG") Hooks+=("$OPTARG")
else else
warning "%s: hook does not exist" "$OPTARG" warning "%s: hook does not exist" "$OPTARG"
fi ;; fi ;;
M) Mirror="$OPTARG";;
O) Init="-openrc";;
s) ImgSizeGb="$(sed 's|[^0-9]||g' <<<$OPTARG)";;
*) usage >&2; exit "$EXIT_INVALIDARGUMENT";; *) usage >&2; exit "$EXIT_INVALIDARGUMENT";;
esac esac
done done
local shiftlen=$(( OPTIND - 1 )) local shiftlen=$(( OPTIND - 1 ))
shift $shiftlen shift $shiftlen
if [ "$#" -ne 2 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi if [ "$#" -ne 2 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi
local file="$1" local file="$1"
local arch="$2" local arch="$2"