#!/bin/bash
# shellcheck disable=SC1091 # Runtime-resolved path; intentionally not followed.
. "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../local-snap.sh" || return 1
set -eu

if [[ "${LXD_SNAP_CHANNEL}" =~ ^4\.0/ ]]; then
  echo "Skipping test on 4.0 branch"
  # shellcheck disable=SC2034
  FAIL=0
  exit 0
fi

# Install LXD
install_lxd

# Configure LXD
lxd init --auto --storage-backend zfs --storage-create-loop 24

# Test
set -x

# XXX: only testing 24.04 onward because prior versions either had LXD snap
# pre-seeded or had an lxd-installer always installing from the default channel.
RELEASES="${RELEASES:-"24.04 26.04"}"

test_lxd_installer() {
    local instance="${1}"
    local release="${2}"

    echo "==> ${instance} (${release})"

    # prepare to install snaps
    lxc exec "${instance}" -- sh -c "$(declare -f waitSnapdSeed); waitSnapdSeed"

    # report on lxd-installer version
    lxc exec "${instance}" -- dpkg -l | grep -wF lxd-installer

    # list snaps (should be empty)
    lxc exec "${instance}" -- snap list
    ! lxc exec "${instance}" -- snap list lxd 2>/dev/null || false

    # trigger lxd-installer (without prompting)
    lxc exec "${instance}" -- lxc list < /dev/null

    # list snaps (should not be empty)
    lxc exec "${instance}" -- snap list
    [ "$(lxc exec "${instance}" -- snap list lxd)" != "" ]

    # check the LXD version matches what we expect
    LXD_VERSION="$(lxc exec "${instance}" -- lxd --version)"
    LXD_EXPECTED_VERSION="5.21"
    [ "${release}" = "26.04" ] && LXD_EXPECTED_VERSION="6"
    [[ "${LXD_VERSION}" =~ ^${LXD_EXPECTED_VERSION}\..* ]]

    # check the LXD channel matches what we expect
    SNAP_CHANNEL="$(lxc exec "${instance}" -- snap info lxd | awk '/^tracking:/ {print $2}')"
    [ "${SNAP_CHANNEL}" = "${LXD_EXPECTED_VERSION}/stable/ubuntu-${release}" ]
}

test_lxd() {
    local instance="${1}"
    local release="${2}"

    echo "==> ${instance} (${release})"

    # new Ubuntu releases have split out the ZFS kernel module into a separate
    # package, so check if modinfo can find it and if not install the package
    # that provides it and ensure it is usable by LXD (reload or reboot if needed).
    if ! lxc exec "${instance}" -- modinfo -F version zfs; then
      lxc exec "${instance}" -- apt-get update
      lxc exec "${instance}" -- apt-get install --no-install-recommends -y linux-modules-zfs-generic

      # Check if we were lucky and got a ZFS module directly usable with the running kernel.
      if lxc exec "${instance}" -- modinfo -F version zfs; then
        # If ZFS was installed after the LXD daemon was started, it needs to be reloaded to pick up the PATH to the right tools.
        if lxc exec "${instance}" -- systemctl is-active --quiet snap.lxd.daemon.service; then
          echo "==> Reloading LXD snap to pick up newly installed ZFS modules"
          lxc exec "${instance}" -- systemctl reload snap.lxd.daemon.service
        fi
      else  # If not, we need to reboot the instance to get a newer kernel with ZFS support.
        lxc restart "${instance}"
        waitInstanceBooted "${instance}"
        lxc exec "${instance}" -- modinfo -F version zfs
      fi
    fi

    # check that ZFS is functional
    lxc exec "${instance}" -- lxd init --auto --storage-backend "zfs"
    lxc exec "${instance}" -- lxc storage show default | grep -xF 'driver: zfs'
    lxc exec "${instance}" -- cat /sys/module/zfs/version

    # use -minimal for a lighter nested instance
    lxc exec "${instance}" -- lxc launch "ubuntu-minimal-daily:${release}" n1
    lxc exec "${instance}" -- lxc delete -f n1

    # XXX: workaround for https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2141703
    lxc exec "${instance}" -- modprobe vxlan

    # test the creation of a FAN bridge
    lxc exec "${instance}" -- lxc network create lxdfan0 bridge.mode=fan
}

# Silence GH warnings in isSystemdClean
export WARNING_PREFIX="false"
for remote in ubuntu-minimal-daily ubuntu-daily; do
    for release in $RELEASES; do
        IMAGE="${remote}:${release}"

        echo "==> VM (${IMAGE})"
        lxc launch "${IMAGE}" v1 --vm -c security.devlxd.images=true
        isSystemdClean v1  # for VM: require systemd --fail to be empty
        setup_instance_gocoverage v1
        test_lxd_installer v1 "${release}"
        test_lxd v1 "${release}"
        prepare_vm_for_hard_stop v1
        lxc delete -f v1
    done
done
unset WARNING_PREFIX

# shellcheck disable=SC2034
FAIL=0
