uniform return values and better logging
This commit is contained in:
parent
50d32d2cba
commit
906535e29d
@ -39,7 +39,9 @@ usage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pvm_mount() {
|
pvm_mount() {
|
||||||
if ! file "$imagefile" | grep -q ' DOS/MBR '; then
|
if file "$imagefile" | grep -q ' DOS/MBR '; then
|
||||||
|
msg "mounting filesystems"
|
||||||
|
else
|
||||||
error "%s: does not seem to be a raw qemu image." "$imagefile"
|
error "%s: does not seem to be a raw qemu image." "$imagefile"
|
||||||
return "$EXIT_FAILURE"
|
return "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
@ -60,7 +62,9 @@ pvm_mount() {
|
|||||||
sudo umount "$workdir"
|
sudo umount "$workdir"
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "$rootpart" ]; then
|
if [ -n "$rootpart" ]; then
|
||||||
|
msg "found root filesystem partition: %s" "$rootpart"
|
||||||
|
else
|
||||||
error "%s: unable to determine root partition." "$imagefile"
|
error "%s: unable to determine root partition." "$imagefile"
|
||||||
return "$EXIT_FAILURE"
|
return "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
@ -68,7 +72,9 @@ pvm_mount() {
|
|||||||
# find the boot partition
|
# find the boot partition
|
||||||
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 [ -n "$bootpart" ]; then
|
||||||
|
msg "found boot filesystem partition: %s" "$bootpart"
|
||||||
|
else
|
||||||
error "%s: unable to determine boot partition." "$imagefile"
|
error "%s: unable to determine boot partition." "$imagefile"
|
||||||
return "$EXIT_FAILURE"
|
return "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
@ -78,6 +84,8 @@ pvm_mount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pvm_umount() {
|
pvm_umount() {
|
||||||
|
msg "un-mounting filesystems"
|
||||||
|
|
||||||
trap - INT TERM EXIT
|
trap - INT TERM EXIT
|
||||||
|
|
||||||
[ -n "$workdir" ] && (sudo umount -R "$workdir"; rmdir "$workdir")
|
[ -n "$workdir" ] && (sudo umount -R "$workdir"; rmdir "$workdir")
|
||||||
@ -98,7 +106,7 @@ main() {
|
|||||||
case "$arg" in
|
case "$arg" in
|
||||||
h) usage; return "$EXIT_SUCCESS";;
|
h) usage; return "$EXIT_SUCCESS";;
|
||||||
o) output="$OPTARG";;
|
o) output="$OPTARG";;
|
||||||
*) usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
*) error "invalid argument: %s\n" "$arg"; usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
local shiftlen=$(( OPTIND - 1 ))
|
local shiftlen=$(( OPTIND - 1 ))
|
||||||
@ -140,6 +148,7 @@ main() {
|
|||||||
# archlinuxarm and the generated parabola tarball through:
|
# archlinuxarm and the generated parabola tarball through:
|
||||||
#
|
#
|
||||||
# `tar -tf <tarball> | sort`
|
# `tar -tf <tarball> | sort`
|
||||||
|
msg "imploding tarball"
|
||||||
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
|
||||||
|
@ -28,23 +28,23 @@ usage() {
|
|||||||
print "USAGE: %s [-h] <img> [qemu-args ...]" "${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 instance is assigned
|
created using pvmbootstrap. The started instances are assigned
|
||||||
${DEF_RAM_MB}MB of RAM and one SMP core."
|
${DEF_RAM_MB}MB of 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##*/} ./an.img"
|
echo " DISPLAY= ${0##*/} 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##*/} ./an.img -m 2G -smp 2"
|
echo " ${0##*/} 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"
|
||||||
@ -59,15 +59,17 @@ pvm_mount() {
|
|||||||
return "$EXIT_FAILURE"
|
return "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
msg "mounting filesystems"
|
||||||
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 "$EXIT_FAILURE"
|
||||||
loopdev="$(sudo losetup -fLP --show "$1")" || return
|
loopdev="$(sudo losetup -fLP --show "$1")" || return "$EXIT_FAILURE"
|
||||||
sudo mount "$loopdev"p1 "$workdir" \
|
sudo mount "$loopdev"p1 "$workdir" \
|
||||||
|| sudo mount "$loopdev"p2 "$workdir" || return
|
|| sudo mount "$loopdev"p2 "$workdir" || return "$EXIT_FAILURE"
|
||||||
}
|
}
|
||||||
|
|
||||||
pvm_umount() {
|
pvm_umount() {
|
||||||
|
msg "un-mounting filesystems"
|
||||||
trap - INT TERM EXIT
|
trap - INT TERM EXIT
|
||||||
|
|
||||||
[ -n "$workdir" ] && (sudo umount "$workdir"; rmdir "$workdir")
|
[ -n "$workdir" ] && (sudo umount "$workdir"; rmdir "$workdir")
|
||||||
@ -81,29 +83,29 @@ pvm_probe_arch() {
|
|||||||
kernel=$(find "$workdir" -maxdepth 1 -type f -iname '*vmlinu*' | head -n1)
|
kernel=$(find "$workdir" -maxdepth 1 -type f -iname '*vmlinu*' | head -n1)
|
||||||
if [ -z "$kernel" ]; then
|
if [ -z "$kernel" ]; then
|
||||||
warning "%s: unable to find kernel binary" "$1"
|
warning "%s: unable to find kernel binary" "$1"
|
||||||
return
|
return "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# attempt to get kernel arch from elf header
|
# attempt to get kernel arch from elf header
|
||||||
arch="$(readelf -h "$kernel" 2>/dev/null | grep Machine | awk '{print $2}')"
|
arch="$(readelf -h "$kernel" 2>/dev/null | grep Machine | awk '{print $2}')"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
PowerPC64) arch=ppc64; return;;
|
PowerPC64) arch=ppc64; return "$EXIT_SUCCESS";;
|
||||||
RISC-V) arch=riscv64; return;;
|
RISC-V ) arch=riscv64; return "$EXIT_SUCCESS";;
|
||||||
* ) arch="";;
|
* ) arch="";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# attempt to get kernel arch from objdump
|
# attempt to get kernel arch from objdump
|
||||||
arch="$(objdump -f "$kernel" 2>/dev/null | grep architecture: | awk '{print $2}' | tr -d ',')"
|
arch="$(objdump -f "$kernel" 2>/dev/null | grep architecture: | awk '{print $2}' | tr -d ',')"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
i386) arch=i386; return;;
|
i386 ) arch=i386; return "$EXIT_SUCCESS";;
|
||||||
i386:*) arch=x86_64; return;;
|
i386:*) arch=x86_64; return "$EXIT_SUCCESS";;
|
||||||
* ) arch="";;
|
* ) arch="";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# attempt to get kernel arch from file magic
|
# attempt to get kernel arch from file magic
|
||||||
arch="$(file "$kernel")"
|
arch="$(file "$kernel")"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
*"ARM boot executable"*) arch=arm; return;;
|
*"ARM boot executable"*) arch=arm; return "$EXIT_SUCCESS";;
|
||||||
* ) arch="";;
|
* ) arch="";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@ -173,23 +175,24 @@ main() {
|
|||||||
while getopts 'h' arg; do
|
while getopts 'h' arg; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
h) usage; return "$EXIT_SUCCESS";;
|
h) usage; return "$EXIT_SUCCESS";;
|
||||||
*) usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
*) error "invalid argument: %s\n" "$arg"; usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
local shiftlen=$(( OPTIND - 1 ))
|
local shiftlen=$(( OPTIND - 1 ))
|
||||||
shift $shiftlen
|
shift $shiftlen
|
||||||
local imagefile="$1"
|
local imagefile="$1"
|
||||||
shift
|
shift
|
||||||
[ ! -e "$imagefile" ] && error "%s: file not found" "$imagefile" && exit "$EXIT_FAILURE"
|
[ ! -n "$imagefile" ] && error "no image file specified" && exit "$EXIT_FAILURE"
|
||||||
|
[ ! -e "$imagefile" ] && error "image file not found: '%s'" "$imagefile" && exit "$EXIT_FAILURE"
|
||||||
|
|
||||||
|
msg "initializing ...."
|
||||||
local workdir loopdev
|
local workdir loopdev
|
||||||
pvm_mount "$imagefile" || exit
|
pvm_mount "$imagefile" || exit
|
||||||
|
|
||||||
local arch
|
local arch
|
||||||
pvm_probe_arch "$imagefile" || exit
|
pvm_probe_arch "$imagefile" || exit
|
||||||
|
|
||||||
if [ -z "$arch" ]; then
|
if [ -z "$arch" ]; then
|
||||||
error "%s: arch is unknown" "$imagefile"
|
error "image arch is unknown: '%s'" "$arch"
|
||||||
exit "$EXIT_FAILURE"
|
exit "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -197,9 +200,11 @@ main() {
|
|||||||
pvm_guess_qemu_args "$imagefile" "$arch" || exit
|
pvm_guess_qemu_args "$imagefile" "$arch" || exit
|
||||||
qemu_args+=("$@")
|
qemu_args+=("$@")
|
||||||
|
|
||||||
|
msg "booting ...."
|
||||||
(set -x; qemu-system-"$arch" "${qemu_args[@]}")
|
(set -x; qemu-system-"$arch" "${qemu_args[@]}")
|
||||||
|
|
||||||
# clean up the terminal, in case SeaBIOS did something weird
|
# clean up the terminal, in case SeaBIOS did something weird
|
||||||
|
msg "cleaning up ...."
|
||||||
echo -n "[?7h[0m"
|
echo -n "[?7h[0m"
|
||||||
pvm_umount
|
pvm_umount
|
||||||
}
|
}
|
||||||
|
@ -65,25 +65,26 @@ usage() {
|
|||||||
pvm_native_arch() {
|
pvm_native_arch() {
|
||||||
local arch=$( [[ "$1" =~ arm.* ]] && echo 'armv7l' || echo "$1" )
|
local arch=$( [[ "$1" =~ arm.* ]] && echo 'armv7l' || echo "$1" )
|
||||||
|
|
||||||
setarch "$arch" /bin/true 2>/dev/null || return
|
setarch "$arch" /bin/true 2>/dev/null || return "$EXIT_FAILURE"
|
||||||
}
|
}
|
||||||
|
|
||||||
pvm_bootstrap() {
|
pvm_bootstrap() {
|
||||||
msg "%s: starting image creation for %s" "$file" "$arch"
|
msg "starting creation of %s image: %s" "$arch" "$file"
|
||||||
|
|
||||||
# create the raw image file
|
# create the raw image file
|
||||||
qemu-img create -f raw "$file" "${ImgSizeGb}G" || return
|
qemu-img create -f raw "$file" "${ImgSizeGb}G" || return "$EXIT_FAILURE"
|
||||||
|
|
||||||
# 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 "$EXIT_FAILURE"
|
||||||
loopdev="$(sudo losetup -fLP --show "$file")" || return
|
loopdev="$(sudo losetup -fLP --show "$file")" || return "$EXIT_FAILURE"
|
||||||
sudo dd if=/dev/zero of="$loopdev" bs=1M count=8 || return
|
sudo dd if=/dev/zero of="$loopdev" bs=1M count=8 || return "$EXIT_FAILURE"
|
||||||
|
|
||||||
# partition
|
# partition
|
||||||
|
msg "partitioning blank image"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
i686|x86_64)
|
i686|x86_64)
|
||||||
sudo parted -s "$loopdev" \
|
sudo parted -s "$loopdev" \
|
||||||
@ -92,21 +93,21 @@ pvm_bootstrap() {
|
|||||||
set 1 bios_grub on \
|
set 1 bios_grub on \
|
||||||
mkpart primary ext2 2MiB 514MiB \
|
mkpart primary ext2 2MiB 514MiB \
|
||||||
mkpart primary linux-swap 514MiB 4610MiB \
|
mkpart primary linux-swap 514MiB 4610MiB \
|
||||||
mkpart primary ext4 4610MiB 100% || return ;;
|
mkpart primary ext4 4610MiB 100% || return "$EXIT_FAILURE" ;;
|
||||||
armv7h)
|
armv7h)
|
||||||
sudo parted -s "$loopdev" \
|
sudo parted -s "$loopdev" \
|
||||||
mklabel gpt \
|
mklabel gpt \
|
||||||
mkpart ESP fat32 1MiB 513MiB \
|
mkpart ESP fat32 1MiB 513MiB \
|
||||||
set 1 boot on \
|
set 1 boot on \
|
||||||
mkpart primary linux-swap 513MiB 4609MiB \
|
mkpart primary linux-swap 513MiB 4609MiB \
|
||||||
mkpart primary ext4 4609MiB 100% || return ;;
|
mkpart primary ext4 4609MiB 100% || return "$EXIT_FAILURE" ;;
|
||||||
ppc64le|riscv64)
|
ppc64le|riscv64)
|
||||||
sudo parted -s "$loopdev" \
|
sudo parted -s "$loopdev" \
|
||||||
mklabel gpt \
|
mklabel gpt \
|
||||||
mkpart primary ext2 1MiB 513MiB \
|
mkpart primary ext2 1MiB 513MiB \
|
||||||
set 1 boot on \
|
set 1 boot on \
|
||||||
mkpart primary linux-swap 513MiB 4609MiB \
|
mkpart primary linux-swap 513MiB 4609MiB \
|
||||||
mkpart primary ext4 4609MiB 100% || return ;;
|
mkpart primary ext4 4609MiB 100% || return "$EXIT_FAILURE" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# refresh partition data
|
# refresh partition data
|
||||||
@ -114,35 +115,37 @@ pvm_bootstrap() {
|
|||||||
|
|
||||||
# make file systems
|
# make file systems
|
||||||
local swapdev
|
local swapdev
|
||||||
|
msg "creating target filesystems"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
i686|x86_64)
|
i686|x86_64)
|
||||||
sudo mkfs.ext2 "$loopdev"p2 || return
|
sudo mkfs.ext2 "$loopdev"p2 || return "$EXIT_FAILURE"
|
||||||
sudo mkswap "$loopdev"p3 || return
|
sudo mkswap "$loopdev"p3 || return "$EXIT_FAILURE"
|
||||||
sudo mkfs.ext4 "$loopdev"p4 || return
|
sudo mkfs.ext4 "$loopdev"p4 || return "$EXIT_FAILURE"
|
||||||
swapdev="$loopdev"p3 ;;
|
swapdev="$loopdev"p3 ;;
|
||||||
armv7h)
|
armv7h)
|
||||||
sudo mkfs.vfat -F 32 "$loopdev"p1 || return
|
sudo mkfs.vfat -F 32 "$loopdev"p1 || return "$EXIT_FAILURE"
|
||||||
sudo mkswap "$loopdev"p2 || return
|
sudo mkswap "$loopdev"p2 || return "$EXIT_FAILURE"
|
||||||
sudo mkfs.ext4 "$loopdev"p3 || return
|
sudo mkfs.ext4 "$loopdev"p3 || return "$EXIT_FAILURE"
|
||||||
swapdev="$loopdev"p2 ;;
|
swapdev="$loopdev"p2 ;;
|
||||||
ppc64le|riscv64)
|
ppc64le|riscv64)
|
||||||
sudo mkfs.ext2 "$loopdev"p1 || return
|
sudo mkfs.ext2 "$loopdev"p1 || return "$EXIT_FAILURE"
|
||||||
sudo mkswap "$loopdev"p2 || return
|
sudo mkswap "$loopdev"p2 || return "$EXIT_FAILURE"
|
||||||
sudo mkfs.ext4 "$loopdev"p3 || return
|
sudo mkfs.ext4 "$loopdev"p3 || return "$EXIT_FAILURE"
|
||||||
swapdev="$loopdev"p2 ;;
|
swapdev="$loopdev"p2 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# mount partitions
|
# mount partitions
|
||||||
|
msg "mounting target 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 "$EXIT_FAILURE"
|
||||||
sudo mkdir -p "$workdir"/boot || return
|
sudo mkdir -p "$workdir"/boot || return "$EXIT_FAILURE"
|
||||||
sudo mount "$loopdev"p2 "$workdir"/boot || return
|
sudo mount "$loopdev"p2 "$workdir"/boot || return "$EXIT_FAILURE"
|
||||||
;;
|
;;
|
||||||
armv7h|ppc64le|riscv64)
|
armv7h|ppc64le|riscv64)
|
||||||
sudo mount "$loopdev"p3 "$workdir" || return
|
sudo mount "$loopdev"p3 "$workdir" || return "$EXIT_FAILURE"
|
||||||
sudo mkdir -p "$workdir"/boot || return
|
sudo mkdir -p "$workdir"/boot || return "$EXIT_FAILURE"
|
||||||
sudo mount "$loopdev"p1 "$workdir"/boot || return
|
sudo mount "$loopdev"p1 "$workdir"/boot || return "$EXIT_FAILURE"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@ -158,18 +161,20 @@ pvm_bootstrap() {
|
|||||||
local qemu_user_static=$(sudo grep -l -F -e "interpreter /usr/bin/qemu-$qemu_arch-" \
|
local qemu_user_static=$(sudo grep -l -F -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
|
if [[ -n "$qemu_user_static" ]]; then
|
||||||
error "%s: missing qemu-user-static for %s" "$file" "$arch"
|
msg "found qemu-user-static for %s" "$arch"
|
||||||
|
else
|
||||||
|
error "missing qemu-user-static for %s" "$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 "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# prepare pacstrap config
|
# prepare pacstrap config
|
||||||
local pacconf repos
|
local pacconf repos
|
||||||
pacconf="$(mktemp -t pvm-pacconf-XXXXXXXXXX)" || return
|
pacconf="$(mktemp -t pvm-pacconf-XXXXXXXXXX)" || return "$EXIT_FAILURE"
|
||||||
repos=('libre' 'core' 'extra' 'community' 'pcr')
|
repos=('libre' 'core' 'extra' 'community' 'pcr')
|
||||||
echo -e "[options]\nArchitecture = $arch\n\n" > "$pacconf"
|
echo -e "[options]\nArchitecture = $arch\n\n" > "$pacconf"
|
||||||
for repo in ${repos[@]}; do echo -e "[$repo]\nServer = $Mirror\n" >> "$pacconf"; done;
|
for repo in ${repos[@]}; do echo -e "[$repo]\nServer = $Mirror\n" >> "$pacconf"; done;
|
||||||
@ -203,10 +208,12 @@ pvm_bootstrap() {
|
|||||||
local pkg_guest_cache=(ca-certificates-utils)
|
local pkg_guest_cache=(ca-certificates-utils)
|
||||||
|
|
||||||
# pacstrap! :)
|
# pacstrap! :)
|
||||||
sudo pacstrap -GMc -C "$pacconf" "$workdir" "${pkgs[@]}" || return
|
msg "installing packages into the work chroot"
|
||||||
sudo pacstrap -GM -C "$pacconf" "$workdir" "${pkg_guest_cache[@]}" || return
|
sudo pacstrap -GMc -C "$pacconf" "$workdir" "${pkgs[@]}" || return "$EXIT_FAILURE"
|
||||||
|
sudo pacstrap -GM -C "$pacconf" "$workdir" "${pkg_guest_cache[@]}" || return "$EXIT_FAILURE"
|
||||||
|
|
||||||
# create an fstab
|
# create an fstab
|
||||||
|
msg "generating /etc/fstab"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
riscv64) ;;
|
riscv64) ;;
|
||||||
*)
|
*)
|
||||||
@ -217,14 +224,16 @@ pvm_bootstrap() {
|
|||||||
sudo swapon --all ;;
|
sudo swapon --all ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# produce a hostname
|
# configure the system envoronment
|
||||||
echo "parabola" | sudo tee "$workdir"/etc/hostname
|
local hostname='parabola'
|
||||||
|
local lang='en_US.UTF-8'
|
||||||
# produce an /etc/locale.conf
|
msg "configuring system envoronment"
|
||||||
echo "LANG=en_US.UTF-8" | sudo tee "$workdir"/etc/locale.conf
|
echo "/etc/hostname: " ; echo $hostname | sudo tee "$workdir"/etc/hostname ;
|
||||||
sudo sed -i 's/#en_US.UTF-8/en_US.UTF-8/' "$workdir"/etc/locale.gen
|
echo "/etc/locale.conf: " ; echo "LANG=$lang" | sudo tee "$workdir"/etc/locale.conf ;
|
||||||
|
sudo sed -i "s/#${lang}/${lang}/" "$workdir"/etc/locale.gen
|
||||||
|
|
||||||
# install a boot loader
|
# install a boot loader
|
||||||
|
msg "installing boot loader"
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
i686|x86_64)
|
i686|x86_64)
|
||||||
local grub_def_file="$workdir"/etc/default/grub
|
local grub_def_file="$workdir"/etc/default/grub
|
||||||
@ -232,48 +241,57 @@ pvm_bootstrap() {
|
|||||||
# 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\"/" "$grub_def_file" || return
|
sudo sed -i "s/.*$field=.*/$field=\"$value\"/" "$grub_def_file" || return "$EXIT_FAILURE"
|
||||||
# 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/" "$grub_def_file" || return
|
sudo sed -i "s/.*$field=.*/$field=$value/" "$grub_def_file" || return "$EXIT_FAILURE"
|
||||||
# install grub to the VM
|
# install grub to the VM
|
||||||
sudo arch-chroot "$workdir" grub-install "$loopdev" || return
|
sudo arch-chroot "$workdir" grub-install "$loopdev" || return "$EXIT_FAILURE"
|
||||||
sudo arch-chroot "$workdir" grub-mkconfig -o $grub_cfg_file || return
|
sudo arch-chroot "$workdir" grub-mkconfig -o $grub_cfg_file || return "$EXIT_FAILURE"
|
||||||
|
;;
|
||||||
|
armv7h)
|
||||||
|
echo "(armv7h has no boot loader)"
|
||||||
;;
|
;;
|
||||||
riscv64)
|
riscv64)
|
||||||
# FIXME: for the time being, use fedora bbl to boot
|
# FIXME: for the time being, use fedora bbl to boot
|
||||||
|
warning "(riscv64 requires a blob - downloading it now)"
|
||||||
local bbl_url=https://fedorapeople.org/groups/risc-v/disk-images/bbl
|
local bbl_url=https://fedorapeople.org/groups/risc-v/disk-images/bbl
|
||||||
sudo wget $bbl_url -O "$workdir"/boot/bbl || return
|
sudo wget $bbl_url -O "$workdir"/boot/bbl || return "$EXIT_FAILURE"
|
||||||
|
;;
|
||||||
|
ppc64le)
|
||||||
|
# FIXME: what about ppc64le?
|
||||||
|
echo "(ppc64le has no boot loader)"
|
||||||
;;
|
;;
|
||||||
# armv7h has no boot loader.
|
|
||||||
# FIXME: what about ppc64le
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# regenerate the initcpio, skipping the autodetect hook
|
# regenerate the initcpio, skipping the autodetect hook
|
||||||
local preset_file="$workdir"/etc/mkinitcpio.d/linux-libre.preset
|
local kernel='linux-libre'
|
||||||
sudo cp "$preset_file"{,.backup} || return
|
local preset_file="$workdir"/etc/mkinitcpio.d/${kernel}.preset
|
||||||
echo "default_options=\"-S autodetect\"" | sudo tee -a "$preset_file" || return
|
local default_options="default_options=\"-S autodetect\""
|
||||||
sudo arch-chroot "$workdir" mkinitcpio -p linux-libre || return
|
msg "regenerating initcpio for kernel: '${kernel}'"
|
||||||
sudo mv "$preset_file"{.backup,} || return
|
sudo cp "$preset_file"{,.backup} || return "$EXIT_FAILURE"
|
||||||
|
echo "$default_options" | sudo tee -a "$preset_file" > /dev/null || return "$EXIT_FAILURE"
|
||||||
# disable audit
|
sudo arch-chroot "$workdir" mkinitcpio -p ${kernel} || return "$EXIT_FAILURE"
|
||||||
sudo arch-chroot "$workdir" systemctl mask systemd-journald-audit.socket
|
sudo mv "$preset_file"{.backup,} || return "$EXIT_FAILURE"
|
||||||
|
|
||||||
# initialize the pacman keyring
|
# initialize the pacman keyring
|
||||||
|
msg "initializing the pacman keyring"
|
||||||
sudo arch-chroot "$workdir" pacman-key --init
|
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 archlinux archlinux32 archlinuxarm parabola
|
||||||
|
|
||||||
# enable the entropy daemon, to avoid stalling https
|
|
||||||
sudo arch-chroot "$workdir" systemctl enable haveged.service
|
|
||||||
|
|
||||||
# push hooks into the image
|
# push hooks into the image
|
||||||
|
msg "preparing hooks"
|
||||||
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'
|
local hooks_success_msg="[hooks.sh] pre-init hooks successful"
|
||||||
|
echo "hooks.sh:"
|
||||||
|
sudo tee "$workdir"/root/hooks.sh << EOF
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
echo "[hooks.sh] boot successful - configuring ...."
|
||||||
|
|
||||||
systemctl disable preinit.service
|
systemctl disable preinit.service
|
||||||
|
|
||||||
# generate the locale
|
# generate the locale
|
||||||
@ -287,8 +305,8 @@ 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 "[hooks.sh] running hook: '\$(basename \$hook)'"
|
||||||
source "$hook" || return
|
source "\$hook" || return
|
||||||
done
|
done
|
||||||
|
|
||||||
# clean up after yourself
|
# clean up after yourself
|
||||||
@ -299,10 +317,11 @@ rm -f /var/cache/pacman/pkg/*
|
|||||||
rm -f /root/.bash_history
|
rm -f /root/.bash_history
|
||||||
|
|
||||||
# report success :)
|
# report success :)
|
||||||
echo "preinit hooks successful"
|
echo "$hooks_success_msg"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# create a preinit service to run the hooks
|
# create a pre-init service to run the hooks
|
||||||
|
echo "preinit.service:"
|
||||||
sudo tee "$workdir"/usr/lib/systemd/system/preinit.service << 'EOF'
|
sudo tee "$workdir"/usr/lib/systemd/system/preinit.service << 'EOF'
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Oneshot VM Preinit
|
Description=Oneshot VM Preinit
|
||||||
@ -313,19 +332,26 @@ StandardOutput=journal+console
|
|||||||
StandardError=journal+console
|
StandardError=journal+console
|
||||||
ExecStart=/usr/bin/bash /root/hooks.sh
|
ExecStart=/usr/bin/bash /root/hooks.sh
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
ExecStopPost=echo "powering off"
|
||||||
ExecStopPost=shutdown -r now
|
ExecStopPost=shutdown -r now
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# enable the preinit service
|
# configure services
|
||||||
sudo arch-chroot "$workdir" systemctl enable preinit.service || return
|
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"
|
||||||
|
|
||||||
# unmount everything
|
# unmount everything
|
||||||
pvm_cleanup
|
pvm_cleanup
|
||||||
|
|
||||||
# boot the machine to run the preinit hooks
|
# boot the machine to run the pre-init hooks
|
||||||
local pvmboot_cmd
|
local pvmboot_cmd
|
||||||
local qemu_flags=(-no-reboot)
|
local qemu_flags=(-no-reboot)
|
||||||
if [ -f "./src/pvmboot.sh" ]; then
|
if [ -f "./src/pvmboot.sh" ]; then
|
||||||
@ -333,13 +359,13 @@ EOF
|
|||||||
elif type -p pvmboot &>/dev/null; then
|
elif type -p pvmboot &>/dev/null; then
|
||||||
pvmboot_cmd=('pvmboot')
|
pvmboot_cmd=('pvmboot')
|
||||||
else
|
else
|
||||||
error "%s: pvmboot not available -- unable to run hooks" "$file"
|
error "pvmboot not available -- unable to run hooks"
|
||||||
return "$EXIT_FAILURE"
|
return "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
pvmboot_cmd+=("$file" "${qemu_flags[@]}")
|
pvmboot_cmd+=("$file" "${qemu_flags[@]}")
|
||||||
exec 3>&1
|
exec 3>&1
|
||||||
msg "booting the machine to run the pre-init hooks"
|
msg "booting the machine to run the pre-init hooks"
|
||||||
DISPLAY='' "${pvmboot_cmd[@]}" | tee /dev/fd/3 | grep -q "preinit hooks successful"
|
DISPLAY='' "${pvmboot_cmd[@]}" | tee /dev/fd/3 | grep -q -F "$hooks_success_msg"
|
||||||
local res=$?
|
local res=$?
|
||||||
exec 3>&-
|
exec 3>&-
|
||||||
! (( $res )) || error "%s: failed to complete preinit hooks" "$file"
|
! (( $res )) || error "%s: failed to complete preinit hooks" "$file"
|
||||||
@ -350,6 +376,7 @@ EOF
|
|||||||
pvm_cleanup() {
|
pvm_cleanup() {
|
||||||
trap - INT TERM RETURN
|
trap - INT TERM RETURN
|
||||||
|
|
||||||
|
msg "cleaning up"
|
||||||
[ -n "$pacconf" ] && rm -f "$pacconf"
|
[ -n "$pacconf" ] && rm -f "$pacconf"
|
||||||
unset pacconf
|
unset pacconf
|
||||||
if [ -n "$workdir" ]; then
|
if [ -n "$workdir" ]; then
|
||||||
@ -384,7 +411,7 @@ main() {
|
|||||||
M) Mirror="$OPTARG";;
|
M) Mirror="$OPTARG";;
|
||||||
O) Init="-openrc";;
|
O) Init="-openrc";;
|
||||||
s) ImgSizeGb="$(sed 's|[^0-9]||g' <<<$OPTARG)";;
|
s) ImgSizeGb="$(sed 's|[^0-9]||g' <<<$OPTARG)";;
|
||||||
*) usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
*) error "invalid argument: %s\n" "$arg"; usage >&2; exit "$EXIT_INVALIDARGUMENT";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -392,16 +419,18 @@ main() {
|
|||||||
shift $shiftlen
|
shift $shiftlen
|
||||||
local file="$1"
|
local file="$1"
|
||||||
local arch="$2"
|
local arch="$2"
|
||||||
[ "$#" -ne 2 ] && usage >&2 && exit "$EXIT_INVALIDARGUMENT"
|
local has_params=$( [ "$#" -eq 2 ] && echo 1 || echo 0 )
|
||||||
[ "$ImgSizeGb" -lt $MIN_GB ] && usage >&2 && exit "$EXIT_INVALIDARGUMENT"
|
local has_space=$( [ "$ImgSizeGb" -ge $MIN_GB ] && echo 1 || echo 0 )
|
||||||
|
(( ! $has_params )) && error "insufficient arguments" && usage >&2 && exit "$EXIT_INVALIDARGUMENT"
|
||||||
|
(( ! $has_space )) && error "image size too small" && usage >&2 && exit "$EXIT_INVALIDARGUMENT"
|
||||||
|
|
||||||
# determine if the target arch is supported
|
# determine if the target arch is supported
|
||||||
case "$arch" in
|
case "$arch" in
|
||||||
i686|x86_64|armv7h) ;;
|
i686|x86_64|armv7h) ;;
|
||||||
ppc64le|riscv64)
|
ppc64le|riscv64)
|
||||||
warning "%s: arch %s is experimental" "$file" "$arch";;
|
warning "arch %s is experimental" "$arch";;
|
||||||
*)
|
*)
|
||||||
error "%s: arch %s is unsupported" "$file" "$arch"
|
error "arch %s is unsupported" "$arch"
|
||||||
exit "$EXIT_INVALIDARGUMENT";;
|
exit "$EXIT_INVALIDARGUMENT";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@ -418,11 +447,11 @@ main() {
|
|||||||
|
|
||||||
# create the virtual machine
|
# create the virtual machine
|
||||||
if ! pvm_bootstrap; then
|
if ! pvm_bootstrap; then
|
||||||
error "%s: bootstrap failed" "$file"
|
error "bootstrap failed for image: %s" "$file"
|
||||||
exit "$EXIT_FAILURE"
|
exit "$EXIT_FAILURE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg "%s: bootstrap complete" "$file"
|
msg "bootstrap complete for image: %s" "$file"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
Loading…
Reference in New Issue
Block a user