#!/bin/bash

ARCH=`uname -m`

show_help() {
cat << EOF
Usage: $0 [-h] [-y] [-s] [-d] [-8s]
	-h - help
	-y - "yes" (do not ask)
	-s - skip update/clean of current OS
	-d - download only
	-c - post upgrade cleanup
	-8s - switch CentOS 8 to CentOS 8 Stream
	-2r - upgrade 2 releases of Fedora
	--centos8stream - upgrade centos 7 to centos 8 stream
	--centos8 - upgrade centos7 to centos 8 (default for C7)
	--almalinux8 - upgrade to almalinux 8 using deploy script from github
	--altarch - use x86_64_v2 architecture for AlmaLinux 10
EOF
}

hecho() {
  echo ""
  echo "$@"
  echo ""
}

read_enter() {
  if [ ! "$ARG_Y" = "-y" ]; then
    echo "Press ENTER to upgrade or CTRL+C to stop."
    read enter
  fi
}

fix_selinux() {
  if [ "`getenforcing 2>&1`" = "Enforcing" ]; then
    fixfiles onboot
  fi
}

cleanup_gpg_pubkeys() {
  CENTOS_RELEASE=`rpm -E %rhel`
  echo "Cleaning old gpg pubkeys for CentOS/AlmaLinux $CENTOS_RELEASE"
  if [ "$CENTOS_RELEASE" -ge 7 ]; then
    # gpg-pubkey-c105b9de-4e0fd3a3 gpg(CentOS-6 Key (CentOS 6 Official Signing Key) <centos-6-key@centos.org>)
    # gpg-pubkey-0608b895-4bd22942 gpg(EPEL (6) <epel@fedoraproject.org>)
    rpm -e gpg-pubkey-c105b9de-4e0fd3a3 gpg-pubkey-0608b895-4bd22942
  fi
  if [ "$CENTOS_RELEASE" -ge 8 ]; then
    # gpg-pubkey-f4a80eb5-53a7ff4b gpg(CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>)
    # gpg-pubkey-352c64e5-52ae6884 gpg(Fedora EPEL (7) <epel@fedoraproject.org>)
    rpm -e gpg-pubkey-f4a80eb5-53a7ff4b gpg-pubkey-352c64e5-52ae6884
  fi
  if [ "$CENTOS_RELEASE" -ge 9 ]; then
    # gpg-pubkey-2f86d6a1-5cf7cefb gpg(Fedora EPEL (8) <epel@fedoraproject.org>)
    # gpg-pubkey-61e8806c-5581df56 gpg(CentOS Virtualization SIG (http://wiki.centos.org/SpecialInterestGroup/Virtualization) <security@centos.org>)
    # ! gpg-pubkey-3abb34f8-5ffd890e gpg(AlmaLinux <packager@almalinux.org>)
    rpm -e gpg-pubkey-2f86d6a1-5cf7cefb gpg-pubkey-61e8806c-5581df56
    rpm -e gpg-pubkey-3abb34f8-5ffd890e # SHA1 key
  fi
  if [ "$CENTOS_RELEASE" -ge 10 ]; then
    rpm -e gpg-pubkey-b86b3716-61e69f29 gpg-pubkey-3228467c-613798eb
    rpm -e gpg-pubkey-6b822fe7-45927ea8 # old sagator/salstar.sk key
  fi

  rpm -qa gpg-pubkey\* --qf '%{NAME}-%{VERSION}-%{RELEASE} %{SUMMARY}\n'
}

upgrade_centos6_to_centos7() {
  CENTOS_RELEASE=`rpm -E %rhel`
  CENTOS_NEXT=$((CENTOS_RELEASE+1))
  if [ "$CENTOS_RELEASE" = "6" ]; then
    yum install --enablerepo=upg -y \
      redhat-upgrade-tool preupgrade-assistant-contents openscap-1.0.8
    # fix dependency problems
    for i in pcre grep openldap vim-minimal nss nspr nss-util; do
      rpm -e --nodeps --justdb -v $i
    done
    #  elfutils-libelf elfutils-libs nss nspr nss-util
    # downgrade some packages for compatibility
    #yum downgrade -y \
    #  http://vault.centos.org/6.7/os/x86_64/Packages/elfutils-libelf-0.161-3.el6.x86_64.rpm \
    #  http://vault.centos.org/6.7/os/x86_64/Packages/elfutils-libs-0.161-3.el6.x86_64.rpm
    # import keys
    rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
    rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Security-6
    rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
    # run preupgrade
    UPG=`preupg -l`
    if [ "$ARG_Y" = "-y" ]; then
      upgrade_force="--force"
      upgrade_tool_reboot="--reboot"
    fi
    preupg -s $UPG $upgrade_force
    read_enter
    PUD=/root/preupgrade/postupgrade.d
    # upgrade other pkgs after base upgrade
    mkdir -p $PUD/salpack
    (
      echo "#!/bin/bash"
      echo ""
      echo "/usr/bin/salpack-os-upgrade -y"
    ) > $PUD/salpack/salpack.sh
    # fix broken library problems
    mkdir -p $PUD/0salpack
    (
      echo "#!/bin/bash"
      echo ""
      echo "cp -avf $PUD/0salpack/*.so /usr/lib64/"
      echo "/sbin/ldconfig -v"
      #echo "rpm -Uhv $PUD/0salpack/*.rpm --force"
    ) > $PUD/0salpack/salpack.sh
    for lib in libelf-0.163.so; do
      curl http://work.salstar.sk/public/c/$lib > $PUD/0salpack/$lib
    done
    #for rpm in elfutils-libelf-0.163-3.el7.x86_64.rpm; do
    #  curl http://ftp.upjs.sk/pub/centos/7/os/x86_64/Packages/$rpm > $PUD/0salpack/$rpm
    #done
    chmod +x $PUD/*salpack/*.sh
    # run regular update
    if [ -z "$CENTOS_REPO" ]; then
      CENTOS_REPO=http://ftp.upjs.sk/pub/centos/$CENTOS_NEXT/os/$ARCH/
    elif [ "$CENTOS_REPO" = "7.2" ]; then
      CENTOS_VER=7.2.1511
      CENTOS_REPO=http://vault.centos.org/$CENTOS_VER/os/$ARCH/
    fi
    set -x
    centos-upgrade-tool-cli --network $CENTOS_NEXT \
      --instrepo=$CENTOS_REPO \
      --enablerepo="salstar.sk" \
      --cleanup-post $upgrade_tool_reboot $upgrade_force
      #--addrepo="epel$CENTOS_NEXT=http://ftp.upjs.sk/pub/mirrors/epel/$CENTOS_NEXT/$ARCH/" \
      #--enablerepo="epel$CENTOS_NEXT" \
  else
    echo "Unknown CentOS version [$CENTOS_RELEASE]!"
    exit 2
  fi
}

upgrade_centos7_to_v8() {
  if [ ! "$ARG_S" ]; then
    yum update $ARG_Y
    yum install $ARG_Y dnf
    # redhat-upgrade-tool conflicts with kernel workaround swap
    dnf remove redhat-upgrade-tool dracut-network $ARG_Y
    # kernel is renamed in CentOS 8 and need to be removed, but it's protected
    #rpm -e kernel
    dnf swap grubby kernel-workaround $ARG_Y
    # sysvinit-tools is obsoleted by salpack
    # rpm -e sysvinit-tools --nodeps
    # Remove conflicts for yum files, they are replaced by dnf after upgrade
    rm -rf /etc/yum/vars /etc/yum/protected.d /etc/yum/pluginconf.d
  fi

  # Run the upgrade
  # redhat-rpm-config should be excluded due to:
  # (annobin if gcc) is required for redhat-rpm-config-116-1.el8.0.1.noarch
  # rpmpmlib(RichDependencies) <= 4.12.0-1 je vyžadovaný pre mariadb-connector-c-3.1.11-2.el8_3.x86_64
  dnf distro-sync $ARG_Y --allowerasing \
    --releasever=8 --setopt=module_platform_id=platform:el8 \
    --setopt=install_weak_deps=False \
    --disablerepo=\* "$@" \
    --exclude=redhat-rpm-config \
    --exclude=mariadb-connector-c \
    $ARG_OTHER
}

upgrade_centos7_to_centos8() {
  hecho "Upgrading to CentOS 8 (non-stream)!"
  upgrade_centos7_to_v8 --enablerepo=c8upg-\*
}

upgrade_centos7_to_centos8stream() {
  hecho "Upgrading to CentOS 8 Stream!"
  upgrade_centos7_to_v8 --enablerepo=c8supg-\* \
    --enablerepo=c8upg-epel --enablerepo=c8upg-salstar.sk
}

upgrade_centos7_to_almalinux8() {
  # This doesn't really work due to centos-release package conflicts.
  hecho "Upgrading to AlmaLinux 8!"
  # gpg subkeys are not supported on centos7
  #upgrade_centos7_to_v8 --enablerepo=a8upg-\* \
  #  --enablerepo=c8upg-epel --enablerepo=c8upg-salstar.sk \
  #  --nogpgcheck
  echo "Unable to update CentOS 7 to AlmaLinux 8 directly."
  echo "Please use: salpack-os-upgrade --centos8"
}

centos8_to_centos8stream() {
  hecho "Switching CentOS 8 to CentOS 8-Stream"
  echo "    https://www.centos.org/centos-stream/"
  dnf swap centos-linux-repos centos-stream-repos $ARG_Y \
    --disablerepo=appstream --disablerepo=baseos
  dnf distro-sync $ARG_Y --setopt=install_weak_deps=False
}

centos8_to_almalinux8() {
  hecho "Switching to AlmaLinux 8 using deploy script from github"
  cd
  curl -O https://raw.githubusercontent.com/AlmaLinux/almalinux-deploy/master/almalinux-deploy.sh
  read_enter
  # allow also downgrade from CentOS 8 Stream
  bash almalinux-deploy.sh --downgrade
}

chroot_install_check() {
  if [ "$ARG_S" ]; then
    return
  fi
  V=$1
  shift
  TMP=`mktemp -d /tmp/chroot-XXXXXXXX`
  rpm --dbpath $TMP/var/lib/rpm \
    --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-$V
  rpm --dbpath $TMP/var/lib/rpm \
    --import https://www.centos.org/keys/RPM-GPG-KEY-CentOS-Official
  dnf install -y --installroot=$TMP --releasever=$V bash \
    --disablerepo=\* --enablerepo=baseos "$@"
  chroot $TMP bash -c "echo CPU OK" || exit 100
  rm -rf $TMP
}

upgrade_v8_to_v9() {
  chroot_install_check 9 --enablerepo=c9upg-baseos
  dnf distro-sync $ARG_Y --allowerasing \
    --releasever=9 --setopt=module_platform_id=platform:el9 \
    --setopt=install_weak_deps=False \
    --disablerepo=epel\* --enablerepo=c9upg-epel --enablerepo=c9upg-crb \
    "$@" $ARG_OTHER || return
  systemctl restart rpmdb-rebuild.service
  # virt perl perl-IO-Socket-SSL perl-libwww-perl python36
  dnf module disable $ARG_Y \*
  # install rsyslog logrotate
  yum install -y rsyslog-logrotate
  systemctl enable logrotate.timer
  # clean old style gpg keys
  cleanup_gpg_pubkeys
}

upgrade_v9_to_v10() {
  chroot_install_check 10 $ARG_ARCH_V2
  dnf distro-sync $ARG_Y --allowerasing \
    --releasever=10 --setopt=module_platform_id=platform:el10 \
    --disablerepo=epel\* --enablerepo=epel10 \
    --setopt=install_weak_deps=False \
    "$@" $ARG_OTHER $ARG_ARCH_V2 || return
  # clean old style gpg keys
  cleanup_gpg_pubkeys
}

update_almalinux_altarch() {
  # add x86_64_v2 to supported architectures
  sed -i \
    "s/'x86_64', 'amd64', 'ia32e'/'x86_64', 'x86_64_v2', 'amd64', 'ia32e'/" \
    /usr/lib/python3.9/site-packages/dnf/rpm/__init__.py
}

almalinux8_to_almalinux9() {
  hecho "Upgrading to AlmaLinux 9!"
  rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-9
  rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
  upgrade_v8_to_v9
}

almalinux9_to_almalinux10() {
  hecho "Upgrading to AlmaLinux 10!"
  rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-10
  rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-10
  if [ "$ARG_ALTARCH" ]; then
    update_almalinux_altarch
    rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-10-EPEL-AltArch
    ARG_ARCH_V2="--forcearch=x86_64_v2 --disablerepo=appstream --disablerepo=baseos --disablerepo=crb --disablerepo=extras --disablerepo=plus --enablerepo=*_x86_64_v2"
  fi
  upgrade_v9_to_v10
}

centos8stream_to_centos9stream() {
  hecho "Upgrading to CentOS 9 Stream!"
  rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
  yum remove trousers trousers-lib python3-syspurpose $ARG_Y
  MIRROR=http://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/Packages
  dnf install \
    $MIRROR/centos-stream-repos-9.0-23.el9.noarch.rpm \
    $MIRROR/centos-stream-release-9.0-23.el9.noarch.rpm \
    $MIRROR/centos-gpg-keys-9.0-23.el9.noarch.rpm
  dnf upgrade \
    https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm \
    https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm
  #rpm -e --nodeps iptables-services
  upgrade_v8_to_v9 --enablerepo=c9upg-baseos --disablerepo=baseos
}

cleanup_yum() {
  if [ -d /var/cache/yum ]; then
    if rpm -qf /var/cache/yum; then
      echo "OK"
    else
      rm -rfv /var/cache/yum
    fi
  fi
}

post_upgrade_cleanup() {
  # remove obsolete packages
  hecho "Running package cleanup only ..."
  dnf update -y --setopt=install_weak_deps=False
  dnf remove "$@" `dnf repoquery --extras` $ARG_OTHER
  # remove el7 kernel boot entries
  #rm -i /boot/loader/entries/*.el7.*.conf
  cleanup_gpg_pubkeys
  cleanup_yum
}

dnf_upgrade() {
  echo "Running upgrade ..."
  rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$FEDORA_NEXT-$ARCH
  if [ ! "$ARG_S" ]; then
    echo "Upgrading and cleaning current system ..."
    dnf upgrade $ARG_Y --setopt=install_weak_deps=False
    dnf clean all
  fi
  hecho "Upgrading to version $FEDORA_NEXT ..."
  echo "dnf --releasever=$FEDORA_NEXT --setopt=deltarpm=false --setopt=install_weak_deps=False distro-sync $ARG_Y $ARG_D $ARG_OTHER"
  dnf --releasever=$FEDORA_NEXT --setopt=deltarpm=false \
    --setopt=install_weak_deps=False \
    distro-sync $ARG_Y $ARG_D $ARG_OTHER
  if [ $? = 0 ]; then
    echo "Extra packages after install:"
    dnf list extras
  fi
}

upgrade_fedora() {
  FEDORA_MIRROR=http://ftp.upjs.sk/pub/fedora/linux
  FEDORA_RELEASE=`rpm -E %fedora`
  FEDORA_NEXT=$((FEDORA_RELEASE+1))
  FEDORA_NEXT2=$((FEDORA_RELEASE+2))
  if [ "$ARG_RELEASE_PLUS2" ]; then
    FEDORA_NEXT=$FEDORA_NEXT2
  elif wget -O /dev/null -q $FEDORA_MIRROR/releases/$FEDORA_NEXT2/; then
    echo "Currently running Fedora $FEDORA_RELEASE."
    echo "Fedora $FEDORA_NEXT2 is already available, do you want to update"
    echo "to Fedora $FEDORA_NEXT2? Type \"y\" or \"yes\" to confirm."
    if [ "$ARG_Y" = "-y" ]; then
      yn="yes"
    else
      read yn
    fi
    echo "Answer: $yn"
    if [ "$yn" = "yes" -o "$yn" = "y" ]; then
      FEDORA_NEXT=$FEDORA_NEXT2
    fi
  fi
  if [ "$FEDORA_RELEASE" -ge "22" ]; then
    dnf_upgrade
  else
    echo "Unsupported Fedora release [$FEDORA_RELEASE]!"
    exit 2
  fi
}

ARG_Y=""
ARG_S=""
ARG_D=""
ARG_C=""
ARG_TARGET=""
ARG_RELEASE_PLUS2=""
ARG_ALTARCH=""
for arg in "$@"; do
  case $arg in
    -h|--help)
	show_help
	exit
	;;
    -y|--yes)
	ARG_Y=-y
	;;
    -s|--skip|--short)
	ARG_S=yes
	;;
    -d|--downloadonly)
	ARG_D=--downloadonly
	;;
    -c|--cleanup)
	ARG_C=yes
	;;
    -2r)
        ARG_RELEASE_PLUS2=yes
        ;;
    -8s|--8-stream|--centos8stream|8s|8-stream)
	ARG_TARGET=centos8stream
	;;
    --almalinux8|--almalinux|--alma8|--alma)
        ARG_TARGET=almalinux8
        ;;
    --centos8)
        ARG_TARGET=centos8
        ;;
    --altarch)
        ARG_ALTARCH=x86_64_v2
        ;;
    *)
	ARG_OTHER="$ARG_OTHER $arg"
	;;
  esac
done

echo "This is an upgrade script for AlmaLinux/CentOS/Fedora."
echo "WARNING: Use with caution!"

read_enter

if [ "$ARG_C" = "yes" ]; then
  post_upgrade_cleanup
  exit
fi

if [ -f /etc/almalinux-release ]; then
  if grep '^AlmaLinux release 8' /etc/redhat-release; then
    almalinux8_to_almalinux9
  elif grep '^AlmaLinux release 9' /etc/redhat-release; then
    almalinux9_to_almalinux10
  elif grep '^AlmaLinux release 10' /etc/redhat-release; then
    post_upgrade_cleanup "$@"
  else
    echo "ERROR: Unknown release of AlmaLinux!"
    cat /etc/almalinux-release
  fi
elif [ -f /etc/centos-release ]; then
  if grep '^CentOS release 6' /etc/centos-release; then
    upgrade_centos6_to_centos7
  elif grep '^CentOS Linux release 7' /etc/centos-release; then
    if [ "$ARG_TARGET" = "centos8stream" ]; then
      upgrade_centos7_to_centos8stream
    elif [ "$ARG_TARGET" = "almalinux8" ]; then
      upgrade_centos7_to_almalinux8
    else
      upgrade_centos7_to_centos8
    fi
  elif grep '^CentOS \(Linux\|Stream\) release 8' /etc/centos-release; then
    if [ "$ARG_TARGET" = "centos8stream" ]; then
      centos8_to_centos8stream "$@"
    elif [ "$ARG_TARGET" = "almalinux8" ]; then
      centos8_to_almalinux8
    else
      centos8_to_almalinux8
    fi
  fi
elif [ -f /etc/fedora-release ]; then
  if [ -z "$STY" -a -z "$TMUX" ]; then
    echo "Please run this script under screen or tmux."
    #exit 1
  fi
  upgrade_fedora
fi
