#!/bin/bash -ex
#
# This setup script is an unofficial solution designed to deploy QM in
# non-automotive environments like baremetal, desktop, or CICD.
#
# It will install an OS environment by default into
# /usr/lib/qm/rootfs and create a Podman quadlet containerized environment
# running systemd as PID1 inside.
#

# Globals
SYSTEMCTL_SKIP="N"
REMOVE_QM_ROOTFS="N"
INSTALLDIR="/usr/share/qm"
QM_ROOTFS_TOOL="${INSTALLDIR}/qm-rootfs"
ROOTFS="/usr/lib/qm/rootfs"
RWETCFS="/etc/qm"
RWVARFS="/var/qm"
AGENT_HOSTNAME="$(hostname)"
AGENTCONF="/etc/bluechi/agent.conf.d/agent.conf"
QM_CONTAINER_IDS=1000000000:1500000000
CONTAINER_IDS=2500000000:1500000000
PACKAGES_TO_INSTALL="selinux-policy-targeted podman systemd bluechi-agent procps-ng iptables-nft jq"

# RHEL kernel uses iptables-nft, not iptables-legacy, the tool should
# make sure this package is removed.
PACKAGES_TO_REMOVE="iptables-legacy"

CMDLINE_ARGUMENT_LIST=(
  "installdir"
  "rootfs"
  "hostname"
  "rwetcfs"
  "rwvarfs"
  "skip-systemctl"
)

root_check() {
    if [ "$(id -u)" -ne 0 ];then
	echo "Please run this script as root"
	exit 1
    fi
}

usage()
{
   echo "This script is an unofficial solution designed to deploy QM in"
   echo "non-automotive environments like baremetal, desktop, or CICD."
   echo
   echo "The setup script will install an OS environment by default into"
   echo "/usr/lib/qm/rootfs and create a Podman quadlet containerized environment"
   echo "running systemd as PID1 inside."
   echo
   echo "Usage: setup [OPTIONS]"
   echo
   echo "OPTIONS:"
   echo
   echo "--help                Print this message."
   echo "--installdir          qm install directory (default: /usr/share/qm)"
   echo "--rootfs              set rootfs (default: /usr/lib/qm/rootfs)"
   echo "--rwetcfs             set rwetcfs (default: /etc/qm)"
   echo "--rwvarfs             set rwvarfs (default: /var/qm)"
   echo "--skip-systemctl      skip systemctl daemon commands (default: false)"
   echo "--hostname            custom agent hostname to use (default: \$\(hostname\))"
   echo "--remove-qm-rootfs    WARNING: remove qm rootfs created during setup"
   echo
   echo "Example:"
   echo "  $ sudo ./setup --installdir=/usr/share/qm --rootfs=/usr/lib/qm/rootfs"
}

replaceIDs() {
    touch "$1"
    grep -q "^$2:" "$1" || echo "$2":"$3" >> "$1"
}

bluechiSetup() {
    ROOTFS=$1
    RWETCFS=$2
    RWVARFS=$3
    setupRW "${ROOTFS}" "${RWETCFS}" "${RWVARFS}"
    if test ! -f "${ROOTFS}${AGENTCONF}"; then
	if test -f "${AGENTCONF}"; then
	    sed -e 's,^NodeName=,NodeName=qm.,g' "${AGENTCONF}" >  "${ROOTFS}${AGENTCONF}"
	fi
    fi
    hostname=$AGENT_HOSTNAME
    if test -f "${ROOTFS}${AGENTCONF}"; then
	sed -e "s,^NodeName=qm.$,NodeName=qm.${hostname},g" \
	    -e "s,^NodeName=$,NodeName=qm.${hostname},g" \
	    -i "${ROOTFS}${AGENTCONF}"
    else
	cat > "${ROOTFS}${AGENTCONF}" <<EOF
[bluechi-agent]
NodeName=qm.${hostname}
EOF
    fi
}

setupRW() {
    ROOTFS=$1
    RWETCFS=$2
    RWVARFS=$3
    mkdir -Z -p "${ROOTFS}/etc" "${ROOTFS}/var"
    mkdir -Z -p "${RWETCFS}" "${RWVARFS}"
    mount --bind "${RWETCFS}" "${ROOTFS}/etc"
    mount --bind "${RWVARFS}" "${ROOTFS}/var"
}

create_rootfs_required_dirs() {
    # List of directories required for rootfs
    directories=(
	    "${ROOTFS}/etc/containers/"
	    "${ROOTFS}/usr/share/containers/selinux/"
	    "${ROOTFS}/etc/selinux/targeted/contexts/files/"
    )

    for dir in "${directories[@]}"; do
        if [ ! -d "$dir" ]; then
            mkdir -Z -p "$dir"
            echo "Created directory: $dir"
        fi
    done

}

validate_qm_installation() {
    files=(
        "${INSTALLDIR}/containers.conf"
        "${INSTALLDIR}/contexts"
        "${INSTALLDIR}/file_contexts"
    )

    for file in "${files[@]}"; do
        if [[ ! -f "$file" ]]; then
            echo "Exiting... '$file' not found. Try reinstall the QM package before continue." >&2
            exit 1
        fi
    done
}

install() {
    ROOTFS=$1
    RWETCFS=$2
    RWVARFS=$3
    # shellcheck source=/dev/null
    . /etc/os-release
    setupRW "${ROOTFS}" "${RWETCFS}" "${RWVARFS}"

    EXTRA_FLAG=""
    if grep -qi "^ID=fedora" /etc/os-release; then
        EXTRA_FLAG="--use-host-config"
    fi

    # SecurityLabelNested not supported so far in CentOS Stream 9 or lower
    if grep -qi "^ID=centos" /etc/os-release && [[ $(grep -oP '^VERSION_ID="\K[0-9]+' /etc/os-release) -le 9 ]]; then
        sed -i '/SecurityLabelNested/d' /usr/share/containers/systemd/qm.container
    fi

    cmd_dnf_install="dnf -y install --releasever=${VERSION_ID} --installroot ${ROOTFS} ${PACKAGES_TO_INSTALL} ${EXTRA_FLAG}"
    echo "$cmd_dnf_install"
    ${cmd_dnf_install}

    if dnf --installroot "${ROOTFS}" list installed "${PACKAGES_TO_REMOVE}" > /dev/null 2>&1; then
        dnf --installroot "${ROOTFS}" remove "${PACKAGES_TO_REMOVE}" -y
    fi

    # check if "${ROOTFS}"/etc/yum.repos.d
    if [ -z "$(find "${ROOTFS}"/etc/yum.repos.d -mindepth 1 -maxdepth 1)" ]; then
       cat > "${ROOTFS}/etc/yum.repos.d/autosd.repo" << EOF
[autosd]
name=Automotive-Sig \$releasever
baseurl=https://autosd.sig.centos.org/AutoSD-9/nightly/repos/AutoSD/compose/AutoSD/\$basearch/os
enabled=1
gpgcheck=0
EOF
    fi

    dnf -y update --installroot "${ROOTFS}"
    rm -rf "${ROOTFS}"/etc/selinux/targeted/contexts/files/file_contexts/*

    create_rootfs_required_dirs
    validate_qm_installation

    cp "${INSTALLDIR}/containers.conf" "${ROOTFS}/etc/containers/"
    cp "${INSTALLDIR}/contexts" "${ROOTFS}/usr/share/containers/selinux/"
    cp "${INSTALLDIR}/file_contexts" "${ROOTFS}/etc/selinux/targeted/contexts/files/file_contexts"
    replaceIDs "${ROOTFS}/etc/subuid" containers ${QM_CONTAINER_IDS}
    replaceIDs "${ROOTFS}/etc/subgid" containers ${QM_CONTAINER_IDS}
    bluechiSetup "${ROOTFS}" "${RWETCFS}" "${RWVARFS}"

    if [ "$SYSTEMCTL_SKIP" == "N" ]; then
	unshare --mount-proc -R "${ROOTFS}" -m systemctl enable bluechi-agent.service
    else
	chroot "${ROOTFS}" ln -fs \
	    /usr/lib/systemd/system/bluechi-agent.service \
	    /etc/systemd/system/multi-user.target.wants/bluechi-agent.service
    fi

    "${INSTALLDIR}/qm-storage-settings"
    restorecon -R "${ROOTFS}"
    umount "${ROOTFS}/var" "${ROOTFS}/etc"
}

# read command line arguments
opts=$(getopt \
  --longoptions "$(printf "help,skip-systemctl,remove-qm-rootfs,%s:," "${CMDLINE_ARGUMENT_LIST[@]}")" \
  --name "$(basename "$0")" \
  --options "" \
  -- "$@"
)

eval set --"${opts}"

# main()
root_check

while [[ $# -gt 0 ]]; do
  case "$1" in
    --installdir)
      INSTALLDIR="${2}"
      shift 2
      ;;
    --rootfs)
      ROOTFS="${2}"
      shift 2
      ;;
    --rwetcfs)
      RWETCFS="${2}"
      shift 2
      ;;
    --rwvarfs)
      RWVARFS="${2}"
      shift 2
      ;;
    --skip-systemctl)
      SYSTEMCTL_SKIP="Y"
      shift
      ;;
    --hostname)
      AGENT_HOSTNAME="${2}"
      shift 2
      ;;
    --remove-qm-rootfs)
      REMOVE_QM_ROOTFS="Y"
      shift 2
      ;;
    --help)
      usage
      exit 1
      ;;
    *)
      break
      ;;
  esac
done

# Figure out the options, execute setup
echo "setup has started..."
echo  "  * rootfs: ${ROOTFS}"
echo  "  * rwetcfs: ${RWETCFS}"
echo  "  * rwvarfs: ${RWVARFS}"
echo  "  * install dir: ${INSTALLDIR}"
echo  "  * skip-systemctl: ${SYSTEMCTL_SKIP}"
echo  "  * remove-qm-rootfs: ${REMOVE_QM_ROOTFS}"
echo  "  * agent hostname: ${AGENT_HOSTNAME}"
echo

if [ "${REMOVE_QM_ROOTFS}" == "Y" ]; then
    # Unmount qm binds
    qm_mounts="$(mount | grep /qm  | cut -d" " -f3)"
    if [ -z "$qm_mounts" ]; then
        echo "No mount points found under /qm."
    else
        for mount in $qm_mounts; do
            umount "$mount"
        done
    fi
    # Get the one path below, i.e: /usr/lib/qm instead /usr/lib/qm/rootfs
    path_qm_rootfs=$(${QM_ROOTFS_TOOL} | sed 's|/[^/]*$||')
    rm -rf "${path_qm_rootfs}"
    exit 0
fi


case "$1" in
    bluechi-agent)
	rm -f "${ROOTFS}${AGENTCONF}"
	bluechiSetup "${ROOTFS}" "${RWETCFS}" "${RWVARFS}"
	;;
    *)

    if [ "$SYSTEMCTL_SKIP" == "N" ]; then
	    if systemctl is-active --quiet "qm.service" ; then
		systemctl stop qm.service
	    fi
    fi

	install "${ROOTFS}" "${RWETCFS}" "${RWVARFS}"
	replaceIDs /etc/subuid qmcontainers ${QM_CONTAINER_IDS}
	replaceIDs /etc/subgid qmcontainers ${QM_CONTAINER_IDS}
	replaceIDs /etc/subuid containers   ${CONTAINER_IDS}
	replaceIDs /etc/subgid containers   ${CONTAINER_IDS}

    if [ "$SYSTEMCTL_SKIP" == "N" ]; then
	    systemctl daemon-reload
	    systemctl start qm.service
            if [ "$(systemctl is-active qm.service)" != "active" ]; then
               journal=$(journalctl --no-pager -xu qm.service)
               echo QM service is not up details:
               echo "$journal"
               exit 1
            fi
    else
      /usr/libexec/podman/quadlet /run/systemd/generator/
    fi
	;;
esac
