complete rewrite of pvmbootstrap (formerly create) -- support script files are now obsolete and have been removed
This commit is contained in:
parent
6fa8b39787
commit
2fe6f0a131
22
README
22
README
@ -9,20 +9,26 @@ virtual machine image creation
|
||||
------------------------------
|
||||
|
||||
To create a new virtual machine image, run
|
||||
$> sudo ./create.sh
|
||||
|
||||
The creation is influenced by the following environment variables:
|
||||
$> ./pvmbootstrap.sh [path to image] [arch]
|
||||
|
||||
ARCH - the target architecture of the image. default: armv7h
|
||||
where arch is one of the supported parabola arches, which are currently:
|
||||
|
||||
SIZE - the size of the root image. default: 64GiB
|
||||
official: [ i686, x86_64, armv7h ]
|
||||
unofficial: [ ppc64le, riscv64 ]
|
||||
|
||||
MIRROR - the mirror used to pacstrap the image, anything valid in a `Server =`
|
||||
line can go here.
|
||||
default: https://redirector.parabola.nu/\$repo/os/\$arch}
|
||||
the script will attempt to bootstrap a virtual machine of the selected
|
||||
archituecture in the output file specified. If the output file already exists,
|
||||
the script will emit a warning and ask for confirmation to proceed.
|
||||
|
||||
The created images are stored in the build/ directory.
|
||||
the creation can be influenced by providing one or more of the following
|
||||
arguments to pvmbootstrap.sh:
|
||||
|
||||
-s size -- set the size of the created VM image (default: 64G)
|
||||
-M mirror -- set the mirror to fetch packages from
|
||||
(default: https://repo.parabola.nu/$repo/os/$arch)
|
||||
|
||||
the created machine images should be bootable using pvmboot.sh
|
||||
|
||||
virtual machine boot
|
||||
--------------------
|
||||
|
47
create.sh
47
create.sh
@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
##############################################################################
|
||||
# parabola-imagebuilder #
|
||||
# #
|
||||
# Copyright (C) 2017, 2018 Andreas Grapentin #
|
||||
# #
|
||||
# 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/>. #
|
||||
##############################################################################
|
||||
|
||||
# target options
|
||||
export ARCH="${ARCH:-armv7h}"
|
||||
export SIZE="${SIZE:-64G}"
|
||||
export MIRROR="${MIRROR:-https://redirector.parabola.nu/\$repo/os/\$arch}"
|
||||
|
||||
# common directories
|
||||
startdir="$(pwd)"
|
||||
export TOPBUILDDIR="$startdir"/build
|
||||
export TOPSRCDIR="$startdir"/src
|
||||
mkdir -p "$TOPBUILDDIR"
|
||||
chown "$SUDO_USER" "$TOPBUILDDIR"
|
||||
|
||||
# shellcheck source=src/shared/common.sh
|
||||
. "$TOPSRCDIR"/shared/common.sh
|
||||
|
||||
# sanity checks
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
die -e "$ERROR_INVOCATION" "must be root"
|
||||
fi
|
||||
|
||||
# shellcheck source=src/qemu.sh
|
||||
. "$TOPSRCDIR"/qemu.sh
|
||||
|
||||
qemu_make_image "$TOPBUILDDIR/parabola-$ARCH.img" "$SIZE" \
|
||||
|| die "failed to prepare qemu base image"
|
||||
|
||||
msg "all done."
|
@ -50,7 +50,8 @@ pvm_mount() {
|
||||
|
||||
workdir="$(mktemp -d -t pvm-XXXXXXXXXX)" || return
|
||||
loopdev="$(sudo losetup -fLP --show "$1")" || return
|
||||
sudo mount "$loopdev"p1 "$workdir" || return
|
||||
sudo mount "$loopdev"p1 "$workdir" \
|
||||
|| sudo mount "$loopdev"p2 "$workdir" || return
|
||||
}
|
||||
|
||||
pvm_umount() {
|
||||
@ -106,7 +107,7 @@ pvm_native_arch() {
|
||||
setarch "$arch" /bin/true 2>/dev/null || return
|
||||
}
|
||||
|
||||
pvm_build_qemu_args() {
|
||||
pvm_guess_qemu_args() {
|
||||
# if we're not running on X / wayland, disable graphics
|
||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-nographic); fi
|
||||
|
||||
@ -117,8 +118,7 @@ pvm_build_qemu_args() {
|
||||
case "$2" in
|
||||
i386|x86_64|ppc64)
|
||||
qemu_args+=(-m 1G "$1")
|
||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-append "console=ttyS0"); fi
|
||||
# unmount the drive early
|
||||
# unmount the unneeded virtual drive early
|
||||
pvm_umount ;;
|
||||
arm)
|
||||
qemu_args+=(
|
||||
@ -128,22 +128,23 @@ pvm_build_qemu_args() {
|
||||
-kernel "$workdir"/vmlinuz-linux-libre
|
||||
-dtb "$workdir"/dtbs/linux-libre/vexpress-v2p-ca9.dtb
|
||||
-initrd "$workdir"/initramfs-linux-libre.img
|
||||
-append " rw root=/dev/mmcblk0p3"
|
||||
-drive "if=sd,driver=raw,cache=writeback,file=$1")
|
||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-append " console=ttyAMA0"); fi ;;
|
||||
-append "console=tty0 console=ttyAMA0 rw root=/dev/mmcblk0p3"
|
||||
-drive "if=sd,driver=raw,cache=writeback,file=$1") ;;
|
||||
riscv64)
|
||||
qemu_args+=(
|
||||
-machine virt
|
||||
-m 1G
|
||||
-kernel "$workdir"/bbl
|
||||
-append " rw root=/dev/vda"
|
||||
-append "rw root=/dev/vda"
|
||||
-drive "file=${loopdev}p3,format=raw,id=hd0"
|
||||
-device "virtio-blk-device,drive=hd0"
|
||||
-object "rng-random,filename=/dev/urandom,id=rng0"
|
||||
-device "virtio-rng-device,rng=rng0"
|
||||
-device "virtio-net-device,netdev=usernet"
|
||||
-netdev "user,id=usernet")
|
||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-append " console=ttyS0"); fi ;;
|
||||
if [ -z "$DISPLAY" ]; then
|
||||
qemu_args+=(-append "console=ttyS0 rw root=/dev/vda");
|
||||
fi ;;
|
||||
*)
|
||||
error "%s: unable to determine default qemu args" "$1"
|
||||
return "$EXIT_FAILURE" ;;
|
||||
@ -152,7 +153,7 @@ pvm_build_qemu_args() {
|
||||
|
||||
main() {
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
error "This program must be run as regular user"
|
||||
error "This program must be run as a regular user"
|
||||
exit "$EXIT_NOPERMISSION"
|
||||
fi
|
||||
|
||||
@ -187,7 +188,7 @@ main() {
|
||||
fi
|
||||
|
||||
local qemu_args=()
|
||||
pvm_build_qemu_args "$imagefile" "$arch" || exit
|
||||
pvm_guess_qemu_args "$imagefile" "$arch" || exit
|
||||
qemu_args+=("$@")
|
||||
|
||||
(set -x; qemu-system-"$arch" "${qemu_args[@]}")
|
||||
|
266
src/pvmbootstrap.sh
Normal file
266
src/pvmbootstrap.sh
Normal file
@ -0,0 +1,266 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# parabola-vmbootstrap -- create and start parabola virtual machines #
|
||||
# #
|
||||
# Copyright (C) 2017 - 2019 Andreas Grapentin #
|
||||
# #
|
||||
# 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/>. #
|
||||
###############################################################################
|
||||
|
||||
# shellcheck source=/usr/lib/libretools/messages.sh
|
||||
. "$(librelib messages)"
|
||||
|
||||
usage() {
|
||||
print "usage: %s [-h] [-s size] [-M mirror] filename arch" "${0##*/}"
|
||||
echo
|
||||
echo "this script is developed as part of parabola-vmbootstrap."
|
||||
}
|
||||
|
||||
pvm_native_arch() {
|
||||
local arch
|
||||
case "$1" in
|
||||
arm*) arch=armv7l;;
|
||||
*) arch="$1";;
|
||||
esac
|
||||
|
||||
setarch "$arch" /bin/true 2>/dev/null || return
|
||||
}
|
||||
|
||||
pvm_bootstrap() {
|
||||
msg "%s: starting image creation for %s" "$file" "$arch"
|
||||
|
||||
qemu-img create -f raw "$file" "$size" || return
|
||||
|
||||
trap 'pvm_cleanup' INT TERM RETURN
|
||||
|
||||
local workdir loopdev
|
||||
workdir="$(mktemp -d -t pvm-rootfs-XXXXXXXXXX)" || return
|
||||
loopdev="$(sudo losetup -fLP --show "$file")" || return
|
||||
|
||||
sudo dd if=/dev/zero of="$loopdev" bs=1M count=8 || return
|
||||
|
||||
# partition and mount
|
||||
case "$arch" in
|
||||
i686|x86_64)
|
||||
sudo parted -s "$loopdev" \
|
||||
mklabel gpt \
|
||||
mkpart primary 1MiB 2Mib \
|
||||
set 1 bios_grub on \
|
||||
mkpart primary ext2 2MiB 514MiB \
|
||||
mkpart primary linux-swap 514MiB 4610MiB \
|
||||
mkpart primary ext4 4610MiB 100% || return
|
||||
|
||||
sudo partprobe "$loopdev"
|
||||
|
||||
sudo mkfs.ext2 "$loopdev"p2 || return
|
||||
sudo mkswap "$loopdev"p3 || return
|
||||
sudo mkfs.ext4 "$loopdev"p4 || return
|
||||
|
||||
sudo mount "$loopdev"p4 "$workdir" || return
|
||||
sudo mkdir -p "$workdir"/boot || return
|
||||
sudo mount "$loopdev"p2 "$workdir"/boot || return
|
||||
;;
|
||||
ppc64le|riscv64)
|
||||
sudo parted -s "$loopdev" \
|
||||
mklabel gpt \
|
||||
mkpart primary ext2 1MiB 513MiB \
|
||||
set 1 boot on \
|
||||
mkpart primary linux-swap 513MiB 4609MiB \
|
||||
mkpart primary ext4 4609MiB 100% || return
|
||||
|
||||
sudo partprobe "$loopdev"
|
||||
|
||||
sudo mkfs.ext2 "$loopdev"p1 || return
|
||||
sudo mkswap "$loopdev"p2 || return
|
||||
sudo mkfs.ext4 "$loopdev"p3 || return
|
||||
|
||||
sudo mount "$loopdev"p3 "$workdir" || return
|
||||
sudo mkdir -p "$workdir"/boot || return
|
||||
sudo mount "$loopdev"p1 "$workdir"/boot || return
|
||||
;;
|
||||
armv7h)
|
||||
sudo parted -s "$loopdev" \
|
||||
mklabel gpt \
|
||||
mkpart ESP fat32 1MiB 513MiB \
|
||||
set 1 boot on \
|
||||
mkpart primary linux-swap 513MiB 4609MiB \
|
||||
mkpart primary ext4 4609MiB 100% || return
|
||||
|
||||
sudo partprobe "$loopdev"
|
||||
|
||||
sudo mkfs.vfat -F 32 "$loopdev"p1 || return
|
||||
sudo mkswap "$loopdev"p2 || return
|
||||
sudo mkfs.ext4 "$loopdev"p3 || return
|
||||
|
||||
sudo mount "$loopdev"p3 "$workdir" || return
|
||||
sudo mkdir -p "$workdir"/boot || return
|
||||
sudo mount "$loopdev"p1 "$workdir"/boot || return
|
||||
;;
|
||||
esac
|
||||
|
||||
# setup qemu-user-static
|
||||
if ! pvm_native_arch "$arch"; then
|
||||
# target arch can't execute natively, pacstrap is going to need help by qemu
|
||||
local qemu_arch
|
||||
case "$arch" in
|
||||
armv7h) qemu_arch=arm ;;
|
||||
*) qemu_arch="$arch" ;;
|
||||
esac
|
||||
|
||||
if [[ -z $(sudo grep -l -F \
|
||||
-e "interpreter /usr/bin/qemu-$qemu_arch-" \
|
||||
-r -- /proc/sys/fs/binfmt_misc 2>/dev/null \
|
||||
| xargs -r sudo grep -xF 'enabled') ]]
|
||||
then
|
||||
error "%s: missing qemu-user-static for %s" "$file" "$arch"
|
||||
return "$EXIT_FAILURE"
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$workdir"/usr/bin
|
||||
sudo cp -v "/usr/bin/qemu-$qemu_arch-"* "$workdir"/usr/bin || return
|
||||
fi
|
||||
|
||||
# pacstrap
|
||||
local pacconf
|
||||
pacconf="$(mktemp -t pvm-pacconf-XXXXXXXXXX)" || return
|
||||
cat > "$pacconf" << EOF
|
||||
[options]
|
||||
Architecture = $arch
|
||||
[libre]
|
||||
Server = $mirror
|
||||
[core]
|
||||
Server = $mirror
|
||||
[extra]
|
||||
Server = $mirror
|
||||
[community]
|
||||
Server = $mirror
|
||||
EOF
|
||||
|
||||
local pkg=(base)
|
||||
|
||||
case "$arch" in
|
||||
i686|x86_64) pkg+=(grub) ;;
|
||||
esac
|
||||
|
||||
sudo pacstrap -GMcd -C "$pacconf" "$workdir" "${pkg[@]}" || return
|
||||
|
||||
# finalize
|
||||
case "$arch" in
|
||||
i686|x86_64)
|
||||
# create an fstab
|
||||
sudo swapoff --all
|
||||
sudo swapon "$loopdev"p3
|
||||
genfstab -U "$workdir" | sudo tee "$workdir"/etc/fstab
|
||||
sudo swapoff "$loopdev"p3
|
||||
sudo swapon --all
|
||||
|
||||
# install grub to the VM
|
||||
sudo sed -i 's/^GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0"/' \
|
||||
"$workdir"/etc/default/grub || return
|
||||
sudo arch-chroot "$workdir" grub-install --target=i386-pc "$loopdev" || return
|
||||
sudo arch-chroot "$workdir" grub-mkconfig -o /boot/grub/grub.cfg || return
|
||||
|
||||
# regenerate the chroot-botched initcpio
|
||||
sudo cp "$workdir"/etc/mkinitcpio.d/linux-libre.preset{,.backup} || return
|
||||
echo "default_options=\"-S autodetect\"" \
|
||||
| sudo tee -a "$workdir"/etc/mkinitcpio.d/linux-libre.preset || return
|
||||
sudo arch-chroot "$workdir" mkinitcpio -p linux-libre || return
|
||||
sudo mv "$workdir"/etc/mkinitcpio.d/linux-libre.preset{.backup,} || return
|
||||
;;
|
||||
armv7h)
|
||||
# create an fstab
|
||||
sudo swapoff --all
|
||||
sudo swapon "$loopdev"p2
|
||||
genfstab -U "$workdir" | sudo tee "$workdir"/etc/fstab
|
||||
sudo swapoff "$loopdev"p2
|
||||
sudo swapon --all
|
||||
;;
|
||||
riscv64)
|
||||
# FIXME: for the time being, use fedora bbl to boot
|
||||
sudo wget https://fedorapeople.org/groups/risc-v/disk-images/bbl \
|
||||
-O "$workdir"/boot/bbl || return
|
||||
;;
|
||||
esac
|
||||
|
||||
pvm_cleanup
|
||||
}
|
||||
|
||||
pvm_cleanup() {
|
||||
trap - INT TERM RETURN
|
||||
|
||||
[ -n "$pacconf" ] && rm -f "$pacconf"
|
||||
unset pacconf
|
||||
if [ -n "$workdir" ]; then
|
||||
sudo rm -f "$workdir"/usr/bin/qemu-*
|
||||
sudo umount -R "$workdir"
|
||||
rmdir "$workdir"
|
||||
fi
|
||||
unset workdir
|
||||
[ -n "$loopdev" ] && sudo losetup -d "$loopdev"
|
||||
unset loopdev
|
||||
}
|
||||
|
||||
main() {
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
error "This program must be run as a regular user"
|
||||
exit "$EXIT_NOPERMISSION"
|
||||
fi
|
||||
|
||||
local size="64G"
|
||||
local mirror="https://repo.parabola.nu/\$repo/os/\$arch"
|
||||
|
||||
# parse options
|
||||
while getopts 'hs:M:' arg; do
|
||||
case "$arg" in
|
||||
h) usage; return "$EXIT_SUCCESS";;
|
||||
s) size="$OPTARG";;
|
||||
M) mirror="$OPTARG";;
|
||||
*) usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
||||
esac
|
||||
done
|
||||
local shiftlen=$(( OPTIND - 1 ))
|
||||
shift $shiftlen
|
||||
if [ "$#" -ne 2 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi
|
||||
|
||||
local file="$1"
|
||||
local arch="$2"
|
||||
|
||||
# determine if the target arch is supported
|
||||
case "$arch" in
|
||||
i686|x86_64|armv7h) ;;
|
||||
ppc64le|riscv64)
|
||||
warning "%s: arch %s is experimental" "$file" "$arch";;
|
||||
*)
|
||||
error "%s: arch %s is unsupported" "$file" "$arch"
|
||||
exit "$EXIT_INVALIDARGUMENT";;
|
||||
esac
|
||||
|
||||
if [ -e "$file" ]; then
|
||||
warning "%s: file exists. Continue? [y/N]" "$file"
|
||||
read -p " " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit "$EXIT_FAILURE"
|
||||
fi
|
||||
rm -f "$file" || exit
|
||||
fi
|
||||
|
||||
if ! pvm_bootstrap; then
|
||||
error "%s: bootstrap failed" "$file"
|
||||
exit "$EXIT_FAILURE"
|
||||
fi
|
||||
msg "%s: bootstrap complete" "$file"
|
||||
}
|
||||
|
||||
main "$@"
|
202
src/qemu.sh
202
src/qemu.sh
@ -1,202 +0,0 @@
|
||||
#!/bin/bash
|
||||
##############################################################################
|
||||
# parabola-imagebuilder #
|
||||
# #
|
||||
# Copyright (C) 2018 Andreas Grapentin #
|
||||
# #
|
||||
# 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/>. #
|
||||
##############################################################################
|
||||
|
||||
qemu_img_partition_and_mount_for_armv7h() {
|
||||
parted -s "$1" \
|
||||
mklabel gpt \
|
||||
mkpart ESP fat32 1MiB 513MiB \
|
||||
set 1 boot on \
|
||||
mkpart primary linux-swap 513MiB 4609MiB \
|
||||
mkpart primary ext4 4609MiB 100% || return
|
||||
|
||||
check_exe -r mkfs.vfat mkfs.ext4
|
||||
|
||||
mkfs.vfat -F 32 "${1}p1"
|
||||
mkswap "${1}p2"
|
||||
mkfs.ext4 "${1}p3"
|
||||
|
||||
mkdir -p "$2"
|
||||
mount "${1}p3" "$2" || return
|
||||
trap_add "umount -R $2" INT TERM EXIT
|
||||
mkdir -p "$2"/boot
|
||||
mount "${1}p1" "$2"/boot || return
|
||||
}
|
||||
|
||||
qemu_img_partition_and_mount_for_riscv64() {
|
||||
qemu_img_partition_and_mount_for_x86_64 "$@"
|
||||
}
|
||||
|
||||
qemu_img_partition_and_mount_for_powerpc64le() {
|
||||
qemu_img_partition_and_mount_for_x86_64 "$@"
|
||||
}
|
||||
|
||||
qemu_img_partition_and_mount_for_i686() {
|
||||
qemu_img_partition_and_mount_for_x86_64 "$@"
|
||||
}
|
||||
|
||||
qemu_img_partition_and_mount_for_x86_64() {
|
||||
parted -s "$1" \
|
||||
mklabel gpt \
|
||||
mkpart primary ext2 1MiB 513MiB \
|
||||
set 1 boot on \
|
||||
mkpart primary linux-swap 513MiB 4609MiB \
|
||||
mkpart primary ext4 4609MiB 100% || return
|
||||
|
||||
check_exe mkfs.ext2 mkfs.ext4
|
||||
|
||||
mkfs.ext2 "${1}p1"
|
||||
mkswap "${1}p2"
|
||||
mkfs.ext4 "${1}p3"
|
||||
|
||||
mkdir -p "$2"
|
||||
mount "${1}p3" "$2" || return
|
||||
trap_add "umount -R $2" INT TERM EXIT
|
||||
mkdir -p "$2"/boot
|
||||
mount "${1}p1" "$2"/boot || return
|
||||
}
|
||||
|
||||
qemu_img_losetup() {
|
||||
echo -n "checking for free loop device ... "
|
||||
loopdev=$(losetup -f --show "$1") || loopdev=no
|
||||
echo "$loopdev"
|
||||
partprobe "$loopdev"
|
||||
|
||||
[ "x$loopdev" == "xno" ] && return "$ERROR_MISSING"
|
||||
|
||||
trap_add "qemu_img_lorelease $loopdev" INT TERM EXIT
|
||||
}
|
||||
|
||||
qemu_img_lorelease() {
|
||||
losetup -d "$1"
|
||||
}
|
||||
|
||||
qemu_arch_is_foreign() {
|
||||
# borrowed from /usr/bin/librechroot
|
||||
local setarch
|
||||
case "$1" in
|
||||
arm*) setarch=armv7l ;;
|
||||
*) setarch="$1" ;;
|
||||
esac
|
||||
|
||||
echo -n "checking if arch '$1' is foreign ... "
|
||||
local need_qemu=no
|
||||
setarch "$setarch" /bin/true 2>/dev/null || need_qemu=yes
|
||||
echo "$need_qemu"
|
||||
|
||||
[ "x$need_qemu" == "xyes" ] || return
|
||||
}
|
||||
|
||||
qemu_setup_user_static() {
|
||||
local interpreter
|
||||
case "$ARCH" in
|
||||
armv7h) interpreter=/usr/bin/qemu-arm- ;;
|
||||
powerpc64le) interpreter=/usr/bin/qemu-ppc64le- ;;
|
||||
*) interpreter=/usr/bin/qemu-"$ARCH"- ;;
|
||||
esac
|
||||
|
||||
if qemu_arch_is_foreign "$ARCH"; then
|
||||
# target arch can't execute natively, pacstrap is going to need help by qemu
|
||||
if [[ -z $(grep -l -F \
|
||||
-e "interpreter $interpreter" \
|
||||
-r -- /proc/sys/fs/binfmt_misc 2>/dev/null \
|
||||
| xargs -r grep -xF 'enabled') ]]
|
||||
then
|
||||
error "unable to continue - need qemu-user-static for $ARCH"
|
||||
return "$ERROR_MISSING"
|
||||
fi
|
||||
|
||||
mkdir -p "$1"/usr/bin
|
||||
cp -v "$interpreter"* "$1"/usr/bin || return
|
||||
trap_add "qemu_cleanup_user_static $1"
|
||||
fi
|
||||
}
|
||||
|
||||
qemu_cleanup_user_static() {
|
||||
rm -f "$1"/usr/bin/qemu-*
|
||||
}
|
||||
|
||||
qemu_img_finalize_for_armv7h() {
|
||||
true
|
||||
}
|
||||
|
||||
qemu_img_finalize_for_riscv64() {
|
||||
# for the time being, use fedora bbl to boot
|
||||
wget https://fedorapeople.org/groups/risc-v/disk-images/bbl \
|
||||
-O "$1"/boot/bbl
|
||||
}
|
||||
|
||||
qemu_img_finalize_for_powerpc64le() {
|
||||
true
|
||||
}
|
||||
|
||||
qemu_img_finalize_for_i686() {
|
||||
true
|
||||
}
|
||||
|
||||
qemu_img_finalize_for_x86_64() {
|
||||
true
|
||||
}
|
||||
|
||||
qemu_make_image() {
|
||||
msg "preparing parabola qemu image for $ARCH"
|
||||
|
||||
# skip, if already exists
|
||||
check_file "$1" && return
|
||||
|
||||
check_exe -r parted
|
||||
|
||||
# write to preliminary file
|
||||
local tmpfile="$1.part"
|
||||
rm -f "$tmpfile"
|
||||
|
||||
# create an empty image
|
||||
qemu-img create -f raw "$tmpfile" "$2" || return
|
||||
|
||||
# create a minimal pacman.conf
|
||||
cat > "$TOPBUILDDIR/pacman.conf.$ARCH" << EOF
|
||||
[options]
|
||||
Architecture = $ARCH
|
||||
[libre]
|
||||
Server = $MIRROR
|
||||
[core]
|
||||
Server = $MIRROR
|
||||
[extra]
|
||||
Server = $MIRROR
|
||||
[community]
|
||||
Server = $MIRROR
|
||||
EOF
|
||||
|
||||
# setup the image (in a subshell for trap management)
|
||||
(
|
||||
loopdev=''
|
||||
qemu_img_losetup "$tmpfile" || return
|
||||
|
||||
dd if=/dev/zero of="$loopdev" bs=1M count=8 || return
|
||||
"qemu_img_partition_and_mount_for_$ARCH" "$loopdev" "$TOPBUILDDIR"/mnt || return
|
||||
|
||||
qemu_setup_user_static "$TOPBUILDDIR"/mnt || return
|
||||
|
||||
pacstrap -GMcd -C "$TOPBUILDDIR/pacman.conf.$ARCH" "$TOPBUILDDIR"/mnt || return
|
||||
|
||||
"qemu_img_finalize_for_$ARCH" "$TOPBUILDDIR"/mnt || return
|
||||
) || return
|
||||
|
||||
mv "$tmpfile" "$1"
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
#!/bin/bash
|
||||
##############################################################################
|
||||
# parabola-imagebuilder #
|
||||
# #
|
||||
# Copyright (C) 2018 Andreas Grapentin #
|
||||
# #
|
||||
# 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/>. #
|
||||
##############################################################################
|
||||
|
||||
check_exe() {
|
||||
local OPTIND o r=
|
||||
while getopts "r" o; do
|
||||
case "$o" in
|
||||
r) r=yes ;;
|
||||
*) die -e "$ERROR_INVOCATION" "Usage: ${FUNCNAME[0]} [-r] program ..." ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
local v res=0
|
||||
for v in "$@"; do
|
||||
echo -n "checking for $v in \$PATH ... "
|
||||
|
||||
local have_exe=yes
|
||||
type -p "$v" >/dev/null || have_exe=no
|
||||
echo $have_exe
|
||||
|
||||
if [ "x$have_exe" != "xyes" ]; then
|
||||
[ "x$r" == "xyes" ] && die -e "$ERROR_MISSING" "missing $v in \$PATH"
|
||||
res="$ERROR_MISSING"
|
||||
fi
|
||||
done
|
||||
|
||||
return "$res"
|
||||
}
|
||||
|
||||
check_file() {
|
||||
local OPTIND o r=
|
||||
while getopts "r" o; do
|
||||
case "$o" in
|
||||
r) r=yes ;;
|
||||
*) die -e "$ERROR_INVOCATION" "Usage: ${FUNCNAME[0]} [-r] file ..." ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
local v res=0
|
||||
for v in "$@"; do
|
||||
echo -n "checking for $v ... "
|
||||
|
||||
local have_file=yes
|
||||
[ -f "$v" ] || have_file=no
|
||||
echo $have_file
|
||||
|
||||
if [ "x$have_file" != "xyes" ]; then
|
||||
[ "x$r" == "xyes" ] && die -e "$ERROR_MISSING" "missing $v in filesystem"
|
||||
res="$ERROR_MISSING"
|
||||
fi
|
||||
done
|
||||
|
||||
return "$res"
|
||||
}
|
||||
|
||||
check_gpgkey() {
|
||||
local OPTIND o r=
|
||||
while getopts "r" o; do
|
||||
case "$o" in
|
||||
r) r=yes ;;
|
||||
*) die -e "$ERROR_INVOCATION" "Usage: ${FUNCNAME[0]} [-r] key" ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
local v res=0
|
||||
for v in "$@"; do
|
||||
echo -n "checking for key $v ... "
|
||||
|
||||
local have_key=yes
|
||||
sudo -u "$SUDO_USER" gpg --list-keys "$v" &>/dev/null || have_key=no
|
||||
echo $have_key
|
||||
|
||||
if [ "x$have_key" != "xyes" ]; then
|
||||
[ "x$r" == "xyes" ] && die -e "$ERROR_MISSING" "missing $v in keyring"
|
||||
res="$ERROR_MISSING"
|
||||
fi
|
||||
done
|
||||
|
||||
return "$res"
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
#!/bin/bash
|
||||
##############################################################################
|
||||
# parabola-imagebuilder #
|
||||
# #
|
||||
# Copyright (C) 2018 Andreas Grapentin #
|
||||
# #
|
||||
# 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/>. #
|
||||
##############################################################################
|
||||
|
||||
# shellcheck source=src/shared/feedback.sh
|
||||
. "$TOPSRCDIR"/shared/feedback.sh
|
||||
# shellcheck source=src/shared/checks.sh
|
||||
. "$TOPSRCDIR"/shared/checks.sh
|
||||
|
||||
retry() {
|
||||
local OPTIND o n=5 s=60
|
||||
while getopts "n:s:" o; do
|
||||
case "$o" in
|
||||
n) n="$OPTARG" ;;
|
||||
s) s="$OPTARG" ;;
|
||||
*) die -e $ERROR_INVOCATION "Usage: ${FUNCNAME[0]} [-n tries] [-s delay] cmd ..." ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
for _ in $(seq "$((n - 1))"); do
|
||||
"$@" && return 0
|
||||
sleep "$s"
|
||||
done
|
||||
"$@" || return
|
||||
}
|
||||
|
||||
# appends a command to a trap
|
||||
# source: https://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal
|
||||
#
|
||||
# - 1st arg: code to add
|
||||
# - remaining args: names of traps to modify
|
||||
#
|
||||
trap_add() {
|
||||
trap_add_cmd=$1; shift || fatal "${FUNCNAME[0]} usage error"
|
||||
for trap_add_name in "$@"; do
|
||||
trap -- "$(
|
||||
# helper fn to get existing trap command from output
|
||||
# of trap -p
|
||||
extract_trap_cmd() { printf '%s\n' "$3"; }
|
||||
# print the new trap command
|
||||
printf '%s\n' "${trap_add_cmd}"
|
||||
# print existing trap command with newline
|
||||
eval "extract_trap_cmd $(trap -p "${trap_add_name}")"
|
||||
)" "${trap_add_name}" \
|
||||
|| fatal "unable to add to trap ${trap_add_name}"
|
||||
done
|
||||
}
|
||||
# set the trace attribute for the above function. this is
|
||||
# required to modify DEBUG or RETURN traps because functions don't
|
||||
# inherit them unless the trace attribute is set
|
||||
declare -f -t trap_add
|
@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
##############################################################################
|
||||
# parabola-imagebuilder #
|
||||
# #
|
||||
# Copyright (C) 2018 Andreas Grapentin #
|
||||
# #
|
||||
# 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/>. #
|
||||
##############################################################################
|
||||
|
||||
# error codes
|
||||
export ERROR_UNSPECIFIED=1
|
||||
export ERROR_INVOCATION=2
|
||||
export ERROR_MISSING=3
|
||||
export ERROR_BUILDFAIL=4
|
||||
export ERROR_KEYFAIL=5
|
||||
|
||||
# messaging functions
|
||||
msg() {
|
||||
echo "$(tput bold)$(tput setf 2)==>$(tput setf 7) $*$(tput sgr0)";
|
||||
}
|
||||
|
||||
error() {
|
||||
echo "$(tput bold)$(tput setf 4)==> ERROR:$(tput setf 7) $*$(tput sgr0)" 1>&2
|
||||
}
|
||||
|
||||
die() {
|
||||
local OPTIND o e="$ERROR_UNSPECIFIED"
|
||||
while getopts "e:" o; do
|
||||
case "$o" in
|
||||
e) e="$OPTARG" ;;
|
||||
*) die -e "$ERROR_INVOCATION" "Usage: ${FUNCNAME[0]} [-e status] msg ..." ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
error "$@"
|
||||
trap - ERR
|
||||
exit "$e"
|
||||
}
|
||||
trap 'die "unknown error"' ERR
|
Loading…
Reference in New Issue
Block a user