updated helps and README, added pvm2tarball.sh

This commit is contained in:
Andreas Grapentin 2019-03-18 21:07:36 +01:00
parent c7eb38694f
commit bc0fc70388
No known key found for this signature in database
GPG Key ID: 7171986E4B745536
5 changed files with 250 additions and 40 deletions

14
README

@ -35,8 +35,8 @@ The creation hooks currently supported are:
ethernet-dhcp:
this hook will setup ethernet in the VM by enabling systemd-resolved and
symlinking /etc/resolv.conf properly, as well as creating and enabling a
netctl configuration based on the ethernet-dhcp example.
openresolv properly, as well as creating and enabling a systemd-networkd
configuration.
virtual machine boot
--------------------
@ -62,3 +62,13 @@ memory to the machine, by specifying additional qemu parameters on the command
line following the virtual machine image name:
$> DISPLAY= ./pvmboot [path to image] -m 2G
release tarball creation
------------------------
To convert a virtual machine image into a parabola release tarball, run:
$> ./pvm2tarball.sh [path to image]
This will attempt to mount the rootfs and the /boot partition, and tar the
contents to an output file, filtering out all unneeded files.

@ -2,16 +2,19 @@
set -e
# setup systemd-resolved
systemctl start systemd-resolved.service || return
systemctl enable systemd-resolved.service
ln -sf /var/run/systemd/resolve/resolv.conf /etc/resolv.conf
# determine first ethernet device
eth="$(basename "$(find /sys/class/net/ -mindepth 1 -maxdepth 1 -iname 'e*' | head -n1)")"
[ -n "$eth" ] || eth="eth0"
# setup netctl for ethernet-dhcp
sed "s/eth0/$eth/" /etc/netctl/examples/ethernet-dhcp > /etc/netctl/ethernet-dhcp
netctl start ethernet-dhcp || return
netctl enable ethernet-dhcp
# create a network configuration
cat > /etc/systemd/network/$eth.network << EOF
[Match]
Name=$eth
[Network]
DHCP=yes
EOF
# enable said network configuration
systemctl enable systemd-networkd.service
systemctl enable systemd-resolved.service

165
src/pvm2tarball.sh Normal file

@ -0,0 +1,165 @@
#!/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] [-o FILE] IMG" "${0##*/}"
prose "Produce a parabola release tarball from IMG."
echo
prose "IMG is expected to be a valid parabola image, ideally freshly bootstrapped
using pvmbootstrap. If FILE is not specifed, generate an archive name
from IMG and place it in the current working directory"
echo
echo "Supported options:"
echo " -o FILE Write the generated tar archive to FILE instead of"
echo " generating a name for the archive from IMG"
echo " -h Display this help and exit"
echo
echo "This script is part of parabola-vmbootstrap. source code available at:"
echo " <https://git.parabola.nu/~oaken-source/parabola-vmbootstrap.git>"
}
pvm_mount() {
if ! file "$1" | grep -q ' DOS/MBR '; then
error "%s: does not seem to be a raw qemu image." "$1"
return "$EXIT_FAILURE"
fi
trap 'pvm_umount' INT TERM EXIT
workdir="$(mktemp -d -t pvm-XXXXXXXXXX)" || return
loopdev="$(sudo losetup -fLP --show "$1")" || return
# find the root partition
local part rootpart
for part in "$loopdev"p*; do
sudo mount "$part" "$workdir" || continue
if [ -f "$workdir"/etc/fstab ]; then
rootpart="$part"
break
fi
sudo umount "$workdir"
done
if [ -z "$rootpart" ]; then
error "%s: unable to determine root partition." "$1"
return "$EXIT_FAILURE"
fi
# find the boot partition
bootpart="$(findmnt -senF "$workdir"/etc/fstab /boot | awk '{print $2}')"
if [ -z "$bootpart" ]; then
error "%s: unable to determine boot partition." "$1"
return "$EXIT_FAILURE"
fi
# mount and be happy
sudo mount "$bootpart" "$workdir"/boot || return
}
pvm_umount() {
trap - INT TERM EXIT
[ -n "$workdir" ] && (sudo umount -R "$workdir"; rmdir "$workdir")
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
# parse options
local output
while getopts 'ho:' arg; do
case "$arg" in
h) usage; return "$EXIT_SUCCESS";;
o) output="$OPTARG";;
*) usage >&2; exit "$EXIT_INVALIDARGUMENT";;
esac
done
local shiftlen=$(( OPTIND - 1 ))
shift $shiftlen
if [ "$#" -ne 1 ]; then usage >&2; exit "$EXIT_INVALIDARGUMENT"; fi
local imagebase imagefile="$1"
imagebase="$(basename "$imagefile")"
shift
# check for input file presence
if [ ! -e "$imagefile" ]; then
error "%s: file not found" "$imagefile"
exit "$EXIT_FAILURE"
fi
# determine output file
[ -n "$output" ] || output="${imagebase%.*}.tar.gz"
# check for output file presence
if [ -e "$output" ]; then
warning "%s: file exists. Continue? [y/N]" "$output"
read -p " " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit "$EXIT_FAILURE"
fi
rm -f "$output" || exit
fi
# mount the root filesystem
local workdir loopdev
pvm_mount "$imagefile" || exit
# tar the root filesystem, excluding unneeded things
sudo tar -c -f "$output" -C "$workdir" -X - . << EOF
./boot/lost+found
./etc/.updated
./etc/pacman.d/empty.conf
./etc/pacman.d/gnupg
./lost+found
./root/.bash_history
./var/.updated
./var/log/journal/*
./var/log/pacman.log
./var/log/tallylog
EOF
# HACKING:
# to update the exclude list above, one can download the latest archlinuxarm
# release tarball, and scroll over the diff generated by running both the
# archlinuxarm and the generated parabola tarball through:
#
# `tar -tf <tarball> | sort`
# give the archive back to the user
sudo chown "$(id -u)":"$(id -g)" "$output"
# cleanup
pvm_umount
}
main "$@"

@ -22,22 +22,32 @@
. "$(librelib messages)"
usage() {
print "usage: %s [-h] filename [args...]" "${0##*/}"
print "usage: %s [-h] IMG [ARG]..." "${0##*/}"
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
created using pvmbootstrap. The started instances are assigned 1GiB of
RAM and one SMP core."
echo
prose " this script is designed to smartly boot a parabola GNU/Linux-libre
virtual machine with qemu. It takes the path to a virtual machine image
as parameter, and determines the architecture of that image. It sets
default qemu parameters for the target architecture, and determines
whether kvm acceleration is available."
prose "When a graphical desktop environment is available, start the machine
normally, otherwise append -nographic to the qemu options. This behavior
can be forced by unsetting DISPLAY manually, for example through:"
echo
prose " the script also determines whether a graphical desktop environment
is available by evaluating the DISPLAY environment variable, and sets
default options accordingly."
echo " DISPLAY= ${0##*/} IMG ..."
echo
prose " the default qemu parameters can be overwritten and extended by adding
custom arguments after the image file name."
prose "When the architecture of IMG is compatible with the host architecture,
append -enable-kvm to the qemu arguments."
echo
echo "this script is developed as part of parabola-vmbootstrap."
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
machine, for example:"
echo
echo " ${0##*/} IMG -m 2G -smp 2"
echo
echo "Supported options:"
echo " -h Display this help and exit"
echo
echo "This script is part of parabola-vmbootstrap. source code available at:"
echo " <https://git.parabola.nu/~oaken-source/parabola-vmbootstrap.git>"
}
pvm_mount() {

@ -22,26 +22,31 @@
. "$(librelib messages)"
usage() {
print "usage: %s [-h] [-s size] [-M mirror] [-H hook...] filename arch" "${0##*/}"
print "usage: %s [-h] [-s SIZE] [-M MIRROR] [-H HOOK]... IMG ARCH" "${0##*/}"
prose "Produce preconfigured parabola GNU/Linux-libre virtual machine instances."
echo
prose " this script produces preconfigured parabola GNU/Linux-libre virtual
machine images, to be started using the accompanying pvmboot.sh
script. The created image is placed at the specified path."
prose "The produced image file is written to IMG, and is configured and
bootstrapped for the achitecture specified in ARCH. ARCH can ether be
one of the officially supported architectures x86_64, i686 or armv7h,
or one of the unofficial arches ppc64le and riscv64 (refer to -M for
custom package mirrors)"
echo
prose " the target architecture of the virtual machine image can be one of the
officially supported i686, x86_64 and armv7h, as well as one of the
unofficial ports for ppc64le and riscv64."
echo "Supported options:"
echo " -s SIZE Set the size of the VM image (default: 64GiB)"
echo " -M MIRROR Choose a different mirror to pacstrap from"
echo " default: <https://repo.parabola.nu/\$repo/os/\$arch>"
echo " -H HOOK Enable a hook to customize the created image. This can be"
echo " the path to a script, which will be executed once within"
echo " the running VM, or one of the predefined hooks described"
echo " below. This option can be specified multiple times."
echo " -h Display this help and exit"
echo
prose " the creation of the virtual machine is configurable in three ways. First,
the size of the image can be configured with the -s switch, whose
value is passed verbatim to qemu-img create (default 64G). Second,
the mirror to load packages from can be configured with the -M switch,
wich is necessary for the unofficial ports, whose packages are not on
the main mirrors. Lastly, the -H switch can be passed multiple times to
specify post-install hooks to be run in the virtual machine for
install finalization. See src/hooks/ for examples."
echo "Predefined hooks:"
echo " ethernet-dhcp: configure and enable an ethernet device in the virtual"
echo " machine, using openresolv, dhcp and systemd-networkd"
echo
echo "this script is developed as part of parabola-vmbootstrap."
echo "This script is part of parabola-vmbootstrap. source code available at:"
echo " <https://git.parabola.nu/~oaken-source/parabola-vmbootstrap.git>"
}
pvm_native_arch() {
@ -170,10 +175,12 @@ Server = $mirror
Server = $mirror
[community]
Server = $mirror
[pcr]
Server = $mirror
EOF
# prepare lists of packages
local pkg=(base haveged)
local pkg=(base haveged openssh openresolv ldns net-tools)
case "$arch" in
i686|x86_64) pkg+=(grub) ;;
esac
@ -190,6 +197,13 @@ EOF
sudo swapoff "$swapdev"
sudo swapon --all
# produce a hostname
echo "parabola" | sudo tee "$workdir"/etc/hostname
# produce an /etc/locale.conf
echo "LANG=en_US.UTF-8" | sudo tee "$workdir"/etc/locale.conf
sudo sed -i 's/#en_US.UTF-8/en_US.UTF-8/' "$workdir"/etc/locale.gen
# install a boot loader
case "$arch" in
i686|x86_64)
@ -242,21 +256,29 @@ EOF
#!/bin/bash
systemctl disable preinit.service
# generate the locale
locale-gen
# fix the mkinitcpio
mkinitcpio -p linux-libre
# fix ca-certificates
pacman -U --noconfirm /var/cache/pacman/pkg/ca-certificates-utils-*.pkg.tar.xz
# run the hooks
for hook in /root/hooks/*; do
echo "running hook \"$hook\""
. "$hook" || return
done
# clean up after yourself
rm -rf /root/hooks
rm -f /root/hooks.sh
rm -f /usr/lib/systemd/system/preinit.service
rm -f /var/cache/pacman/pkg/*
rm -f /root/.bash_history
# report success :)
echo "preinit hooks successful"
EOF