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
|
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 =`
|
the script will attempt to bootstrap a virtual machine of the selected
|
||||||
line can go here.
|
archituecture in the output file specified. If the output file already exists,
|
||||||
default: https://redirector.parabola.nu/\$repo/os/\$arch}
|
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
|
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
|
workdir="$(mktemp -d -t pvm-XXXXXXXXXX)" || return
|
||||||
loopdev="$(sudo losetup -fLP --show "$1")" || 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() {
|
pvm_umount() {
|
||||||
@ -106,7 +107,7 @@ pvm_native_arch() {
|
|||||||
setarch "$arch" /bin/true 2>/dev/null || return
|
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 we're not running on X / wayland, disable graphics
|
||||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-nographic); fi
|
if [ -z "$DISPLAY" ]; then qemu_args+=(-nographic); fi
|
||||||
|
|
||||||
@ -117,8 +118,7 @@ pvm_build_qemu_args() {
|
|||||||
case "$2" in
|
case "$2" in
|
||||||
i386|x86_64|ppc64)
|
i386|x86_64|ppc64)
|
||||||
qemu_args+=(-m 1G "$1")
|
qemu_args+=(-m 1G "$1")
|
||||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-append "console=ttyS0"); fi
|
# unmount the unneeded virtual drive early
|
||||||
# unmount the drive early
|
|
||||||
pvm_umount ;;
|
pvm_umount ;;
|
||||||
arm)
|
arm)
|
||||||
qemu_args+=(
|
qemu_args+=(
|
||||||
@ -128,9 +128,8 @@ pvm_build_qemu_args() {
|
|||||||
-kernel "$workdir"/vmlinuz-linux-libre
|
-kernel "$workdir"/vmlinuz-linux-libre
|
||||||
-dtb "$workdir"/dtbs/linux-libre/vexpress-v2p-ca9.dtb
|
-dtb "$workdir"/dtbs/linux-libre/vexpress-v2p-ca9.dtb
|
||||||
-initrd "$workdir"/initramfs-linux-libre.img
|
-initrd "$workdir"/initramfs-linux-libre.img
|
||||||
-append " rw root=/dev/mmcblk0p3"
|
-append "console=tty0 console=ttyAMA0 rw root=/dev/mmcblk0p3"
|
||||||
-drive "if=sd,driver=raw,cache=writeback,file=$1")
|
-drive "if=sd,driver=raw,cache=writeback,file=$1") ;;
|
||||||
if [ -z "$DISPLAY" ]; then qemu_args+=(-append " console=ttyAMA0"); fi ;;
|
|
||||||
riscv64)
|
riscv64)
|
||||||
qemu_args+=(
|
qemu_args+=(
|
||||||
-machine virt
|
-machine virt
|
||||||
@ -143,7 +142,9 @@ pvm_build_qemu_args() {
|
|||||||
-device "virtio-rng-device,rng=rng0"
|
-device "virtio-rng-device,rng=rng0"
|
||||||
-device "virtio-net-device,netdev=usernet"
|
-device "virtio-net-device,netdev=usernet"
|
||||||
-netdev "user,id=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"
|
error "%s: unable to determine default qemu args" "$1"
|
||||||
return "$EXIT_FAILURE" ;;
|
return "$EXIT_FAILURE" ;;
|
||||||
@ -152,7 +153,7 @@ pvm_build_qemu_args() {
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
if [ "$(id -u)" -eq 0 ]; then
|
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"
|
exit "$EXIT_NOPERMISSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -187,7 +188,7 @@ main() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local qemu_args=()
|
local qemu_args=()
|
||||||
pvm_build_qemu_args "$imagefile" "$arch" || exit
|
pvm_guess_qemu_args "$imagefile" "$arch" || exit
|
||||||
qemu_args+=("$@")
|
qemu_args+=("$@")
|
||||||
|
|
||||||
(set -x; qemu-system-"$arch" "${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