#!/bin/bash # vim: sw=3:ts=3:et set -e RAWHIDE_VERSION=35 FEDORA_VERSION=$(rpm -qf --qf '%{version}' /etc/os-release) TARGET_VERSION=$((FEDORA_VERSION + 1)) UPGRADE_FINISHED=0 TMPFS_MOUNTED=0 DISABLED_PLUGINS="--disableplugin=needs-restarting --disableplugin=tracer" function check_installation() { [[ -e /usr/sbin/fedora-upgrade ]] } function pause() { # clear the stdin buffer and pause with question read -t 1 -n 10000 discard || [ $? -gt 128 ] read -p "Hit Enter to continue or Ctrl + C to cancel." } function continue_or_skip() { read -t 1 -n 10000 discard || [ $? -gt 128 ] echo -e $1 echo "This step is highly recommended but can be safely skipped." ANSWER='XXX' while [ "$ANSWER" != "" -a "$ANSWER" != "S" ] ; do read -p "Hit Enter to continue, Ctrl + C to cancel or S + Enter to skip. " ANSWER ANSWER=$(echo $ANSWER | tr "[:lower:]" "[:upper:]") done } function dnf_install_deps() { # TODO add -q to all dnf and create some kind of progress meter # but now be verbose install_if_missing rpmconf install_if_missing dnf-plugins-core } function install_if_missing() { echo "Checking if $1 is installed." rpm -q $1 >/dev/null || dnf install -y -q $1 } function upgrade_before_upgrade() { continue_or_skip "\nGoing to run 'dnf upgrade' before upgrading." if [ "$ANSWER" != "S" ] ; then dnf upgrade fi } function dnf_upgrade_before_upgrade() { continue_or_skip "\nGoing to run 'dnf upgrade' before upgrading." if [ "$ANSWER" != "S" ] ; then dnf upgrade fi } function rpmconf_before_upgrade() { continue_or_skip "\nGoing to resolve old .rpmsave and .rpmnew files before upgrading." if [ "$ANSWER" != "S" ] ; then rpmconf -fvimdiff -a fi } function import_keys() { echo "Importing new RPM-GPG keys." rpm --import /usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-$TARGET_VERSION-primary if [ -f /etc/yum.repos.d/rpmfusion-free.repo -a -e /usr/share/distribution-gpg-keys/rpmfusion/RPM-GPG-KEY-rpmfusion-free-fedora-$TARGET_VERSION ]; then rpm --import /usr/share/distribution-gpg-keys/rpmfusion/RPM-GPG-KEY-rpmfusion-free-fedora-$TARGET_VERSION fi if [ -f /etc/yum.repos.d/rpmfusion-nonfree.repo -a -e /usr/share/distribution-gpg-keys/rpmfusion/RPM-GPG-KEY-rpmfusion-nonfree-fedora-$TARGET_VERSION ]; then rpm --import /usr/share/distribution-gpg-keys/rpmfusion/RPM-GPG-KEY-rpmfusion-nonfree-fedora-$TARGET_VERSION fi } function install_base() { continue_or_skip "\nGoing to install missing packages from group 'Minimal Install'" if [ "$ANSWER" != "S" ] ; then dnf group install 'Minimal Install' fi } function dnf_install_base() { continue_or_skip "\nGoing to install missing packages from group 'Minimal Install'" if [ "$ANSWER" != "S" ] ; then dnf groupupdate 'Minimal Install' fi } function rpmconf_after_upgrade() { continue_or_skip "\nGoing to resolve .rpmsave and .rpmnew files after upgrade." if [ "$ANSWER" != "S" ] ; then rpmconf -fvimdiff -a rpmconf --clean fi } function remove_old_gpg_keys() { continue_or_skip "\nGoing to remove old GPG keys." # Fedora 30 rpm -e gpg-pubkey-c0aeda6e-5ad45327 2>/dev/null rpm -e gpg-pubkey-1d14a795-5ad4532e 2>/dev/null rpm -e gpg-pubkey-cfc659b9-5b6eac67 2>/dev/null # Fedora 31 rpm -e gpg-pubkey-c481937a-5bc4662d 2>/dev/null rpm -e gpg-pubkey-3c3359c4-5c6ae44d 2>/dev/null rpm -e gpg-pubkey-54a86092-5bc4663b 2>/dev/null } function reset_service_priorities() { continue_or_skip "\nGoing to resets all installed unit files to the defaults configured\nin the preset policy file." if [ "$ANSWER" != "S" ] ; then systemctl preset-all fi } function EXCEPTION_reset_libgit2_module() { continue_or_skip "\nGoing to reset libgit2, exa, bat Fedora Modules. (dnf module reset libgit2 exa bat)" if [ "$ANSWER" != "S" ] ; then dnf module reset libgit2 exa bat fi } function EXCEPTION_reset_modules() { continue_or_skip "\nGoing to reset Fedora Modules. (dnf module reset '*')" if [ "$ANSWER" != "S" ] ; then dnf module reset '*' fi } function cleanup_cache() { rm -rf /var/cache/yum/* /var/cache/dnf/* /var/cache/PackageKit/* } function unwanted_packages() { LAST=$1 continue_or_skip "\nThere may be some packages which are now orphaned, do you want to see them?" RESULT=0 package-cleanup --orphans | grep -v kernel && RESULT=1 if [ 0$RESULT -eq 1 ]; then echo "These packages are very probably orphaned. You may want to remove them." fi } function is_prerelease() { # will print string "--enablerepo=updates-testing" if this is prerelease, "" otherwise local RELEASE=$1 TEMP=$(mktemp -d) dnf download -q --destdir "$TEMP" --disablerepo=* --enablerepo=fedora --releasever=$RELEASE fedora-repos if rpm2cpio "$TEMP"/fedora-repos*.rpm | cpio -i --quiet --to-stdout - ./etc/yum.repos.d/fedora-updates-testing.repo | grep 'enabled=1' >/dev/null ; then if [ -e /etc/yum.repos.d/fedora-updates-modular.repo ]; then echo "--enablerepo=updates-testing --enablerepo=updates-testing-modular" else echo "--enablerepo=updates-testing" fi else echo "" fi rm -rf "$TEMP" } function warn_if_graphics_mode() { if [[ ! "$TERM" =~ "screen".* ]]; then cat << WARNING It seems you are running upgrade from graphics mode. You should use "screen" or "tmux". Are you sure you want to continue? WARNING pause fi } function print_exit_banner() { umount_cache_dnf if [ $UPGRADE_FINISHED -eq 1 ]; then echo "Enabling updates repos back" # upgrade to rawhide failed, restore repos dnf config-manager --set-enabled fedora updates updates-testing updates-modular # FIXME we should enable # rpmfusion-free-updates rpmfusion-nonfree-updates # but only if we previously disabled it echo "Disabling rawhide repo." dnf config-manager --set-disabled rawhide UPGRADE_FINISHED=0 fi if [ $UPGRADE_FINISHED -eq 1 ]; then echo echo You successfully upgraded to Fedora $TARGET_VERSION echo Reboot is strongly suggested. exit 0 else echo echo Upgrade to Fedora $TARGET_VERSION was not finished! echo You can safely re-run fedora-upgrade again to start over with: echo " fedora-upgrade --upgrade-to=${TARGET_VERSION}" exit 1 fi } function welcome_banner() { echo "Going to upgrade your Fedora to version $1." echo "You may want to read Release Notes:" echo " http://docs.fedoraproject.org/f${TARGET_VERSION}/release-notes/" echo "and about commond bugs:" echo " https://fedoraproject.org/wiki/Common_F${TARGET_VERSION}_bugs" pause } function warn_about_online() { echo "Warning: This is unofficial upgrade path. For official tool see:" echo " https://fedoraproject.org/wiki/Upgrading" echo " While author of fedora-upgrade thinks online upgrade is better, it is" echo " not officially tested by FedoraQA." pause } function going_to_reboot() { echo "" echo "********** End of DNF plugin output **********" echo "" echo "Download complete! The downloaded packages were saved in cache till the next" echo "successful transaction. You can remove cached packages by executing" echo "'dnf clean packages'." echo "In next step, your computer will be REBOOTED, and packages will be upgraded." pause } function choose_upgrade_method() { echo "Choose upgrade method" echo " * offline - this use dnf-plugin-system-upgrade plugin and requires two reboots" echo " - this is official upgrade method" echo " * online - this use distro-sync and require only one reboot" echo " - this is not officially tested by FedoraQA" echo "For more information see https://fedoraproject.org/wiki/Upgrading" read -t 1 -n 10000 discard || [ $? -gt 128 ] } function mount_cache_dnf() { if [ -n "$OPTS_TMPFS" ]; then mount -t tmpfs none -o "size=$OPTS_TMPFS" /var/cache/dnf/ TMPFS_MOUNTED=1 fi } function umount_cache_dnf() { if [ -n "$OPTS_TMPFS" -a 0$TMPFS_MOUNTED -eq 1 ]; then umount /var/cache/dnf/ TMPFS_MOUNTED=0 fi } ################################ START OF THE CODE ############################ if ! check_installation; then echo "Please install fedora-upgrade package using dnf first" exit 2 fi if [ 0$UID -ne 0 ]; then echo "Error: You must be a root." echo "Run as: sudo fedora-upgrade" exit 1 fi # make obvious ending for inexperienced users trap "print_exit_banner" SIGHUP SIGINT SIGTERM INT ERR # parse command line options for i in "$@"; do case $i in -u=*|--upgrade-to=*) OPTS_UPGRADE_TO="${i#*=}" TARGET_VERSION="$OPTS_UPGRADE_TO" if [ "$TARGET_VERSION" = "rawhide" ]; then TARGET_VERSION="$RAWHIDE_VERSION" fi shift # past argument=value ;; --tmpfs=*) OPTS_TMPFS="${i#*=}" shift # past argument=value ;; --help) OPTS_HELP=YES shift # past argument ;; *) # unknown option ;; esac done if [ -n "$OPTS_HELP" ]; then man fedora-upgrade | cat exit 0; fi if [ 0$TARGET_VERSION -eq 32 ]; then # Fedora 31 to 32 warn_if_graphics_mode welcome_banner $TARGET_VERSION dnf_install_deps dnf_upgrade_before_upgrade rpmconf_before_upgrade import_keys dnf clean -q dbcache metadata echo "Checking if this is pre-release" enable_updates="" #$(is_prerelease $TARGET_VERSION ) # https://bugzilla.redhat.com/show_bug.cgi?id=1767351 EXCEPTION_reset_modules choose_upgrade_method echo -e $1 ANSWER='XXX' while [ "$ANSWER" != "offline" -a "$ANSWER" != "online" ] ; do read -p "What is your choice? (offline/online) " ANSWER ANSWER=$(echo $ANSWER | tr "[:upper:]" "[:lower:]") done if [ "$ANSWER" == "online" ] ; then mount_cache_dnf dnf --releasever=$TARGET_VERSION --setopt=deltarpm=false --setopt=module_platform_id=platform:f$TARGET_VERSION $enable_updates $DISABLED_PLUGINS distro-sync umount_cache_dnf elif [ "$ANSWER" == "offline" ] ; then install_if_missing dnf-plugin-system-upgrade dnf system-upgrade download --setopt=module_platform_id=platform:f$TARGET_VERSION --releasever=$TARGET_VERSION going_to_reboot dnf system-upgrade reboot fi dnf_install_base cleanup_cache rpmconf_after_upgrade reset_service_priorities remove_old_gpg_keys unwanted_packages UPGRADE_FINISHED=1 elif [ 0$TARGET_VERSION -eq 33 ]; then # Fedora 32 to 33 warn_if_graphics_mode welcome_banner $TARGET_VERSION dnf_install_deps dnf_upgrade_before_upgrade rpmconf_before_upgrade import_keys dnf clean -q dbcache metadata # echo "Checking if this is pre-release" enable_updates="" #enable_updates=$(is_prerelease $TARGET_VERSION ) choose_upgrade_method echo -e $1 ANSWER='XXX' while [ "$ANSWER" != "offline" -a "$ANSWER" != "online" ] ; do read -p "What is your choice? (offline/online) " ANSWER ANSWER=$(echo $ANSWER | tr "[:upper:]" "[:lower:]") done if [ "$ANSWER" == "online" ] ; then mount_cache_dnf dnf --releasever=$TARGET_VERSION --setopt=deltarpm=false --setopt=module_platform_id=platform:f$TARGET_VERSION $enable_updates $DISABLED_PLUGINS distro-sync umount_cache_dnf elif [ "$ANSWER" == "offline" ] ; then install_if_missing dnf-plugin-system-upgrade dnf system-upgrade download --setopt=module_platform_id=platform:f$TARGET_VERSION --releasever=$TARGET_VERSION going_to_reboot dnf system-upgrade reboot fi dnf_install_base cleanup_cache rpmconf_after_upgrade reset_service_priorities remove_old_gpg_keys unwanted_packages UPGRADE_FINISHED=1 elif [ 0$TARGET_VERSION -eq 34 ]; then # Fedora 33 to 34 warn_if_graphics_mode welcome_banner $TARGET_VERSION dnf_install_deps dnf_upgrade_before_upgrade rpmconf_before_upgrade import_keys dnf clean -q dbcache metadata enable_updates="" #echo "Checking if this is pre-release" #enable_updates=$(is_prerelease $TARGET_VERSION ) # EXCEPTION https://bugzilla.redhat.com/show_bug.cgi?id=1919864 allowerasing="" rpm -q rdma-core.i686 >/dev/null 2>&1 && allowerasing="--allowerasing" choose_upgrade_method echo -e $1 ANSWER='XXX' while [ "$ANSWER" != "offline" -a "$ANSWER" != "online" ] ; do read -p "What is your choice? (offline/online) " ANSWER ANSWER=$(echo $ANSWER | tr "[:upper:]" "[:lower:]") done if [ "$ANSWER" == "online" ] ; then mount_cache_dnf dnf --releasever=$TARGET_VERSION --setopt=deltarpm=false --setopt=module_platform_id=platform:f$TARGET_VERSION $enable_updates $DISABLED_PLUGINS distro-sync $allowerasing umount_cache_dnf elif [ "$ANSWER" == "offline" ] ; then install_if_missing dnf-plugin-system-upgrade dnf system-upgrade download --setopt=module_platform_id=platform:f$TARGET_VERSION --releasever=$TARGET_VERSION $allowerasing going_to_reboot dnf system-upgrade reboot fi dnf_install_base cleanup_cache rpmconf_after_upgrade reset_service_priorities remove_old_gpg_keys unwanted_packages UPGRADE_FINISHED=1 elif [ 0$TARGET_VERSION -eq 0$RAWHIDE_VERSION ]; then warn_if_graphics_mode echo "Going to upgrade your Fedora to rawhide." echo "Fedora $TARGET_VERSION is currently under development." echo "Are you sure?" pause dnf_install_deps rpmconf_before_upgrade install_if_missing fedora-repos-rawhide dnf config-manager --set-disabled fedora updates updates-testing updates-modular rpmfusion-free-updates rpmfusion-nonfree-updates dnf config-manager --set-enabled rawhide UPGRADE_FINISHED=2 dnf clean -q dbcache metadata EXCEPTION_reset_libgit2_module choose_upgrade_method echo -e $1 ANSWER='XXX' while [ "$ANSWER" != "offline" -a "$ANSWER" != "online" ] ; do read -p "What is your choice? (offline/online) " ANSWER ANSWER=$(echo $ANSWER | tr "[:upper:]" "[:lower:]") done if [ "$ANSWER" == "online" ] ; then mount_cache_dnf dnf --releasever=rawhide --setopt=deltarpm=false --setopt=module_platform_id=platform:f$TARGET_VERSION $DISABLED_PLUGINS distro-sync --nogpgcheck umount_cache_dnf elif [ "$ANSWER" == "offline" ] ; then install_if_missing dnf-plugin-system-upgrade dnf system-upgrade download --setopt=module_platform_id=platform:f$TARGET_VERSION --releasever=rawhide --nogpgcheck going_to_reboot dnf system-upgrade reboot fi dnf_install_base cleanup_cache rpmconf_after_upgrade reset_service_priorities remove_old_gpg_keys unwanted_packages UPGRADE_FINISHED=1 else echo Upgrading to version $TARGET_VERSION is not supported. exit 1 fi print_exit_banner