#!/bin/bash
## kola:
##   # Increase timeout since this test has a lot of I/O and involves rebasing
##   timeoutMin: 20
##   # We've seen some OOM when 1024M is used:
##   # https://github.com/coreos/fedora-coreos-tracker/issues/1506
##   minMemory: 2048
##   # Needs internet access as we fetch files from koji
##   # We add the "reprovision" tag here even though we aren't
##   # reprovisioning as a hack so that in our pipeline the test
##   # will execute with no other tests. We were seeing a lot of
##   # timeouts on ppc64le.
##   tags: "needs-internet platform-independent reprovision"
##   description: Verify that build of a container image with a new kernel
##     and reboot into it succeeds.

#
# Copyright (C) 2023 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

set -euxo pipefail

# shellcheck disable=SC1091
. "$KOLA_EXT_DATA/commonlib.sh"

cd $(mktemp -d)

# TODO: It'd be much better to test this via a registry

# define OS ID in order to assign appropriate kernel later
OS_ID=$(. /etc/os-release; echo $ID)
image_dir=/var/tmp/coreos
image=oci:${image_dir}
image_pull=ostree-unverified-image:$image
tmp_imagedir=${image_dir}-tmp
arch=$(arch)

# we only want to query repos once but need the info on multiple boots, so write out state to /var
if [ ! -f /var/kola-kernel.evr ]; then
  case "$OS_ID" in
    rhcos|scos|rhel|centos)
      c9s_mirror="https://mirror.stream.centos.org/9-stream/BaseOS/${arch}/os"
      dnf_opts="--repofrompath=tmp,${c9s_mirror} --disablerepo=* --enablerepo tmp"
      # we're probably already on CentOS and running the latest kernel. so
      # here we need to instead pick whatever the latest that's *not* the same
      kver=$(dnf repoquery $dnf_opts kernel --qf '%{EVR}' | \
                grep -v "$(rpm -q kernel --qf '%{EVR}')" | tail -n1)
      # Download kernel RPMs locally; direct HTTP URLs to
      # mirror.stream.centos.org fail with HTTP 403 due to GeoIP-based
      # DNS routing. dnf download handles mirror failover automatically.
      mkdir -p /var/kola-kernel-rpms
      pushd /var/kola-kernel-rpms
      dnf download $dnf_opts --resolve kernel-{,core-,modules-,modules-core-,modules-extra-}$kver
      popd
      kver="${kver}.${arch}"
      ;;
    fedora)
      # to get the version to use: koji latest-pkg f40 kernel
      # XXX: once we can rely on dnf in FCOS, use repoquery also here
      kver="6.8.5-301.fc40.${arch}"
      url="https://kojipkgs.fedoraproject.org//packages/kernel/6.8.5/301.fc40/${arch}/kernel"
      ;;
    *)
      echo "Unknown OS_ID: ${OS_ID}"
      exit 1
      ;;
  esac
  echo "$kver" > /var/kola-kernel.evr
else
  kver=$(cat /var/kola-kernel.evr)
fi

case "${AUTOPKGTEST_REBOOT_MARK:-}" in
  "")
    # Take the existing ostree commit, and export it to a container image, then rebase to it.
    rpm-ostree status --json > status.json
    checksum=$(jq -r '.deployments[0].checksum' < status.json)
    v0=$(jq -r '.deployments[0].version' < status.json)
    imgref=$(jq -r '.deployments[0]["container-image-reference"]' < status.json)
    rm ${image_dir} -rf
    encapsulate_args=()
    # A hack...if we're booted into a container, then we need to fake things out
    # for the merge commit to turn it back into an image.  What we *really* want
    # here obviously is seamless support for re-serializing a container from
    # the ostree storage, but right now we're not doing the tar-split stuff.
    if [[ "$imgref" != null ]]; then
      encapsulate_args+=("--label" "ostree.bootable=true")
    fi
    # Since we're switching OS update stream, turn off zincati
    systemctl mask --now zincati
    ostree container encapsulate "${encapsulate_args[@]}" --repo=/ostree/repo ${checksum} "${image}"
    # This one keeps --experimental, but we also test without it below
    rpm-ostree rebase --experimental "$image_pull"
    ostree container image list --repo=/ostree/repo | tee imglist.txt
    # Test rebasing back to ostree https://github.com/coreos/rpm-ostree/issues/3677
    rpm-ostree rebase "$checksum"
    rpm-ostree rebase "$image_pull"
    /tmp/autopkgtest-reboot 1
    ;;
  1)
    # Setup
    # copy the OCI dir to containers-storage for a local build
    skopeo copy $image containers-storage:localhost/coreos
    rm "${image_dir}" -rf
    td=$(mktemp -d)
    cd ${td}
    version=$(rpm-ostree --version | grep Version)
    cat > Containerfile << EOF
FROM localhost/coreos
RUN rpm-ostree override replace /tmp/buildcontext/*rpm && \
    rpm-ostree cleanup -m && \
    ostree container commit
EOF
    # Older podman found in RHEL8 blows up without /etc/resolv.conf
    # which happens in our qemu path.
    touched_resolv_conf=0
    if test '!' -f /etc/resolv.conf; then
      podmanv=$(podman --version)
      case "${podmanv#podman version }" in
        3.*) touched_resolv_conf=1; touch /etc/resolv.conf;;
      esac
    fi
    podman build --net=host --volume /var/kola-kernel-rpms:/tmp/buildcontext:z -t localhost/coreos-derived --squash .
    if test "${touched_resolv_conf}" -eq 1; then
      rm -vf /etc/resolv.conf
    fi
    derived=oci:$image_dir:derived
    skopeo copy containers-storage:localhost/coreos-derived $derived
    rpm-ostree --version
    rpm-ostree rebase ostree-unverified-image:$derived
    ostree container image list --repo=/ostree/repo
    rm $image_dir -rf
    /tmp/autopkgtest-reboot 2
    ;;
  2)
    un=$(uname -r)
    if test "$un" != "$kver"; then
      echo "Expected kernel $kver but found $un"
      exit 1
    else
      echo "Kernel switch to $un was successful"
    fi
    test -f /usr/lib/modules/$kver/initramfs.img
    test -f /usr/lib/modules/$kver/vmlinuz
    ;;
  *)
    echo "Unknown AUTOPKGTEST_REBOOT_MARK: ${AUTOPKGTEST_REBOOT_MARK:-}"
    exit 1
    ;;
esac
