#!/bin/bash

# create an image that looks like a classic image
# Note that "mk-image" is left as a script so that it can also be
# run outside of spread easily for quick interactive testing

DEFAULT_BASE_DIR="/tmp/mkimage"
DEFAULT_BOOT_IMG="boot.img"
DEFAULT_CACHE_DIR="cache"
DEFAULT_MNT_DIR="mnt"
DEFAULT_SNAPD_BINPATH="/usr/lib/snapd"
DEFAULT_BASE_IMAGE_URL="http://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04-base-amd64.tar.gz"
DEFAULT_SNAPD_DEB_URL=https://storage.googleapis.com/snapd-spread-tests/snapd-tests/packages/ubuntu-22.04-64.tar 

show_help() {
    echo "usage: mkimage-uc22 [--boot-img BOOT_IMG] [--cache-dir CACHE_DIR] [--mnt-dir MNT_DIR] [--snap <SNAP_PATH> ...] model_assertion" 
    echo ""
    echo "create an image that looks like a classic image"
    echo ""
    echo "Available options:"
    echo "  -h --help   show this help message."
    echo ""
}

find_snap(){
    local SNAPS_DIR="$1"
    local SNAP="$2"
    find "$SNAPS_DIR" -maxdepth 1 -name "${SNAP}_*.snap" -printf "%f\n"
}

get_extra_snaps() {
    local SNAPS_DIR="$1"
    local EXTRA_SNAPS=""

    if [ -d "$CACHE_DIR" ]; then
        while IFS= read -r mysnap; do
            echo "$mysnap"
        done < <(find "$SNAPS_DIR" -name '*.snap')
    fi
}

get_assets() {
    local CACHE="$1"
    local BASE_IMAGE_URL="$2"
    local BASE_IMAGE_PATH="$3"
    shift 3
    # shellcheck disable=SC2124
    local SNAPS="$@"

    if [ -d "$CACHE" ]; then
        echo "mkimage-uc22: using existing cache dir $CACHE"
    fi

    for snap in $SNAPS; do
        if [ ! -f "$snap" ]; then
            echo "mkimage-uc22: the provided snap \"$snap\" does not exist" >&2
            return 1
        fi
    done

    mkdir -p "$CACHE"
    # shellcheck disable=SC2086
    cp $SNAPS "$CACHE"

    # get the snaps
    local NAME
    for snap in pc-kernel pc; do        
        NAME="$(find_snap "$CACHE" "$snap")"
        if [ -z "$NAME" ]; then
            echo "mkimage-uc22: downloading snap $snap"
            snap download --channel=22 --target-directory="$CACHE" "$snap"
        else
            echo "mkimage-uc22: using provided snap $NAME"
        fi
        unsquashfs -n -d "$CACHE"/snap-"$snap" "$CACHE"/"${snap}"_*.snap
    done
    for snap in snapd core22; do
        NAME="$(find_snap "$CACHE" "$snap")"
        if [ -z "$NAME" ]; then
            echo "mkimage-uc22: downloading snap $snap"
            snap download --target-directory="$CACHE" "$snap"
        else
            echo "mkimage-uc22: using provided snap $NAME"
        fi
    done

    if [ -n "$BASE_IMAGE_PATH" ]; then
        echo "mkimage-uc22: using local ubuntu classic base from $BASE_IMAGE_PATH"
        cp "$BASE_IMAGE_PATH" "$CACHE"
    else
        echo "mkimage-uc22: downloading the ubuntu classic base"
        wget -q -c -P "$CACHE" "$BASE_IMAGE_URL"
    fi    

    echo "mkimage-uc22: image assets ready"
}

# shellcheck disable=SC2317
cleanup() {
    local IMG MNT
    IMG="$(readlink -f "$1")"
    MNT="$(readlink -f "$2")"

    retry -n 3 --wait 1 sh -c "umount \"$MNT\"/*"
    retry -n 3 --wait 1 sh -c "kpartx -d \"$IMG\""
}

create_image() {
    local IMG
    IMG="$(readlink -f "$1")"

    rm -f "$IMG"
    # We need 6G to for the image as the partitions described below use 5,93G
    # In total the image has 12453854 sectors (512B each)
    truncate --size=6G "$IMG"
    echo "Creating partition on $IMG"
    cat <<EOF | sfdisk -q "$IMG"
label: gpt
device: boot.img
unit: sectors
first-lba: 34
last-lba: 12453854
sector-size: 512

boot.img1 : start=        2048, size=        2048, type=21686148-6449-6E6F-744E-656564454649, uuid=ECD24EAE-A687-4177-9223-6DDB4FCFF842, name="BIOS Boot"
##### no ubuntu-seed on the initial version but we need a EFI system
boot.img2 : start=        4096, size=     202752, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=21A0079F-3E45-4669-8FF2-B3917819279F, name="EFI System partition"
boot.img3 : start=     2461696, size=     1536000, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=338DD9E7-CFE1-524A-A8B6-7D87DA8A4B34, name="ubuntu-boot"
boot.img4 : start=     3997696, size=       32768, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=1144DFB5-DFC2-0745-A1F2-AD311FEBE0DB, name="ubuntu-save"
boot.img5 : start=     4030464, size=     8423391, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B84565A3-E9F8-8A40-AB04-810A4B891F8C, name="ubuntu-data"
EOF
}

install_data_partition() {    
    set -x

    local DESTDIR=$1
    local CACHE=$2
    local MODEL_ASSERTION=$3
    local SEED_LABEL
    SEED_LABEL="classic"

    echo "mkimage-uc22: copying base filesystem"
    sudo tar -C "$DESTDIR" -xf "$CACHE"/ubuntu-base-22.04-base-amd64.tar.gz

    echo "mkimage-uc22: creating basic devices to be able to install packages"
    [ -e "$DESTDIR"/dev/null ] || sudo mknod -m 666 "$DESTDIR"/dev/null c 1 3
    [ -e "$DESTDIR"/dev/zero ] || sudo mknod -m 666 "$DESTDIR"/dev/zero c 1 5
    [ -e "$DESTDIR"/dev/random ] || sudo mknod -m 666 "$DESTDIR"/dev/random c 1 8
    [ -e "$DESTDIR"/dev/urandom ] || sudo mknod -m 666 "$DESTDIR"/dev/urandom c 1 9

    # ensure the proxy and resolv configuration is set inside the chroot
    if [ "${SNAPD_USE_PROXY:-}" = true ]; then
        cp /etc/resolv.conf "$DESTDIR"/etc/resolv.conf
        cp /etc/environment "$DESTDIR"/etc/environment
    else
        echo "nameserver 8.8.8.8" | sudo tee -a "$DESTDIR"/etc/resolv.conf
    fi

    local pkgs="snapd ssh openssh-server sudo iproute2 iputils-ping isc-dhcp-client netplan.io vim-tiny kmod cloud-init jq update-notifier-common systemd-timesyncd"
    echo "mkimage-uc22: installing additional packages: $pkgs"
    sudo chroot "$DESTDIR" /usr/bin/sh -c "DEBIAN_FRONTEND=noninteractive apt -qq update"    
    sudo chroot "$DESTDIR" /usr/bin/sh -c \
         "DEBIAN_FRONTEND=noninteractive apt -qq install --no-install-recommends -y $pkgs" < /dev/null > /dev/null

    echo "mkimage-uc22: configuring netplan"
    cat > "$CACHE"/00-ethernet.yaml <<'EOF'
network:
  ethernets:
    any:
      match:
        name: e*
      dhcp4: true
  version: 2
EOF
    sudo cp "$CACHE"/00-ethernet.yaml "$DESTDIR"/etc/netplan

    echo "mkimage-uc22: mounting bits needed to be able to update boot assets"
    sudo mkdir -p "$DESTDIR"/boot/grub "$DESTDIR"/boot/efi
    sudo tee "$DESTDIR"/etc/fstab <<'EOF'
/run/mnt/ubuntu-boot/EFI/ubuntu /boot/grub none bind 0 0
EOF

    echo "mkimage-uc22: creating users"
    sudo chroot "$DESTDIR" /usr/sbin/adduser --disabled-password --gecos "" user1
    printf "ubuntu\nubuntu\n" | sudo chroot "$DESTDIR" /usr/bin/passwd user1
    echo "user1 ALL=(ALL) NOPASSWD:ALL" | sudo tee -a "$DESTDIR"/etc/sudoers

    # set password for root user
    sudo chroot "$DESTDIR" /usr/bin/sh -c 'echo root:root | chpasswd'
    sudo tee -a "$DESTDIR/etc/ssh/sshd_config" <<'EOF'
PermitRootLogin yes
PasswordAuthentication yes
EOF

    echo "mkimage-uc22: populating snapd data"
    cat > modeenv <<EOF
mode=run
recovery_system=$SEED_LABEL
current_recovery_systems=$SEED_LABEL
good_recovery_systems=$SEED_LABEL
base=$(find_snap "$CACHE" core22)
gadget=$(find_snap "$CACHE" pc)
current_kernels=$(find_snap "$CACHE" pc-kernel)
model=canonical/ubuntu-core-22-pc-amd64
grade=dangerous
model_sign_key_id=9tydnLa6MTJ-jaQTFUXEwHl1yRx7ZS4K5cyFDhYDcPzhS7uyEkDxdUjg9g08BtNn
current_kernel_command_lines=["snapd_recovery_mode=run console=ttyS0 console=tty1 panic=-1"]
EOF
    sudo cp modeenv "$DESTDIR"/var/lib/snapd/
    # needed from the beginning in ubuntu-data as these are mounted by snap-bootstrap
    # (UC also has base here, but we do not mount it from initramfs in classic)
    sudo mkdir -p "$DESTDIR"/var/lib/snapd/snaps/
    sudo cp "$CACHE"/"$(find_snap "$CACHE" pc-kernel)" "$CACHE"/"$(find_snap "$CACHE" pc)" \
         "$DESTDIR"/var/lib/snapd/snaps/

    # clean classic-seed dir
    rm -rf ./classic-seed/

    local EXTRA_SNAPS
    for mysnap in $(get_extra_snaps "$CACHE"); do
        EXTRA_SNAPS="$EXTRA_SNAPS --snap $mysnap"
    done

    # create the seed
    # shellcheck disable=SC2086
    snap prepare-image --classic \
         --channel=edge \
         $EXTRA_SNAPS \
         "$MODEL_ASSERTION" \
         ./classic-seed

    # rename seed-label
    mv ./classic-seed/system-seed/systems/"$(date +%Y%m%d)" ./classic-seed/system-seed/systems/"$SEED_LABEL"
    # and put the seed in place
    mkdir -p "$DESTDIR"/var/lib/snapd
    mv ./classic-seed/system-seed "$DESTDIR"/var/lib/snapd/seed
}

populate_image() {
    local IMG="$1"
    local CACHE="$2"
    local MNT="$3"
    local MODEL_ASSERTION="$4"
    local KERNEL_SNAP
    KERNEL_SNAP="$(find_snap "$CACHE" pc-kernel)"

    mkdir -p "$MNT"
    local loop loop_esp loop_boot loop_save loop_data
    loop=$(sudo kpartx -asv "$IMG" | head -n1 | cut -d' ' -f3)
    loop=${loop%p*}
    loop_esp="${loop}"p2
    loop_boot="${loop}"p3
    loop_save="${loop}"p4
    loop_data="${loop}"p5

    # XXX: on a real UC device this the ESP is "ubuntu-seed"
    sudo mkfs.fat -n ubuntu-seed /dev/mapper/"$loop_esp"
    sudo mkfs.ext4 -L ubuntu-boot -q /dev/mapper/"$loop_boot"
    sudo mkfs.ext4 -L ubuntu-save -q /dev/mapper/"$loop_save"
    sudo mkfs.ext4 -L ubuntu-data -q /dev/mapper/"$loop_data"
    for name in esp ubuntu-boot ubuntu-save ubuntu-data; do
        mkdir -p "$MNT"/"$name"
    done
    sudo mount /dev/mapper/"$loop_esp" "$MNT"/esp
    sudo mount /dev/mapper/"$loop_boot" "$MNT"/ubuntu-boot
    sudo mount /dev/mapper/"$loop_save" "$MNT"/ubuntu-save
    sudo mount /dev/mapper/"$loop_data" "$MNT"/ubuntu-data

    # install things into the image
    install_data_partition "$MNT"/ubuntu-data "$CACHE" "$MODEL_ASSERTION"

    # ESP partition just chainloads into ubuntu-boot
    # XXX: do we want this given that we don't have recovery systems?
    sudo mkdir -p "$MNT"/esp/EFI/boot
    sudo cp "$CACHE"/snap-pc/grubx64.efi "$MNT"/esp/EFI/boot
    sudo cp "$CACHE"/snap-pc/shim.efi.signed "$MNT"/esp/EFI/boot/bootx64.efi
    cat > "$CACHE"/esp-grub.cfg <<'EOF'
set default=0
set timeout=3

search --no-floppy --set=boot_fs --label ubuntu-boot
menuentry "Continue to run mode" --hotkey=n --id=run {
    chainloader ($boot_fs)/EFI/boot/grubx64.efi
}
EOF
    sudo mkdir -p "$MNT"/esp/EFI/ubuntu
    sudo cp "$CACHE"/esp-grub.cfg "$MNT"/esp/EFI/ubuntu/grub.cfg

    # ubuntu-boot
    sudo mkdir -p "$MNT"/ubuntu-boot/EFI/boot
    sudo cp -a "$CACHE"/snap-pc/grubx64.efi "$MNT"/ubuntu-boot/EFI/boot
    sudo cp -a "$CACHE"/snap-pc/shim.efi.signed "$MNT"/ubuntu-boot/EFI/boot/bootx64.efi

    sudo mkdir -p "$MNT"/ubuntu-boot/EFI/ubuntu
    cat > "$CACHE"/grub.cfg <<'EOF'
set default=0
set timeout=3

# load only kernel_status and kernel command line variables set by snapd from
# the bootenv
load_env --file /EFI/ubuntu/grubenv kernel_status snapd_extra_cmdline_args snapd_full_cmdline_args

set snapd_static_cmdline_args='console=ttyS0 console=tty1 panic=-1'
set cmdline_args="$snapd_static_cmdline_args $snapd_extra_cmdline_args"
if [ -n "$snapd_full_cmdline_args" ]; then
    set cmdline_args="$snapd_full_cmdline_args"
fi

set kernel=kernel.efi

if [ "$kernel_status" = "try" ]; then
    # a new kernel got installed
    set kernel_status="trying"
    save_env kernel_status

    # use try-kernel.efi
    set kernel=try-kernel.efi
elif [ "$kernel_status" = "trying" ]; then
    # nothing cleared the "trying snap" so the boot failed
    # we clear the mode and boot normally
    set kernel_status=""
    save_env kernel_status
elif [ -n "$kernel_status" ]; then
    # ERROR invalid kernel_status state, reset to empty
    echo "invalid kernel_status!!!"
    echo "resetting to empty"
    set kernel_status=""
    save_env kernel_status
fi

if [ -e $prefix/$kernel ]; then
menuentry "Run Ubuntu Core 22" {
    # use $prefix because the symlink manipulation at runtime for kernel snap
    # upgrades, etc. should only need the /boot/grub/ directory, not the
    # /EFI/ubuntu/ directory
    chainloader $prefix/$kernel snapd_recovery_mode=run $cmdline_args
}
else
    # nothing to boot :-/
    echo "missing kernel at $prefix/$kernel!"
fi
EOF
    sudo cp -a "$CACHE"/grub.cfg "$MNT"/ubuntu-boot/EFI/ubuntu/
    # This must be exactly 1024 bytes
    local GRUBENV="# GRUB Environment Block
#######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################"
    printf "%s" "$GRUBENV" > "$CACHE"/grubenv
    sudo cp -a "$CACHE"/grubenv "$MNT"/ubuntu-boot/EFI/ubuntu/grubenv
    sudo mkdir -p "$MNT"/ubuntu-boot/device/
    sudo cp -a "$MODEL_ASSERTION" "$MNT"/ubuntu-boot/device/model

    # kernel
    sudo mkdir -p "$MNT"/ubuntu-boot/EFI/ubuntu/"$KERNEL_SNAP"
    sudo cp -a "$CACHE"/snap-pc-kernel/kernel.efi "$MNT"/ubuntu-boot/EFI/ubuntu/"$KERNEL_SNAP"
    sudo ln -sf "$KERNEL_SNAP"/kernel.efi "$MNT"/ubuntu-boot/EFI/ubuntu/kernel.efi

    # cleanup
    sync
    sudo umount "$MNT"/ubuntu-*
}

replace_initramfs_bits() {
    local CACHE="$1"
    local SNAPD_BINPATH="$2"
    # TODO is there code to share with uc20_build_initramfs_kernel_snap in prepare.sh?
    local KERNEL_EFI_ORIG="$CACHE"/snap-pc-kernel/kernel.efi
    if [ ! -d initrd ]; then
        objcopy -O binary -j .initrd "$KERNEL_EFI_ORIG" initrd.img
        unmkinitramfs initrd.img initrd
    fi

    # Retrieve efi stub from ppa so we can rebuild kernel.efi
    DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends ubuntu-dev-tools lz4 < /dev/null > /dev/null
    pull-lp-debs -a amd64 -D ppa --ppa ppa:snappy-dev/image ubuntu-core-initramfs "jammy"
    dpkg --fsys-tarfile ubuntu-core-initramfs_*.deb |
        tar --wildcards -xf - './usr/lib/ubuntu-core-initramfs/efi/linux*.efi.stub'

    cp "$SNAPD_BINPATH"/snap-bootstrap initrd/main/usr/lib/snapd/
    ( cd initrd/main && find . | cpio --create --quiet --format=newc --owner=0:0 | lz4 -l -7 > ../../initrd.img.new )

    objcopy -O binary -j .linux "$KERNEL_EFI_ORIG" linux
    # Replace kernel.efi in unsquashed snap
    objcopy --add-section .linux=linux --change-section-vma .linux=0x2000000 \
            --add-section .initrd=initrd.img.new --change-section-vma .initrd=0x3000000 \
            usr/lib/ubuntu-core-initramfs/efi/linux*.efi.stub \
            "$KERNEL_EFI_ORIG"
}

replace_images_files() {
    local IMG="$1"
    local CACHE="$2"
    local MNT="$3"
    local SNAPD_DEB="$4"
    local SNAPD_BINPATH="$5"

    mkdir -p "$MNT"/ubuntu-boot "$MNT"/data

    replace_initramfs_bits "$CACHE" "$SNAPD_BINPATH"

    loop=$(sudo kpartx -asv "$IMG" | head -n1 | cut -d' ' -f3)
    loop=${loop%p*}
    loop_boot="$loop"p3
    sudo mount /dev/mapper/"$loop_boot" "$MNT"/ubuntu-boot

    # copy kernel.efi with modified initramfs
    local subpath
    subpath=$(readlink "$MNT"/ubuntu-boot/EFI/ubuntu/kernel.efi)
    # TODO we should also repack kernel snap and replace the one in the rootfs too, and also re-sign
    cp -a "$CACHE"/snap-pc-kernel/kernel.efi "$MNT"/ubuntu-boot/EFI/ubuntu/"$subpath"

    # when no snapd deb package provided, the prebuilt one from master is used
    if [ -z "$SNAPD_DEB" ]; then
        wget -q -c -P "$CACHE" "$DEFAULT_SNAPD_DEB_URL"
        tar -xvf "$CACHE"/"$(basename "$DEFAULT_SNAPD_DEB_URL")" -C "$CACHE"
        SNAPD_DEB="$CACHE"/"$(find "$CACHE" -maxdepth 1 -name "snapd_*.deb" -printf "%f\n")"
    fi
    # replace snapd in data partition with the one passed as parameter
    local data_mnt="$loop"p5
    sudo mount /dev/mapper/"$data_mnt" "$MNT"/data
    sudo cp "$SNAPD_DEB" "$MNT"/data/snapd.deb
    sudo chroot "$MNT"/data apt install -qq -y --no-install-recommends ./snapd.deb < /dev/null > /dev/null
    sudo rm "$MNT"/data/snapd.deb
    # enable debug traces
    sudo mkdir -p "$MNT"/data/etc/systemd/system/snapd.service.d/
    sudo tee "$MNT"/data/etc/systemd/system/snapd.service.d/override.conf <<'EOF'
[Service]
Environment=SNAPD_DEBUG=1
EOF
}

show_how_to_run_qemu() {
    local IMG="$1"

    echo "mkimage-uc22: mage ready, run as: "
    echo cp /usr/share/OVMF/OVMF_VARS_4M.fd .
    echo qemu-system-x86_64 -m q35,accel=kvm -m 1500 -snapshot \
        -netdev user,id=net.0,hostfwd=tcp::10022-:22 \
        -device rtl8139,netdev=net.0 \
        -drive file=/usr/share/OVMF/OVMF_CODE_4M.fd,if=pflash,format=raw,readonly=on \
        -drive file=OVMF_VARS_4M.fd,if=pflash,format=raw \
        -drive file="$1",if=virtio \
        -serial stdio

    echo "mkimage-uc22: grub will chainload from ESP to ubuntu-boot"
    echo "mkimage-uc22: there press ESC and add 'dangerous rd.systemd.debug-shell=1' after kernel.efi"
}

main() {
    local BASE_DIR="$DEFAULT_BASE_DIR"
    local BOOT_IMG="$DEFAULT_BOOT_IMG"
    local CACHE_DIR="$DEFAULT_CACHE_DIR"
    local MNT_DIR="$DEFAULT_MNT_DIR"
    local SNAPD_BINPATH="$DEFAULT_SNAPD_BINPATH"
    local BASE_IMAGE_URL="$DEFAULT_BASE_IMAGE_URL"
    
    local SNAPD_DEB=""
    local BASE_IMAGE_PATH=""
    local MODEL_ASSERTION=""
    local SNAPS=""
    while [ $# -gt 0 ]; do
        case "$1" in
            -h|--help)
                show_help
                exit 0
                ;;
            --base-dir)
                BASE_DIR="$2"
                shift 2
                ;;
            --boot-img)
                BOOT_IMG="$2"
                shift 2
                ;;
            --cache-dir)
                CACHE_DIR="$2"
                shift 2
                ;;
            --mnt-dir)
                MNT_DIR="$2"
                shift 2
                ;;
            --snapd-deb)
                SNAPD_DEB="$2"
                shift 2
                ;;
            --snapd-binpath)
                SNAPD_BINPATH="$2"
                shift 2
                ;;
            --base-image-url)
                BASE_IMAGE_URL="$2"
                shift 2
                ;;
            --base-image-path)
                BASE_IMAGE_PATH="$2"
                shift 2
                ;;
            --snap)
                if [ -z "$SNAPS" ]; then
                    SNAPS="$2"
                else
                    SNAPS="$SNAPS $2"
                fi
                shift 2
                ;;
            *)
                MODEL_ASSERTION="$1"
                shift
                ;;
        esac
    done

    if [ -z "$BASE_DIR" ]; then
        echo "mkimage-uc22: base dir cannot be empty" >&2
        return 1
    fi

    if [ "$BASE_DIR" = "/" ]; then
        echo "mkimage-uc22: base dir cannot be /" >&2
        return 1
    fi

    if [ -z "$MODEL_ASSERTION" ]; then
        echo "mkimage-uc22: model assert not provided" >&2
        show_help
        return 1
    fi
    if [ ! -f "$MODEL_ASSERTION" ] ; then
        echo "mkimage-uc22: $MODEL_ASSERTION not found, please sign an assertion using classic-model.json as model" >&2
        return 1
    fi

    if [ -n "$SNAPS" ]; then
        echo "mkimage-uc22: snaps provided: $SNAPS"
        echo "mkimage-uc22: remember that the names need to be SNAPNAME_*.snap"
    fi

    if [ -n "$BASE_IMAGE_PATH" ] && [ ! -f "$BASE_IMAGE_PATH" ]; then
        echo "mkimage-uc22: Base image file not found: $BASE_IMAGE_PATH" >&2
        return 1
    fi

    if [ -z "$BASE_IMAGE_PATH" ] && [ -z "$BASE_IMAGE_URL" ]; then
        echo "mkimage-uc22: either base image path or url needs to be provided" >&2
        return 1
    fi

    BOOT_IMG="$BASE_DIR/$BOOT_IMG"
    CACHE_DIR="$BASE_DIR/$CACHE_DIR"
    MNT_DIR="$BASE_DIR/$MNT_DIR"

    rm -rf "$BOOT_IMG" "$CACHE_DIR" "$MNT_DIR"
    # shellcheck disable=SC2064
    trap "cleanup \"$BOOT_IMG\" \"$MNT_DIR\"" EXIT INT

    get_assets "$CACHE_DIR" "$BASE_IMAGE_URL" "$BASE_IMAGE_PATH" "$SNAPS"
    create_image "$BOOT_IMG"
    populate_image "$BOOT_IMG" "$CACHE_DIR" "$MNT_DIR" "$MODEL_ASSERTION"
    replace_images_files "$BOOT_IMG" "$CACHE_DIR" "$MNT_DIR" "$SNAPD_DEB" "$SNAPD_BINPATH"

    show_how_to_run_qemu "$BOOT_IMG"
    # TODO: show how to mount/chroot into the dir to test seeding
}

main "$@"
