Overhaul the entire library.

This commit is a "complete" overhaul of libdevuansdk and is a likely
breaking change for all the sdks. They will be updated accordingly.

Notable changes:
    * Bootstrap tarballs are now cpio archives.
    * Error handling is improved a lot.
    * rsync is avoided and cpio is used where necessary.
    * debootstrap submodule is removed and system-wide debootstrap is
      used instead.
    * VMs aren't being built inside an nbd device anymore. They are now
      built normally on the filesystem, and copied into a raw image
      which is then converted to requested formats (qcow and/or vdi).
    * Vagrant build support is completely dropped.
    * apt-cache functionality is completely dropped.
    * The full-build helper functions are renamed and and separated into
      more internal functions/steps.
    * Obsolete and unused code is removed.
This commit is contained in:
parazyd 2020-11-13 10:04:52 +01:00
parent 881efdf1ba
commit aedf124832
No known key found for this signature in database
GPG Key ID: 6B636BF0493EE747
11 changed files with 748 additions and 1140 deletions

18
config
View File

@ -1,4 +1,5 @@
#!/usr/bin/env zsh
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
@ -17,21 +18,13 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
## libdevuansdk configuration
vars+=(release version mirror section blend_name image_name vm_name)
vars+=(arch earch)
vars+=(aptcachedir APT_CACHE aptcachegpg)
vars+=(usercredentials rootcredentials)
vars+=(nocompressimage)
vars+=(COMPRESS_IMAGE CPIO_STAGE4 MKEFI)
arrs+=(core_packages base_packages purge_packages blend_packages)
## enable local apt cache
APT_CACHE=${APT_CACHE:-0}
aptcachedir="$LIBPATH/apt-cache"
## key used to sign the cache's Release
aptcachegpg="0xdeadbeefdeadbeef"
arrs+=(core_packages_option base_packages_option purge_packages_option blend_packages_option)
os="devuan"
release="beowulf"
@ -43,11 +36,10 @@ image_name="${os}_${release}_${version}_${arch}"
[[ -n "$blend_name" ]] && image_name="${image_name}_${blend_name}"
[[ -n "$device_name" ]] && image_name="${image_name}_${device_name}"
vm_name="${os}_${release}_${version}_${arch}_vagrant"
[[ -n $blend_name ]] && vm_name="${image_name}_${blend_name}"
vm_name="${os}_${release}_${version}_${arch}_virtual"
[[ -n "$blend_name" ]] && vm_name="${vm_name}_${blend_name}"
rootcredentials="root:toor"
usercredentials="devuan:devuan"
core_packages_option=()
core_packages=(

View File

@ -1,6 +1,7 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2017 Dyne.org Foundation
# libdevuansdk maintained by Ivan J. <parazyd@dyne.org>
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
#
@ -17,22 +18,18 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
libdevuansdk_version="1.0"
LIBPATH=${LIBPATH:-$(dirname $0)}
vars+=(libdevuansdk_version LIBPATH)
source $LIBPATH/config
source $LIBPATH/zlibs/bootstrap
source $LIBPATH/zlibs/cache
source $LIBPATH/zlibs/helpers
source $LIBPATH/zlibs/imaging
source $LIBPATH/zlibs/iso
source $LIBPATH/zlibs/kernel
source $LIBPATH/zlibs/rsync
source $LIBPATH/zlibs/sysconf
source $LIBPATH/zlibs/vm
libdevuansdk_version="2.0"
LIBPATH="${LIBPATH:-$(dirname $0)}"
vars+=(libdevuansdk_version)
vars+=(LIBPATH)
source "$LIBPATH/config"
source "$LIBPATH/zlibs/bootstrap"
source "$LIBPATH/zlibs/helpers"
source "$LIBPATH/zlibs/imaging"
source "$LIBPATH/zlibs/iso"
source "$LIBPATH/zlibs/vm"
source "$LIBPATH/zlibs/sysconf"
setopt pushdsilent

View File

@ -1,6 +1,7 @@
#!/usr/bin/env zsh
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk maintained by Ivan J. <parazyd@dyne.org>
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
#
@ -17,222 +18,227 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
vars+=(bootstrap_tgz_stage3 bootstrap_tgz_stage4 TAR_STAGE4)
arrs+=(base_packages_option core_packages_option extra_packages_option)
arrs+=(purge_packages_option)
vars+=(bootstrap_cpio_stage3 bootstrap_cpio_stage4 CPIO_STAGE4)
bootstrap_complete_base() {
fn bootstrap_complete_base "$@"
req=(arch)
bootstrap_complete_base()
{
fn bootstrap_complete_base "$*"
req=(R os arch strapdir LIBPATH release mirror)
ckreq || return 1
notice "bootstrapping $os $arch base"
notice "Bootstrapping: ${os}:${arch} base"
export LANG=C
export LC_ALL=C
export DEBIAN_FRONTEND=noninteractive
bootstrap_tgz_stage3="$R/tmp/bootstrap-${os}-${arch}-stage3.tgz"
bootstrap_tgz_stage4="$R/tmp/bootstrap-${os}-${arch}-stage4.tgz"
bootstrap_cpio_stage3="$R/tmp/bootstrap-${os}-${arch}-stage3.cpio.gz"
bootstrap_cpio_stage4="$R/tmp/bootstrap-${os}-${arch}-stage4.cpio.gz"
if [[ -n "$TAR_STAGE4" && -f "$bootstrap_tgz_stage4" ]]; then
notice "using the existing stage4 bootstrap tarball found in $R/tmp"
bootstrap_tar_unpack "$bootstrap_tgz_stage4" "$strapdir" || {
die "failed to extract tarball"
zerr
if [[ -n "$CPIO_STAGE4" && -f "$bootstrap_cpio_stage4" ]]; then
act "Using the existing stage4 bootstrap cpio archive..."
bootstrap_cpio_unpack "$bootstrap_cpio_stage4" "$strapdir" || {
die "Failed to extract cpio archive"
return 1
}
return
elif [[ -f "$bootstrap_tgz_stage3" ]]; then
notice "using the existing stage3 bootstrap tarball found in $R/tmp"
bootstrap_tar_unpack "$bootstrap_tgz_stage3" "$strapdir" || {
die "failed to extract tarball"
zerr
elif [[ -f "$bootstrap_cpio_stage3" ]]; then
act "Using the existing stage3 bootstrap cpio archive..."
bootstrap_cpio_unpack "$bootstrap_cpio_stage3" "$strapdir" || {
die "Failed to extract cpio archive"
return 1
}
bootstrap_stage4 || { zerr; return 1; }
if [[ -n "$CPIO_STAGE4" ]]; then
bootstrap_cpio_pack "$bootstrap_cpio_stage4" || { zerr; return 1; }
fi
return
fi
notice "running debootstrap stage 1"
notice "Running stage1 debootstrap"
sudo DEBOOTSTRAP_DIR="$LIBPATH/extra/debootstrap" "$LIBPATH/extra/debootstrap/debootstrap" \
sudo debootstrap \
--keyring="$LIBPATH/extra/devuan-keyring/keyrings/devuan-archive-keyring.gpg" \
--include=wget,ca-certificates \
--include=devuan-keyring,wget,ca-certificates \
--foreign \
--arch $arch $release $strapdir $mirror || zerr
--arch "$arch" "$release" "$strapdir" "$mirror" || { zerr; return 1; }
[[ $arch =~ "^arm.." ]] && { qemu_install_user || zerr }
sudo mkdir -p $strapdir/tmp
sudo chmod 1777 $strapdir/tmp
## debootstrap stage 2
notice "running debootstrap stage 2"
sudo chroot $strapdir \
/debootstrap/debootstrap --second-stage || zerr
blend_bootstrap_setup || zerr
## write all system configuration
notice "writing system configuration"
conf_print_debconf | sudo tee $strapdir/debconf.set >/dev/null
conf_print_fstab | sudo tee $strapdir/etc/fstab >/dev/null
conf_print_hostname | sudo tee $strapdir/etc/hostname >/dev/null
conf_print_hosts | sudo tee $strapdir/etc/hosts >/dev/null
conf_print_netifaces | sudo tee $strapdir/etc/network/interfaces >/dev/null
conf_print_resolvconf | sudo tee $strapdir/etc/resolv.conf >/dev/null
conf_print_sourceslist | sudo tee $strapdir/etc/apt/sources.list >/dev/null
#conf_print_locales | sudo tee $strapdir/etc/profile.d/locales.sh >/dev/null
## write third-stage for chroot
bootstrap_config_thirdstage | sudo tee $strapdir/thirdstage >/dev/null
## chroot into it and configure further
## debootstrap stage 3
notice "running debootstrap stage 3"
chroot-script -d thirdstage || zerr
[[ $APT_CACHE = 1 ]] && {
notice "adding apt cache gpg pubkey"
cat <<EOF | sudo tee ${strapdir}/addcachepubkey >/dev/null
#!/bin/sh
gpgkey="$(gpg --export -a $aptcachegpg)"
printf "%s" "\$gpgkey" | apt-key add -
EOF
chroot-script addcachepubkey || zerr
}
if [[ -n "$TAR_STAGE4" ]]; then
bootstrap_tar_pack "$bootstrap_tgz_stage3" || zerr
bootstrap_tar_unpack "$bootstrap_tgz_stage4" "$strapdir" || zerr
else
bootstrap_tar_pack "$bootstrap_tgz_stage3" || zerr
bootstrap_tar_unpack "$bootstrap_tgz_stage3" "$strapdir" || zerr
if [[ "$arch" =~ "^arm.." ]]; then
qemu_install_user "$strapdir" || { zerr; return 1; }
fi
notice "Running stage2 debootstrap"
sudo chroot "$strapdir" /debootstrap/debootstrap --second-stage || { zerr; return 1; }
# TODO: sys config as function
conf_print_fstab | sudo tee "$strapdir/etc/fstab" >/dev/null
conf_print_hostname | sudo tee "$strapdir/etc/hostname" >/dev/null
conf_print_hosts | sudo tee "$strapdir/etc/hosts" >/dev/null
conf_print_netifaces | sudo tee "$strapdir/etc/network/interfaces" >/dev/null
conf_print_resolvconf | sudo tee "$strapdir/etc/resolv.conf" >/dev/null
conf_print_sourceslist | sudo tee "$strapdir/etc/apt/sources.list" >/dev/null
blend_bootstrap_setup || { zerr; return 1; }
bootstrap_stage3 || { zerr; return 1; }
bootstrap_cpio_pack "$bootstrap_cpio_stage3" || { zerr; return 1; }
bootstrap_stage4 || { zerr; return 1; }
if [[ -n "$CPIO_STAGE4" ]]; then
bootstrap_cpio_pack "$bootstrap_cpio_stage4" || { zerr; return 1; }
fi
return
}
bootstrap_config_thirdstage() {
fn bootstrap_config_thirdstage
req=(core_packages base_packages)
bootstrap_stage3()
{
fn bootstrap_stage3
req=(core_packages base_packages rootcredentials)
ckreq || return 1
cat << EOF
cat <<EOF | sudo tee "$strapdir/thirdstage" >/dev/null
#!/bin/sh
apt-get update
debconf-set-selections /debconf.set
echo "${rootcredentials}" | chpasswd
sed -i -e 's/KERNEL\!=\"eth\*|/KERNEL\!=\"/' \
/lib/udev/rules.d/75-persistent-net-generator.rules
rm -f /etc/udev/rules.d/70-persistent-net.rules
export DEBIAN_FRONTEND=noninteractive
apt-get --yes --force-yes install ${core_packages_option} ${core_packages}
apt-get --yes --force-yes install ${base_packages_option} ${base_packages}
apt-get --yes --force-yes purge ${purge_packages_option} ${purge_packages}
apt-get --yes --force-yes autoremove
apt-get --yes --force-yes install ${core_packages_option} ${core_packages} || exit 1
apt-get --yes --force-yes install ${base_packages_option} ${base_packages} || exit 1
apt-get --yes --force-yes purge ${purge_packages_option} ${purge_packages} || exit 1
apt-get --yes --force-yes --purge autoremove || exit 1
apt-get clean
sed -e 's/# en_US.UTF-8/en_US.UTF-8/' -i /etc/locale.gen
locale-gen
echo "${rootcredentials}" | chpasswd
rm -f /debconf.set
rm -f /etc/ssh/ssh_host_*
rm -f /root/.bash_history
#echo "1" > .keep
EOF
chroot-script -d thirdstage || { zerr; return 1; }
}
bootstrap_tar_pack() {
fn bootstrap_tar_pack
req=(bootstrap_tgz)
bootstrap_tgz="$1"
bootstrap_stage4()
{
fn bootstrap_stage4
req=(strapdir extra_packages)
ckreq || return 1
local _dest="$(dirname $bootstrap_tgz)"
sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
if [[ -f "$bootstrap_tgz" ]]; then
notice "tarball found already in $_dest"
else
notice "Creating boostrap tarball in $bootstrap_tgz"
silly
pushd ${strapdir}
mkdir -p ${_dest}
silly
sudo tar czfp "$bootstrap_tgz" \
--acls \
--selinux \
--xattrs \
--xattrs-include=security.capability \
--xattrs-include=user.pax.flags \
--exclude={./dev,./sys,./proc} . || zerr
popd
fi
}
bootstrap_tar_unpack() {
fn bootstrap_tar_unpack $@
local bootstrap_tgz="$1"
req=(strapdir bootstrap_tgz)
ckreq || return 1
[[ -n "$TAR_STAGE4" ]] && {
[[ -f "$bootstrap_tgz" ]] || bootstrap_tgz="$bootstrap_tgz_stage3"
}
sudo rm -rf "${strapdir}"/*
silly
sudo tar xpf "$bootstrap_tgz" -C "$strapdir" --xattrs-include='*.*' --numeric-owner \
--acls --selinux --xattrs
sudo mkdir -p ${strapdir}/{boot,dev,sys,proc}
conf_print_sourceslist | sudo tee $strapdir/etc/apt/sources.list >/dev/null
cat <<EOF | sudo tee ${strapdir}/postunpack >/dev/null
cat <<EOF | sudo tee "$strapdir/fourthstage" >/dev/null
#!/bin/sh
apt-get update
## check if all our extra_packages exist
# check if all our extra_packages exist
allpkgs="\$(apt-cache search '.' | cut -d' ' -f1)"
for i in ${extra_packages} ; do
for i in ${extra_packages}; do
printf "%s" "\$allpkgs" | grep -q "^\$i$" || {
case "\$i" in
--*) continue ;;
*) missing="\$missing \$i" ;;
--*) continue;;
*) missing="\$missing \$i" ;;
esac
}
done
[ -n "\$missing" ] && {
printf "\033[1;31m[!!] some extra packages don't exist\033[0m\n"
if [ -n "\$missing" ]; then
printf "\033[1;31m[!!] Some extra packages don't exist:\033[0m\n"
printf "%s\n" "\$missing"
exit 1
}
apt-get --yes --force-yes upgrade
apt-get --yes --force-yes install ${extra_packages_option} ${extra_packages}
apt-get --yes --force-yes autoremove
fi
apt-get --yes --force-yes upgrade || exit 1
apt-get --yes --force-yes install ${extra_packages_option} ${extra_packages} || exit 1
apt-get --yes --force-yes --purge autoremove || exit 1
apt-get clean
EOF
chroot-script -d postunpack || zerr
chroot-script -d fourthstage || { zerr; return 1; }
for i in $inittab; do
grep -q "^$i" $strapdir/etc/inittab && continue
print "$i" | sudo tee -a $strapdir/etc/inittab >/dev/null
grep -q "$^i" "$strapdir/etc/inittab" && continue
echo "$i" | sudo tee -a "$strapdir/etc/inittab" >/dev/null
done || true
for i in $custmodules; do
grep -q "^$i" $strapdir/etc/modules && continue
print "$i" | sudo tee -a $strapdir/etc/modules >/dev/null
grep -q "^$i" "$strapdir/etc/modules" && continue
echo "$i" | sudo tee -a "$strapdir/etc/modules" >/dev/null
done || true
[[ -n "$TAR_STAGE4" ]] && bootstrap_tar_pack "$bootstrap_tgz_stage4" || true
}
blend_bootstrap_setup() {
fn blend_bootstrap_setup "noop"
return 0
qemu_install_user()
{
fn qemu_install_user "$*"
req=(arch _target)
local _target="$1"
ckreq || return 1
case "$(uname -m)" in
arm*|aarch*)
return
;;
esac
notice "Installing qemu-user-static"
case "$arch" in
armel)
sudo cp -a "$armel_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
;;
armhf)
sudo cp -a "$armhf_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
;;
arm64)
sudo cp -a "$arm64_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
;;
esac
}
bootstrap_cpio_pack()
{
fn bootstrap_cpio_pack "$*"
req=(_bootstrap_cpio strapdir)
local _bootstrap_cpio="$1"
ckreq || return 1
local _dest="$(dirname "$_bootstrap_cpio")"
if [[ -f "$_bootstrap_cpio" ]]; then
notice "cpio archive already found in $_dest"
return
fi
notice "Creating bootstrap cpio archive: $_bootstrap_cpio"
silly
pushd "$strapdir"
mkdir -p "$_dest"
sudo find . \
-not -path "./dev/*" \
-a -not -path "./proc/*" \
-a -not -path "./sys/*" \
| sudo cpio -o --format=newc \
| gzip - > "$_bootstrap_cpio" || { zerr; return 1; }
popd
}
bootstrap_cpio_unpack()
{
fn bootstrap_cpio_unpack "$*"
req=(_bootstrap_cpio strapdir)
local _bootstrap_cpio="$1"
ckreq || return 1
notice "Unpacking bootstrap cpio archive: $_bootstrap_cpio"
silly
sudo rm -rf "${strapdir}"/*
pushd "$strapdir" || { zerr; return 1; }
zcat "$_bootstrap_cpio" | sudo cpio -id || { zerr; return 1; }
popd
sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
}
blend_bootstrap_setup()
{
fn blend_bootstrap_setup "(noop)"
return
}

View File

@ -1,83 +0,0 @@
#!/usr/bin/env zsh
# Copyright (c) 2017 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
#
# This source code 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 software 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 source code. If not, see <http://www.gnu.org/licenses/>.
aptcache() {
fn aptcache "$*"
req=(aptcachedir watdo werdo APT_CACHE)
local watdo="$1"
local werdo="$2"
ckreq || return 1
[[ $APT_CACHE = 1 ]] || return 0
case "$watdo" in
on)
act "mounting local apt cache"
sudo mount -o bind "$aptcachedir" "$werdo" || zerr
;;
off)
act "umounting local apt cache"
sudo umount "$werdo" || zerr
;;
esac
}
fill_apt_cache() {
fn fill_apt_cache
req=(strapdir APT_CACHE aptcachedir)
ckreq || return 1
[[ $APT_CACHE = 1 ]] || return 0
notice "filling local apt cache"
cp -fv $strapdir/var/cache/apt/archives/*.deb $aptcachedir
pushd "$aptcachedir"
dpkg-scanpackages . /dev/null > Packages
gzip -c Packages > Packages.gz
cat <<EOF > Release
Origin: ${os}
Suite: ${release}
Version: ${version}
Architectures: alpha amd64 arm64 armel armhf hppa i386 ia64 mips mipsel powerpc ppc64el s390x sparc
MD5sum:
$(md5sum Packages | cut -d' ' -f1) $(du -b Packages)
$(md5sum Packages.gz | cut -d' ' -f1) $(du -b Packages.gz)
SHA1:
$(sha1sum Packages | cut -d' ' -f1) $(du -b Packages)
$(sha1sum Packages.gz | cut -d' ' -f1) $(du -b Packages.gz)
SHA256:
$(sha256sum Packages | cut -d' ' -f1) $(du -b Packages)
$(sha256sum Packages.gz | cut -d' ' -f1) $(du -b Packages.gz)
EOF
rm -f Packages
gpg --sign --detach-sign -a --sign-with $aptcachegpg Release || zerr
mv Release.asc Release.gpg
popd
sudo sed -i '/deb file:\/mnt/d' "$strapdir/etc/apt/sources.list"
notice "removing apt cache gpg pubkey"
cat <<EOF | sudo tee ${strapdir}/delcachepubkey >/dev/null
#!/bin/sh
apt-key del ${aptcachegpg}
EOF
chroot-script delcachepubkey || zerr
}

View File

@ -1,5 +1,6 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2017 Dyne.org Foundation
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
@ -17,101 +18,109 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
## helper functions that make my life easier
vars+=(loopdevice)
build_image_dist() {
fn build_image_dist
req=(arch size parted_type)
if [[ $parted_type = gpt ]]; then
req+=(gpt_boot gpt_root)
elif [[ $parted_type = dos ]]; then
req+=(parted_root parted_boot)
fi
req+=(workdir strapdir image_name)
build_arm_dist()
{
fn build_arm_dist
req=(workdir strapdir os arch size parted_type)
case "$parted_type" in
gpt) req+=(gpt_boot gpt_root) ;;
dos) req+=(dos_boot dos_root) ;;
*) die "Unknown parted_type: $parted_type. Supported is gpt|dos."
zerr; return 1
;;
esac
ckreq || return 1
notice "building complete dist image"
act "$image_name"
notice "Building complete Arm image(s)"
bootstrap_complete_base || { zerr; wrapup }
blend_preinst || { zerr; wrapup }
image_prepare_raw || { zerr; wrapup }
image_partition_raw_${parted_type} || { zerr; wrapup }
build_kernel_${arch} || { zerr; wrapup }
blend_postinst || { zerr; wrapup }
rsync_to_raw_image || { zerr; wrapup }
image_pack_dist || { zerr; wrapup }
bootstrap_complete_base || { zerr; return 1; }
blend_preinst || { zerr; return 1; }
image_prepare_raw || { zerr; return 1; }
image_connect_raw || { zerr; return 1; }
image_partition_${parted_type} || { zerr; return 1; }
image_format_partitions || { zerr; return 1; }
build_kernel_${arch} || { zerr; return 1; }
image_mount || { zerr; return 1; }
strapdir_to_image || { zerr; return 1; }
blend_postinst || { zerr; return 1; }
image_umount || { zerr; return 1; }
image_disconnect_raw || { zerr; return 1; }
image_pack_dist || { zerr; return 1; }
clean_strapdir || { zerr; return 1; }
}
build_iso_dist() {
build_iso_dist()
{
fn build_iso_dist
req=(workdir strapdir os arch)
ckreq || return 1
notice "building complete iso image"
notice "Building complete iso image(s)"
bootstrap_complete_base || { zerr; wrapup }
blend_preinst || { zerr; wrapup }
iso_prepare_strap || { zerr; wrapup }
build_kernel_${arch} || { zerr; wrapup }
iso_setup_isolinux || { zerr; wrapup }
iso_write_isolinux_cfg || { zerr; wrapup }
#[[ $INSTALLER = 1 ]] && iso_setup_installer || zerr
blend_postinst || { zerr; wrapup }
fill_apt_cache || { zerr; wrapup }
iso_squash_strap || { zerr; wrapup }
iso_xorriso_build || { zerr; wrapup }
bootstrap_complete_base || { zerr; return 1; }
blend_preinst || { zerr; return 1; }
iso_prepare_strap || { zerr; return 1; }
iso_setup_isolinux || { zerr; return 1; }
iso_write_isolinux_cfg || { zerr; return 1; }
blend_postinst || { zerr; return 1; }
iso_squash_strap || { zerr; return 1; }
iso_xorriso_build || { zerr; return 1; }
}
build_vagrant_dist() {
fn build_vagrant_dist
req=(workdir strapdir os arch imageformat)
build_vm_dist()
{
fn build_vm_dist
req=(workdir strapdir os arch size imageformat parted_type)
case "$parted_type" in
gpt) req+=(gpt_boot gpt_root) ;;
dos) req+=(dos_boot dos_root) ;;
*) die "Unknown parted_type: $parted_type. Supported is gpt|dos."
zerr; return 1
;;
esac
ckreq || return 1
notice "building complete vagrant image"
notice "Building complete VM image(s)"
image_${imageformat}_as_strapdir || { zerr; wrapup }
bootstrap_complete_base || { zerr; wrapup }
vm_inject_overrides || { zerr; wrapup }
blend_preinst || { zerr; wrapup }
vm_setup_grub || { zerr; wrapup }
blend_postinst || { zerr; wrapup }
vm_umount_${imageformat} || { zerr; wrapup }
vm_vbox_setup || { zerr; wrapup }
vm_vagrant_package || { zerr; wrapup }
vm_init_cloud || { zerr; wrapup }
vm_pack_dist || { zerr; wrapup }
bootstrap_complete_base || { zerr; return 1; }
vm_inject_overrides || { zerr; return 1; }
blend_preinst || { zerr; return 1; }
image_prepare_raw || { zerr; return 1; }
image_connect_raw || { zerr; return 1; }
image_partition_${parted_type} || { zerr; return 1; }
image_format_partitions || { zerr; return 1; }
image_mount || { zerr; return 1; }
strapdir_to_image || { zerr; return 1; }
vm_setup_grub || { zerr; return 1; }
blend_postinst || { zerr; return 1; }
image_umount || { zerr; return 1; }
image_disconnect_raw || { zerr; return 1; }
if [[ "$imageformat" = qcow2 ]]; then
image_raw_to_qcow2 || { zerr; return 1; }
fi
image_raw_to_vdi || { zerr; return 1; }
vm_pack_dist || { zerr; return 1; }
clean_strapdir || { zerr; return 1; }
}
getfield() {
fn getfield $*
print "$1" | \
grep "^$2=" | \
sed -e 's:.*=\(.*\)$:\1:g' | \
sed -e 's:^"\(.*\)"$:\1:g'
}
add-user() {
fn add-user $*
local user="$1"
local pass="$2"
req=(strapdir user pass)
clean_strapdir()
{
fn clean_strapdir
req=(strapdir)
ckreq || return 1
notice "adding user $user:$pass"
if [[ "$DEBUG" = 1 ]]; then
return
fi
cat <<EOF | sudo tee ${strapdir}/adduser
#!/bin/sh
useradd -m ${user}
echo "${user}:${pass}" | chpasswd
EOF
chroot-script adduser || zerr
notice "Cleaning strapdir"
sudo rm -rf "$strapdir"
}
devprocsys() {
fn devprocsys "$@"
devprocsys()
{
fn devprocsys "$*"
local watdo="$1"
local werdo="$2"
req=(watdo werdo)
@ -124,79 +133,17 @@ devprocsys() {
sudo mount -o bind /dev/pts $werdo/dev/pts && act "mounted devpts" && \
return 0
elif [[ $watdo = umount ]]; then
sudo umount $werdo/dev/pts && act "umounted devpts" && sleep 1
sudo umount $werdo/dev && act "umounted dev" && sleep 1
sudo umount $werdo/proc && act "umounted proc" && sleep 1
sudo umount $werdo/sys && act "umounted sys" && sleep 1
sudo umount $werdo/dev/pts && act "umounted devpts"
sudo umount $werdo/dev && act "umounted dev"
sudo umount $werdo/proc && act "umounted proc"
sudo umount $werdo/sys && act "umounted sys"
return 0
fi
return 1
zerr; return 1
}
wrapup() {
# a hopefully clean exit
fn wrapup
req=(strapdir)
ckreq || {
die "something is very wrong"
die "cleanup yourself, sorry"
exit 1
}
devprocsys umount $strapdir
exit 1
}
findloopdev() {
fn findloopdev
req=(workdir image_name)
ckreq || return 1
notice "finding a free loopdevice"
loopdevice=$(sudo losetup -f --show $workdir/${image_name}.img)
sudo partx -av $loopdevice || zerr
func "loopdevice: $loopdevice"
silly sleep 2
}
findfreenbd() {
fn findfreenbd
notice "looking for a free /dev/nbd"
for i in $(seq 0 8); do
grep "^/dev/nbd${i}" /proc/mounts >/dev/null || {
print "/dev/nbd${i}"
break
}
done
}
qemu_install_user() {
fn qemu_install_user
req=(arch strapdir)
ckreq || return 1
[[ "$(uname -m)" =~ "arm" ]] && return
[[ "$(uname -m)" =~ "aarch" ]] && return
notice "installing qemu-user-static"
case "$arch" in
armel)
sudo cp -a "$armel_qemu_bin" "$strapdir/usr/bin"
;;
armhf)
sudo cp -a "$armhf_qemu_bin" "$strapdir/usr/bin"
;;
arm64)
sudo cp -a "$arm64_qemu_bin" "$strapdir/usr/bin"
;;
esac
}
dpkgdivert() {
dpkgdivert()
{
fn dpkgdivert "$@"
req=(watdo werdo)
local watdo="$1"
@ -207,8 +154,8 @@ dpkgdivert() {
cat <<EOF | sudo tee ${werdo}/dpkgdivert >/dev/null
#!/bin/sh
dpkg-divert --add --local \
--divert /usr/sbin/invoke-rc.d.chroot \
--rename /usr/sbin/invoke-rc.d
--divert /usr/sbin/invoke-rc.d.chroot \
--rename /usr/sbin/invoke-rc.d
cp /bin/true /usr/sbin/invoke-rc.d
echo -e "#!/bin/sh\nexit 101" > /usr/sbin/policy-rc.d
chmod +x /usr/sbin/policy-rc.d
@ -222,163 +169,98 @@ dpkg-divert --remove --rename /usr/sbin/invoke-rc.d
EOF
fi
chroot-script dpkgdivert || zerr
chroot-script "$werdo/dpkgdivert" || { zerr; return 1; }
}
enableserv() {
fn enableserv "$@"
local service="$1"
req=(service strapdir)
ckreq || return 1
cat <<EOF | sudo tee -a ${strapdir}/enserv >/dev/null
#!/bin/sh
update-rc.d ${service} enable
EOF
notice "enabling $service service"
chroot-script enserv
}
disableserv() {
fn disableserv "$@"
local service="$1"
req=(service strapdir)
ckreq || return 1
cat <<EOF | sudo tee -a ${strapdir}/disserv >/dev/null
#!/bin/sh
update-rc.d ${service} disable
EOF
notice "disabling $service service"
chroot-script disserv
}
install-custdebs() {
fn install-custdebs
req=(R strapdir custom_deb_packages)
ckreq || return 1
sudo mkdir -p $strapdir/debs
sudo cp $R/extra/custom-packages/*.deb $strapdir/debs/
cat <<EOF | sudo tee ${strapdir}/install-debs >/dev/null
#!/bin/sh
cd /debs
for deb in ${custom_deb_packages}; do
dpkg -i \$deb
apt-get --yes --force-yes -f install
done
cd /
apt-get --yes --force-yes autoremove
rm -rf /debs
EOF
chroot-script -d install-debs
}
chroot-script() {
fn chroot-script "$@"
req=(strapdir)
chroot-script()
{
fn chroot-script "$*"
req=(R workdir strapdir)
ckreq || return 1
mkdir -p "$R/log"
local _divert=""
local _path=""
local _script=""
case "x$1" in
x-d)
local script="$2"
devprocsys mount "$strapdir" || zerr
dpkgdivert on "$strapdir" || zerr
[[ "$APT_CACHE" = 1 ]] && { aptcache on "$strapdir/mnt" || zerr }
## logging
sudo sed -i "$strapdir/$script" \
-e 's@#!/bin/sh@#!/bin/sh\'$'\nset -x ; exec 2>/'$script'.log ; export DEBIAN_FRONTEND=noninteractive@'
notice "chrooting to execute $script..."
sudo chmod +x "$strapdir/$script" || zerr
sudo chroot "$strapdir" "/$script" || zerr
sudo mv -f "$strapdir/${script}.log" "$R/log/"
[[ "$APT_CACHE" = 1 ]] && { aptcache off "$strapdir/mnt" || zerr }
dpkgdivert off "$strapdir" || zerr
devprocsys umount "$strapdir" || zerr
;;
*)
local script="$1"
[[ "$APT_CACHE" = 1 ]] && { aptcache on "$strapdir/mnt" || zerr }
## logging
sudo sed -i "$strapdir/$script" \
-e 's@#!/bin/sh@#!/bin/sh\'$'\nset -x ; exec 2>/'$script'.log@'
notice "chrooting to execute $script..."
sudo chmod +x "$strapdir/$script" || zerr
sudo chroot "$strapdir" "/$script" || zerr
sudo mv -f "$strapdir/${script}.log" "$R/log/"
[[ "$APT_CACHE" = 1 ]] && { aptcache off "$strapdir/mnt" || zerr }
;;
x-d)
_divert=1
shift
;;
esac
sudo rm -f $strapdir/$script
if [[ "$(dirname "$1")" = "." ]]; then
_path="$strapdir"
else
_path="$(dirname "$1")"
fi
_script="$(basename "$1")"
if [[ -n "$_divert" ]]; then
devprocsys mount "$_path" || { zerr; return 1; }
dpkgdivert on "$_path" || { zerr; return 1; }
fi
sudo sed -i "$_path/$_script" \
-e 's@^#!/bin/sh@&\nexport DEBIAN_FRONTEND=noninteractive@' \
-e 's@^#!/bin/sh@&\nexport LC_ALL=C@' \
-e 's@^#!/bin/sh@&\nexport LANG=C@' \
-e 's@^#!/bin/sh@&\nset -x ; exec 2>/'$_script'.log@'
notice "Chrooting to execute '$_script' ..."
sudo chmod +x "$_path/$_script" || { zerr; return 1; }
sudo chroot "$_path" "/$_script" || { zerr; return 1; }
sudo mv -f "$_path/${_script}.log" "$R/log/"
if [[ -n "$_divert" ]]; then
dpkgdivert off "$_path" || { zerr; return 1; }
devprocsys umount "$_path" || { zerr; return 1; }
fi
sudo rm -f "$_path/$_script"
}
install_fake_package() {
fn install_fake_package "$@"
req=(strapdir pkgname pkgver section)
local pkgname="$1"
local pkgver="$2"
local section="$3"
findloopdev()
{
fn findloopdev
req=(workdir image_name)
ckreq || return 1
local _tmp="$strapdir/tmp"
sudo mkdir -p "$_tmp/$pkgname"
local _l="$(sudo losetup -f --show "$workdir/${image_name}.img")"
if [[ -z "$_l" ]]; then
zerr; return 1
fi
cat <<EOF | sudo tee ${_tmp}/${pkgname}/${pkgname}_${pkgver}.control >/dev/null
Section: ${section}
Priority: optional
Homepage: https://devuan.org/
Standards-Version: 3.9.6
Package: ${pkgname}
Version: ${pkgver}
Maintainer: Devuan developers <onelove@devuan.org>
Architecture: all
Description: (Fake) ${pkgname}
Dummy package used to meet some dependencies without installing the
real ${pkgname} package.
EOF
cat <<EOF | sudo tee ${strapdir}/install-fake-package >/dev/null
#!/bin/sh
cd /tmp/${pkgname}
equivs-build ${pkgname}_${pkgver}.control \
&& dpkg -i ${pkgname}_${pkgver}_all.deb || exit 1
cd /tmp
rm -rf ${pkgname}
EOF
chroot-script install-fake-package || zerr
echo "$_l"
}
blend_preinst() {
fn blend_preinst
func "not overriden"
return 0
findnbddev()
{
fn findnbddev
notice "Finding a free /dev/nbd device"
for i in $(seq 0 8); do
grep -q "^/dev/nbd${i}" /proc/mounts || {
echo "/dev/nbd${i}"
return
}
done
zerr; return 1
}
blend_postinst() {
fn blend_postinst
func "not overriden"
return 0
}
silly() {
silly()
{
fn silly "$@"
local arg1="$1"
local arg2="$2"
## cheers mailpile!
funneh=("do not think of purple hippos"
# Cheers Mailpile!
funneh=(
"do not think of purple hippos"
"increasing entropy & scrambling bits"
"indexing kittens..."
"patching bugs..."
@ -406,10 +288,20 @@ silly() {
"Supplying monkeys with typewriters"
"Swapping time and space"
"Self potato"
"god is porco"
"God is porco"
"A million hamsters are spinning their wheels right now"
)
local rnd=$(shuf -i1-$#funneh -n 1)
act "${funneh[$rnd]}"
[[ $arg1 = sleep ]] && sleep $arg2 || true
}
blend_preinst()
{
fn blend_preinst "(noop)"
}
blend_postinst()
{
fn blend_postinst "(noop)"
}

View File

@ -1,4 +1,5 @@
#!/usr/bin/env zsh
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
@ -17,305 +18,337 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
## imagine images
vars+=(bootpart rootpart loopdevice)
vars+=(image_name bootpart rootpart loopdevice filesystem)
arrs+=(fsargs)
strapdir_to_image()
{
fn strapdir_to_image
req=(workdir strapdir bootpart rootpart loopdevice)
ckreq || return 1
image_prepare_raw() {
notice "Copying strapdir to image ..."
if [[ ! -d "$workdir/mnt" ]]; then
die "$workdir/mnt doesn't exist. Did you run image_mount?"
zerr; return 1
fi
pushd "$strapdir"
sudo find . \
-not -path "./dev/*" \
-a -not -path "./proc/*" \
-a -not -path "./sys/*" \
| sudo cpio -p "$workdir/mnt" || { zerr; return 1; }
popd
}
image_prepare_raw()
{
fn image_prepare_raw
req=(workdir size image_name)
ckreq || return 1
notice "creating raw image file from zeroes..."
dd if=/dev/zero \
of=$workdir/${image_name}.img \
bs=1M \
count=$size
notice "Creating raw image of $size MB"
touch "$workdir/${image_name}.img"
chattr +C "$workdir/${image_name}.img"
dd if=/dev/zero of="$workdir/${image_name}.img" bs=1M count="$size" || { zerr; return 1; }
}
image_format_partitions() {
image_prepare_qcow2()
{
fn image_prepare_qcow2
req=(workdir size image_name)
ckreq || return 1
notice "Creating qcow2 image of $size MB"
touch "$workdir/${image_name}.qcow2"
chattr +C "$workdir/${image_name}.qcow2"
qemu-img create -f qcow2 "${workdir}/${image_name}.qcow2" "${size}M" || { zerr; return 1; }
}
image_format_partitions()
{
fn image_format_partitions
req=(bootfs bootpart rootpart)
ckreq || return 1
notice "formatting partitions..."
case "$bootfs" in
none)
act "skipping boot partition"
;;
vfat|fat|dos)
act "formatting boot as vfat"
sudo mkfs.vfat ${=bootopts} ${bootpart}
;;
ext4)
act "formatting boot as ext4"
sudo mkfs.ext4 ${=bootopts} ${bootpart}
;;
ext2)
act "formating boot as ext2"
sudo mkfs.ext2 ${=bootopts} ${bootpart}
;;
*)
error "unknown parted_bootfs type '$bootfs'"
zerr
;;
esac
notice "Formatting image partitions"
# default to ext4
[[ -z "$rootfs" ]] && rootfs=ext4
case "$bootfs" in
none)
act "Skipping boot partition"
;;
vfat|fat|dos)
act "Formatting boot as VFAT"
sudo mkfs.vfat ${=bootopts} "${bootpart}" || { zerr; return 1; }
;;
ext?)
act "Formatting boot as $bootfs"
sudo mkfs.${bootfs} ${=bootopts} "${bootpart}" || { zerr; return 1; }
;;
btrfs)
act "Formatting boot as btrfs"
sudo mkfs.btrfs ${=bootopts} "${bootpart}" || { zerr; return 1; }
;;
"")
die "No bootfs filesystem set!"
zerr; return 1
;;
*)
die "Unimplemented filesystem: $bootfs"
die "Please report it for inclusion."
zerr; return 1
;;
esac
case "$rootfs" in
none)
act "skipping root partition"
;;
vfat|fat|dos)
act "formatting root as vfat"
sudo mkfs.vfat ${=rootopts} ${rootpart}
;;
ext4)
act "formatting root as ext4"
sudo mkfs.ext4 ${=rootopts} ${rootpart}
;;
ext2)
act "formating root as ext2"
sudo mkfs.ext2 ${=rootopts} ${rootpart}
;;
btrfs)
act "formatting root as btrfs"
sudo mfks.btrfs ${=rootopts} ${rootpart}
;;
*)
error "unknown parted_rootfs type '$rootfs'"
zerr
;;
none)
act "Skipping root partition"
;;
vfat|fat|dos)
act "Formatting root as VFAT"
sudo mkfs.vfat ${=rootopts} "${rootpart}" || { zerr; return 1; }
;;
ext?)
act "Formatting root as $rootfs"
sudo mkfs.${rootfs} ${=rootopts} "${rootpart}" || { zerr; return 1; }
;;
btrfs)
act "Formatting root as btrfs"
sudo mkfs.btrfs ${=rootopts} "${rootpart}" || { zerr; return 1; }
;;
"")
die "No rootfs filesystem set!"
zerr; return 1
;;
*)
die "Unimplemented filesystem: $rootfs"
die "Please report it for inclusion."
zerr; return 1
;;
esac
}
image_partition_raw_dos() {
fn image_partition_raw_dos
req=(workdir image_name parted_boot parted_root)
image_connect_raw()
{
fn image_connect_raw
req=(workdir image_name)
ckreq || return 1
notice "partitioning raw dos image..."
notice "Connecting raw image to loop device"
parted $workdir/${image_name}.img --script -- mklabel msdos
parted $workdir/${image_name}.img --script -- mkpart primary ${parted_boot}
parted $workdir/${image_name}.img --script -- mkpart primary ${parted_root}
[ -n "$bootable_part" ] && \
parted "$workdir/${image_name}.img" --script -- set "$bootable_part" boot on
## get loopdevice (see ./helpers)
findloopdev
bootpart=${loopdevice}p1
rootpart=${loopdevice}p2
image_format_partitions
}
image_partition_raw_gpt() {
fn image_partition_raw_gpt
req=(workdir image_name gpt_boot gpt_root)
ckreq || return 1
notice "partitioning raw gpt image..."
parted $workdir/${image_name}.img --script -- mklabel gpt || zerr
cgpt create -z $workdir/${image_name}.img || zerr
cgpt create $workdir/${image_name}.img || zerr
cgpt add -i 1 -t kernel -b ${gpt_boot[1]} \
-s ${gpt_boot[2]} \
-l kernel -S 1 -T 5 -P 10 $workdir/${image_name}.img
cgpt add -i 2 -t data -b ${gpt_root[1]} \
-s $(expr $(cgpt show $workdir/${image_name}.img | \
awk '/Sec GPT table/ {print $1}') - ${gpt_root[1]}) \
-l Root $workdir/${image_name}.img
findloopdev
loopdevice="$(findloopdev)"
if [[ -z "$loopdevice" ]]; then
die "Didn't find a free loop device"
zerr; return 1
fi
bootpart="${loopdevice}p1"
rootpart="${loopdevice}p2"
image_format_partitions
}
image_pack_dist() {
fn image_pack_dist
req=(loopdevice image_name strapdir workdir)
image_connect_qcow2()
{
fn image_connect_qcow2
req=(workdir image_name)
ckreq || return 1
notice "packaging image for dist"
notice "Connecting qcow2 image to nbd device"
act "rechecking filesystem"
sudo e2fsck -fy ${loopdevice}p2
sudo resize2fs ${loopdevice}p2
sleep 2
[[ $parted_type = gpt ]] && {
sudo cgpt repair $loopdevice
sleep 1
}
case "$device_name" in
pinephone-dontbeevil)
notice "dd-ing u-boot bootloader to image"
sudo dd if="$R/dist/u-boot-sunxi-with-spl-sopine.bin" \
of="$loopdevice" bs=1024 seek=8 || zerr
;;
esac
sudo partx -dv $loopdevice || {
die "partx failed to remove $loopdevice"
zerr
}
sudo losetup -d $loopdevice || {
die "losetup failed to remove $loopdevice"
zerr
}
if [[ -n "$nocompressimage" ]]; then
_suffix="img"
else
_suffix="img.xz"
sudo modprobe nbd max_part=8 || { zerr; return 1; }
loopdevice="$(findnbddev)"
if [[ -z "$loopdevice" ]]; then
die "Didn't find a free nbd device"
zerr; return 1
fi
pushd $workdir
[[ -n "$nocompressimage" ]] || {
if which pixz > /dev/null ; then
xzcomp=$(which pixz)
else
xzcomp=$(which xz)
fi
notice "compressing image with $xzcomp"
silly
$xzcomp "${image_name}.img"
}
mkdir -p "$R/dist"
mv -v ${image_name}.${_suffix} $R/dist/
pushd "$R/dist"
notice "generating sha256 for ${image_name}.${_suffix}"
sha256sum ${image_name}.${_suffix} > ${image_name}.${_suffix}.sha
notice "generating sha256 for ${image_name}.tar.gz"
sha256sum ${image_name}.tar.gz > ${image_name}.tar.gz.sha
popd
popd
[[ $DEBUG = 1 ]] || sudo rm -r $workdir
notice "finished packing $image_name"
act "find it in $R/dist/"
act "thanks for being patient!"
sudo qemu-nbd --connect="${loopdevice}" "$workdir/${image_name}.qcow2" || { zerr; return 1; }
}
image_raw_mount() {
fn image_raw_mount
image_partition_dos()
{
fn image_partition_dos
req=(loopdevice bootpart rootpart dos_boot dos_root)
ckreq || return 1
notice "Partitioning dos image"
sudo parted "$loopdevice" --script -- mklabel msdos || { zerr; return 1; }
sudo parted "$loopdevice" --script -- mkpart primary "$dos_boot" || { zerr; return 1; }
sudo parted "$loopdevice" --script -- mkpart primary "$dos_root" || { zerr; return 1; }
if [[ -n "$bootable_part" ]]; then
sudo parted "$loopdevice" --script -- set "$bootable_part" boot on
fi
sudo partprobe "$loopdevice" || { zerr; return 1; }
}
image_mount()
{
fn image_mount
req=(workdir bootpart rootpart bootfs)
ckreq || return 1
mkdir -p $workdir/mnt
sudo mount $rootpart $workdir/mnt && \
act "mounted root partition" || zerr
notice "Mounting image to $workdir/mnt"
[[ "$bootfs" == none ]] || {
sudo mkdir -p $workdir/mnt/boot
sudo mount $bootpart $workdir/mnt/boot && \
act "mounted boot partition" || zerr
}
mkdir -p "$workdir/mnt"
sudo mount "$rootpart" "$workdir/mnt" || { zerr; return 1; }
act "Mounted root partition"
if [[ "$bootfs" = none ]]; then
return
fi
sudo mkdir -p "$workdir/mnt/boot"
sudo mount "$bootpart" "$workdir/mnt/boot" || { zerr; return 1; }
act "Mounted boot partition"
}
image_raw_umount() {
fn image_raw_umount
image_umount()
{
fn image_umount
req=(workdir bootpart rootpart)
ckreq || return 1
[[ "$bootfs" == none ]] || {
sudo umount $workdir/mnt/boot && act "unmounted boot partition" || zerr
sleep 1
notice "Umounting image from $workdir/mnt"
sudo umount -R "$workdir/mnt" || { zerr; return 1; }
act "Umounted"
act "Flushing bytes and buffers"
sudo blockdev --flushbufs "$loopdevice" || { zerr; return 1; }
sudo python -c 'import os; os.fsync(open("'$loopdevice'", "r+b"))' || { zerr; return 1; }
}
image_disconnect_raw()
{
fn image_disconnect_raw
req=(loopdevice bootfs rootfs bootpart rootpart)
ckreq || return 1
notice "Disconnecting image from $loopdevice"
act "Rechecking filesystems"
case "$bootfs" in
ext?)
sudo e2fsck -fy "$bootpart"
sudo resize2fs "$bootpart"
;;
esac
case "$rootfs" in
ext?)
sudo e2fsck -fy "$rootpart"
sudo resize2fs "$rootpart"
;;
esac
act "Disconnecting"
sudo partx -dv "$loopdevice" || {
die "partx failed to remove $loopdevice"
zerr; return 1
}
sudo losetup -d "$loopdevice" || {
die "losetup failed to remove $loopdevice"
zerr; return 1
}
sudo umount $workdir/mnt && act "unmounted root partition" || zerr
}
image_raw_as_strapdir() {
fn image_raw_as_strapdir
req=(workdir strapdir size)
image_disconnect_qcow2()
{
fn image_disconnect_qcow2
req=(loopdevice bootfs rootfs bootpart rootpart)
ckreq || return 1
pushd "$workdir"
notice "Disconnecting image from $loopdevice"
notice "creating raw image of $size MB"
sudo rm -f base.raw
sudo qemu-img create -f raw base.raw ${size}M || zerr
notice "partitioning"
sudo parted base.raw mktable msdos || zerr
sudo parted base.raw mkpart primary '0%' '100%' || zerr
loopdevice=$(losetup --find)
sudo losetup -P $loopdevice base.raw || zerr
sudo mkfs.ext4 ${loopdevice}p1 || zerr
act "Rechecking filesystems"
case "$bootfs" in
ext?)
sudo e2fsck -fy "$bootpart"
sudo resize2fs "$bootpart"
;;
esac
notice "mounting raw image to strapdir"
sudo mount ${loopdevice}p1 $strapdir
echo 1 | sudo tee ${strapdir}/.keep >/dev/null
case "$rootfs" in
ext?)
sudo e2fsck -fy "$rootpart"
sudo resize2fs "$rootpart"
;;
esac
act "Disconnecting"
sudo qemu-nbd --disconnect "$loopdevice" || { zerr; return 1; }
}
image_raw_to_qcow2()
{
fn image_raw_to_qcow2
req=(image_name workdir)
ckreq || return 1
notice "Converting raw image to qcow2"
pushd "$workdir" || { zerr; return 1; }
touch "${image_name}.qcow2"
chattr +C "${image_name}.qcow2"
qemu-img convert -f raw -O qcow2 "${image_name}.img" "${image_name}.qcow2" || { zerr; return 1; }
popd
}
image_qcow2_as_strapdir() {
fn image_qcow2_as_strapdir
req=(workdir strapdir size)
image_raw_to_vdi()
{
fn image_raw_to_vdi
req=(image_name workdir)
ckreq || return 1
pushd "$workdir"
# default filesystem fallback to ext4
filesystem=${filesystem:-ext4}
notice "creating qcow2 image of $size MB formatted with $filesystem"
rm -f base.qcow2
qemu-img create -f qcow2 base.qcow2 ${size}M || zerr
sudo modprobe nbd max_part=8 || zerr
loopdevice="$(findfreenbd)"
[ -n "$loopdevice" ] || zerr
act "$loopdevice"
sudo qemu-nbd --connect=${loopdevice} base.qcow2 || zerr
notice "partitioning"
sudo parted ${loopdevice} mktable msdos || zerr
sudo parted ${loopdevice} mkpart primary '0%' '100%' || zerr
notice "formatting with $filesystem"
command -v mkfs.${filesystem} >/dev/null || {
error "filesystem tools not found in path: mkfs.${filesystem}"
zerr }
sudo mkfs.${filesystem} ${=fsargs} ${loopdevice}p1 || zerr
notice "mounting qcow2 image to strapdir"
sudo mount ${loopdevice}p1 $strapdir || zerr
echo 1 | sudo tee ${strapdir}/.keep >/dev/null
notice "Converting raw image to vdi"
pushd "$workdir" || { zerr; return 1; }
touch "${image_name}.vdi"
chattr +C "${image_name}.vdi"
qemu-img convert -f raw -O vdi "${image_name}.img" "${image_name}.vdi" || { zerr; return 1; }
#VBoxManage modifyhd "${image_name}.vdi" --type immutable --compact || { zerr; return 1; }
popd
}
tar_strapdir() {
fn tar_strapdir
req=(strapdir)
image_pack_dist()
{
fn image_pack_dist
req=(R image_name workdir)
ckreq || return 1
notice "creating a tarbomb of the rootfs..."
mkdir -p "$R/dist"
notice "Packing up built images"
local _xzcomp=""
local _rsuffix="img"
if [[ -n "$COMPRESS_IMAGE" ]]; then
if command -v pixz >/dev/null; then
_xzcomp="$(command -v pixz)"
else
_xzcomp="$(command -v xz)"
fi
_rsuffix="img.xz"
fi
pushd "$workdir" || { zerr; return 1; }
if [[ -n "$COMPRESS_IMAGE" ]]; then
act "Compressing images with $_xzcomp"
silly
$_xzcomp "${image_name}.img" || { zerr; return 1; }
# TODO: cpio image?
fi
act "Calculating sha256 checksums"
silly
pushd "$strapdir"
sudo tar czf "$R/dist/${image_name}.tar.gz" . \
--acls --selinux --xattrs \
--xattrs-include=security.capability \
--xattrs-include=user.pax.flags || zerr
sha256sum "${image_name}.${_rsuffix}" > "${image_name}.${_rsuffix}.sha256"
# TODO: cpio image?
mkdir -p "$R/dist"
mv -v "${image_name}".* "$R/dist" || { zerr; return 1; }
notice "Done! Thanks for being patient!"
popd
}

125
zlibs/iso
View File

@ -1,5 +1,6 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2017 Dyne.org Foundation
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
@ -17,54 +18,55 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
## burn baby
vars+=(MKEFI)
#[[ $INSTALLER = 1 ]] && base_packages+=(grub-pc)
iso_prepare_strap() {
iso_prepare_strap()
{
fn iso_prepare_strap
req=(strapdir)
ckreq || return 1
notice "preparing strapdir for livecd"
notice "Preparing strapdir for Live CD"
cat <<EOF | sudo tee ${strapdir}/isoprep >/dev/null
cat <<EOF | sudo tee "$strapdir/isoprep" >/dev/null
#!/bin/sh
apt-get update
apt-get --yes --force-yes install dialog live-boot live-boot-initramfs-tools
apt-get --yes --force-yes autoremove
apt-get --yes --force-yes install dialog live-boot live-boot-initramfs-tools || exit 1
apt-get --yes --force-yes --purge autoremove || exit 1
EOF
chroot-script -d isoprep || zerr
chroot-script -d isoprep || { zerr; return 1; }
}
iso_setup_isolinux() {
iso_setup_isolinux()
{
fn iso_setup_isolinux
req=(workdir strapdir)
ckreq || return 1
notice "setting up isolinux"
notice "Setting up isolinux"
pushd $workdir
pushd "$workdir" || { zerr; return 1; }
sudo mkdir -p binary/{live,isolinux}
act "copying kernel and initrd"
sudo cp $strapdir/boot/vmlinuz* binary/live/vmlinuz
sudo cp $strapdir/boot/initrd* binary/live/initrd.img
#sudo cp $strapdir/boot/memtest86+.bin binary/live/memtest
sudo cp "$R"/extra/syslinux/isolinux.bin binary/isolinux || zerr
sudo cp "$R"/extra/syslinux/*.c32 binary/isolinux || zerr
act "Copyring kernel and initrd"
sudo cp "$strapdir/boot/"vmlinuz* binary/live/vmlinuz || { zerr; return 1; }
sudo cp "$strapdir/boot/"initrd* binary/live/initrd.img || { zerr; return 1; }
#sudo cp "$strapdir/boot/memtest86+.bin binary/live/memtest || { zerr; return 1; }
sudo cp "$R/extra/syslinux/isolinux.bin" binary/isolinux || { zerr; return 1; }
sudo cp "$R"/extra/syslinux/*.c32 binary/isolinux || { zerr; return 1; }
popd
}
iso_write_isolinux_cfg() {
iso_write_isolinux_cfg()
{
fn iso_write_isolinux_cfg
req=(workdir arch os)
ckreq || return 1
notice "writing isolinux configuration"
cat <<EOF | sudo tee ${workdir}/binary/isolinux/isolinux.cfg >/dev/null
notice "Writing isolinux configuration"
cat <<EOF | sudo tee "$workdir/binary/isolinux/isolinux.cfg" >/dev/null
ui vesamenu.c32
prompt 0
menu title ${os} boot menu
@ -80,49 +82,51 @@ endtext
EOF
}
iso_squash_strap() {
iso_squash_strap()
{
fn iso_squash_strap
req=(workdir strapdir)
ckreq || return 1
notice "creating squashfs out of strapdir"
notice "Creating squashfs out of strapdir"
case "$arch" in
amd64|i386)
_compfilt="-Xbcj x86"
;;
arm*)
_compfilt="-Xbcj arm"
;;
*)
_compfilt=""
;;
amd64|i386)
_compfilt="-Xbcj x86"
;;
arm*)
_compfilt="-Xbcj arm"
;;
*)
_compfilt=""
;;
esac
pushd $workdir
sudo mksquashfs $strapdir binary/live/filesystem.squashfs \
-comp xz ${=_compfilt} -noappend || zerr
pushd "$workdir" || { zerr; return 1; }
sudo mksquashfs "$strapdir" binary/live/filesystem.squashfs \
-comp xz ${=_compfilt} -noappend || { zerr; return 1; }
popd
}
iso_xorriso_build() {
iso_xorriso_build()
{
fn iso_xorriso_build
req=(workdir image_name)
ckreq || return 1
notice "building iso..."
notice "Building iso..."
isoname="${image_name}-live.iso"
[[ -n "$mkefi" ]] && {
uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
}
if [[ -n "$MKEFI" ]]; then
uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
fi
isohybrid="$R"/extra/syslinux/isohdpfx.bin
isohybrid="$R/extra/syslinux/isohdpfx.bin"
mkdir -p $R/dist
pushd $workdir
mkdir -p "$R/dist"
pushd "$workdir"
sudo xorriso -as mkisofs -r -J -joliet-long -l \
-isohybrid-mbr $isohybrid \
-isohybrid-mbr "$isohybrid" \
-partition_offset 16 \
-A "${os} Live - ${arch}" \
-b isolinux/isolinux.bin \
@ -131,21 +135,20 @@ iso_xorriso_build() {
-boot-load-size 4 \
-boot-info-table \
${=uefi_opt} \
-o $R/dist/$isoname \
binary || zerr
-o "$R/dist/$isoname" \
binary || { zerr; return 1; }
popd
unset uefi_opt
[[ "$DEBUG" = 1 ]] || {
[[ -n "$workdir" ]] && sudo rm -rf "$workdir"
}
}
iso_setup_installer() {
fn iso_setup_installer
notice "setting up devuan-installer"
sudo cp $R/extra/installer/* $strapdir/
## TODO: init to script
act "Calculating sha256 checksums"
pushd "$R/dist" || { zerr; return 1; }
sha256sum "$isoname" > "${isoname}.sha256"
popd
if [[ "$DEBUG" = 1 ]]; then
return
fi
sudo rm -rf "$workdir"
notice "Done! Thanks for being patient!"
}

View File

@ -1,40 +0,0 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2017 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
#
# This source code 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 software 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 source code. If not, see <http://www.gnu.org/licenses/>.
## all windows users are suckers
build_kernel_${arch}() {
fn build_kernel_${arch}
req=(strapdir arch)
ckreq || return 1
local kernel_base="linux-image"
case "$arch" in
amd64) local kernel="${kernel_base}-amd64";;
i386) local kernel="${kernel_base}-586";;
esac
notice "installing stock kernel for $arch"
cat <<EOF | sudo tee ${strapdir}/install-linux
#!/bin/sh
apt-get --yes --force-yes install ${kernel}
EOF
chroot-script -d install-linux || zerr
}

View File

@ -1,44 +0,0 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
#
# This source code 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 software 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 source code. If not, see <http://www.gnu.org/licenses/>.
## ilpd
rsync_to_raw_image() {
fn rsync_to_raw_image
req=(workdir strapdir bootpart rootpart)
ckreq || return 1
notice "Preparing to rsync and tar the rootfs..."
image_raw_mount
silly sleep 1
mkdir -p $R/dist
pushd $strapdir
tar_strapdir || zerr
notice "rsyncing strapdir to raw image..."
sudo rsync -HPaq ./* $workdir/mnt || {
image_raw_umount
die "not enough space, please report a bug"
zerr
}
popd
image_raw_umount
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2019 Dyne.org Foundation
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
@ -95,7 +95,6 @@ conf_print_resolvconf() {
fn conf_print_resolvconf
cat <<EOF
## google's nameservers
nameserver 8.8.8.8
nameserver 8.8.4.4
EOF
@ -106,21 +105,14 @@ conf_print_sourceslist() {
req=(mirror release section)
ckreq || return 1
[[ $APT_CACHE = 1 ]] && {
cat <<EOF
deb file:/mnt ./
EOF
}
cat <<EOF
## package repositories
# Package repositories
deb ${mirror} ${release} ${section}
deb ${mirror} ${release}-updates ${section}
deb ${mirror} ${release}-security ${section}
#deb ${mirror} ${release}-backports ${section}
## source repositories
# Source repositories
#deb-src ${mirror} ${release} ${section}
#deb-src ${mirror} ${release}-updates ${section}
#deb-src ${mirror} ${release}-security ${section}

244
zlibs/vm
View File

@ -1,5 +1,6 @@
#!/usr/bin/env zsh
# Copyright (c) 2016-2018 Dyne.org Foundation
# shellcheck shell=bash
# Copyright (c) 2016-2020 Dyne.org Foundation
# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
#
# This file is part of libdevuansdk
@ -17,17 +18,17 @@
# You should have received a copy of the GNU General Public License
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
## ma baker
vars+=(vmname)
vm_inject_overrides() {
vm_inject_overrides()
{
fn vm_inject_overrides
req=(strapdir)
ckreq || return 1
notice "injecting rootfs overrides"
cat <<EOF | sudo tee ${strapdir}/etc/rc.local >/dev/null
notice "Injecting rootfs overrides"
cat <<EOF | sudo tee "$strapdir/etc/rc.local" >/dev/null
#!/bin/sh
# rc.local for base images
@ -35,210 +36,69 @@ vm_inject_overrides() {
exit 0
EOF
sudo chmod +x $strapdir/etc/rc.local
sudo chmod +x "$strapdir/etc/rc.local"
print "rootfs / rootfs rw 0 0" | sudo tee ${strapdir}/etc/fstab >/dev/null
sudo sed -i ${strapdir}/etc/ssh/sshd_config \
sudo sed -i "$strapdir/etc/ssh/sshd_config" \
-e 's/#PermitRootLogin .*/PermitRootLogin yes/' \
-e 's/PermitRootLogin .*/PermitRootLogin yes/'|| zerr
-e 's/PermitRootLogin .*/PermitRootLogin yes/' || { zerr; return 1; }
}
vm_setup_grub() {
fn vm_setup_grub
req=(strapdir loopdevice)
ckreq || return 1
notice "setting up grub"
cat <<EOF | sudo tee ${strapdir}/setupgrub >/dev/null
#!/bin/sh
export DEBIAN_FRONTEND=noninteractive
apt-get --yes --force-yes install linux-image-amd64 grub-pc
sed -e 's:GRUB_TIMEOUT=5:GRUB_TIMEOUT=1:' -i /etc/default/grub
sed -e 's:GRUB_CMDLINE_LINUX_DEFAULT=".*":GRUB_CMDLINE_LINUX_DEFAULT="net.ifnames=0":' \
-i /etc/default/grub
update-grub
grub-install --no-floppy --recheck --modules="biosdisk part_msdos" \
${loopdevice}
sed -e 's:${loopdevice}p1:/dev/sda1:g' -i /boot/grub/grub.cfg
sync; sync; sync
EOF
chroot-script -d setupgrub || zerr
}
vm_umount_${imageformat}() {
fn vm_umount_${imageformat}
req=(strapdir loopdevice imageformat)
ckreq || return 1
notice "remounting ${imageformat} image"
sudo mount -o remount,ro $strapdir || zerr
notice "flushing bytes and buffers"
sudo blockdev --flushbufs $loopdevice || zerr
sudo python -c 'import os;os.fsync(open("'${loopdevice}'", "r+b"))' || zerr
notice "unmounting ${imageformat} image from strapdir"
sudo umount $strapdir || zerr
silly sleep 1
sudo rmdir $strapdir || zerr
notice "cleaning up"
case "$imageformat" in
raw)
sudo losetup -d ${loopdevice} || zerr
;;
qcow2)
sudo qemu-nbd --disconnect ${loopdevice} || zerr
;;
*)
zerr
;;
esac
silly sleep 1
}
vm_vbox_setup() {
fn vm_vbox_setup
req=(workdir imageformat)
ckreq || return 1
notice "converting ${imageformat} image to vdi"
pushd $workdir
qemu-img convert \
-f ${imageformat} \
-O vdi \
base.${imageformat} \
base.vdi || zerr
VBoxManage modifyhd base.vdi --type immutable --compact || zerr
vmname="${os}-${release}-prevagrant-${RANDOM}"
notice "importing base.vdi to a VBox"
act "creating vm"
VBoxManage createvm --name "$vmname" --ostype Debian_64 --register || zerr
act "setting up ram and group"
VBoxManage modifyvm "$vmname" --memory 256 --groups /vmsdk || zerr
act "setting up storage"
VBoxManage storagectl "$vmname" --name "IDE Controller" --add ide || zerr
act "attaching storage"
VBoxManage storageattach "$vmname" --storagectl "IDE Controller" --port 0 \
--device 0 --type hdd --medium base.vdi || zerr
vminfo="$(VBoxManage showvminfo "$vmname" --machinereadable)"
diskuuid="$(getfield "$vminfo" '"IDE Controller-ImageUUID-0-0"')"
act "autoreset off on storage"
VBoxManage modifyhd "$diskuuid" --autoreset off || zerr
act "setting up nat network"
VBoxManage modifyvm "$vmname" --nic1 nat || zerr
popd
}
vm_vagrant_package() {
fn vm_vagrant_package
req=(workdir vmname)
ckreq || return 1
notice "packaging a vagrant box"
pushd $workdir
act "creating vagrantfile"
cat <<EOF > Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "devuanbox.box"
config.ssh.username = "root"
config.ssh.password = "toor"
config.vm.guest = :debian
config.vm.synced_folder ".", "/vagrant", disabled: true
# https://github.com/dotless-de/vagrant-vbguest
end
EOF
act "creating metadata.json"
cat <<EOF > metadata.json
vm_setup_grub()
{
"provider": "virtualbox"
}
EOF
notice "actually packaging..."
vagrant package --base "$vmname" --output ${vm_name}.box \
--include metadata.json --vagrantfile Vagrantfile || zerr
popd
}
vm_init_cloud() {
fn vm_init_cloud
req=(workdir strapdir imageformat loopdevice)
fn vm_setup_grub
req=(workdir loopdevice bootfs)
ckreq || return 1
[[ -n "$makecloud" ]] || return
[[ "$imageformat" = qcow2 ]] || {
die "imageformat is not qcow2"
zerr
}
notice "Setting up grub"
notice "Creating a cloud-based image"
pushd "$workdir"
cp -v "base.qcow2" "base-cloud.qcow2"
notice "Connecting qemu-nbd and mounting"
sudo mkdir -p "$strapdir"
sudo qemu-nbd --connect=${loopdevice} base-cloud.qcow2 || zerr
silly sleep 1
sudo mount ${loopdevice}p1 $strapdir || zerr
notice "Installing cloud-init"
cat <<EOF | sudo tee ${strapdir}/initcloud >/dev/null
cat <<EOF | sudo tee "$workdir/mnt/setupgrub" >/dev/null
#!/bin/sh
apt-get update
apt-get --yes --force-yes install cloud-init
apt-get clean
grub-install "${loopdevice}" || exit 1
grub-mkconfig -o /boot/grub/grub.cfg || exit 1
EOF
chroot-script -d initcloud || zerr
vm_umount_${imageformat} || zerr
popd
chroot-script -d "$workdir/mnt/setupgrub" || { zerr; return 1; }
}
vm_pack_dist() {
vm_pack_dist()
{
fn vm_pack_dist
req=(workdir imageformat)
req=(R workdir image_name imageformat)
ckreq || return 1
notice "packing up dist"
mkdir -p $R/dist
mv $workdir/${vm_name}.box $R/dist
mv $workdir/base.${imageformat} $R/dist/${vm_name}.${imageformat}
cp $workdir/base.vdi $R/dist/${vm_name}.vdi
notice "Packing up built images"
[[ -n "$makecloud" ]] && \
mv $workdir/base-cloud.${imageformat} \
$R/dist/${vm_name}-cloud.${imageformat}
local _xzcomp=""
local _rsuffix="${imageformat}"
local _vsuffix="vdi"
act "calculating sha256 sums..."
if [[ -n "$COMPRESS_IMAGE" ]]; then
if command -v pixz >/dev/null; then
_xzcomp="$(command -v pixz)"
else
_xzcomp="$(command -v xz)"
fi
_rsuffix="${imageformat}.xz"
_vsuffix="vdi.xz"
fi
pushd "$workdir" || { zerr; return 1; }
if [[ -n "$COMPRESS_IMAGE" ]]; then
act "Compressing images with $_xzcomp"
silly
$_xzcomp "${image_name}.${imageformat}" || { zerr; return 1; }
$_xzcomp "${image_name}.vdi" || { zerr; return 1; }
fi
act "Calculating sha256 checksums"
silly
sha256sum $R/dist/${vm_name}.box > \
$R/dist/${vm_name}.box.sha
sha256sum $R/dist/${vm_name}.${imageformat} > \
$R/dist/${vm_name}.${imageformat}.sha
sha256sum $R/dist/${vm_name}.vdi > \
$R/dist/${vm_name}.vdi.sha
[[ -n "$makecloud" ]] && \
sha256sum $R/dist/${vm_name}-cloud.${imageformat} > \
$R/dist/${vm_name}-cloud.${imageformat}.sha
sha256sum "${image_name}.${_rsuffix}" > "${image_name}.${_rsuffix}.sha256"
sha256sum "${image_name}.${_vsuffix}" > "${image_name}.${_vsuffix}.sha256"
mkdir -p "$R/dist"
mv -v "${image_name}".* "$R/dist" || { zerr; return 1; }
notice "Done! Thanks for being patient!"
notice "cleaning up virtualbox leftovers"
pushd "$workdir"
VBoxManage unregistervm "$vmname" --delete
rm -f metadata.json Vagrantfile
rm -rf .vagrant
popd
rm -rf "$workdir"
rm -rf "$HOME/VirtualBox VMs/vmsdk"
notice "done!"
ls -1 $R/dist
}