diff --git a/locales/en.json b/locales/en.json index 04aa5926a..7693e601d 100644 --- a/locales/en.json +++ b/locales/en.json @@ -570,6 +570,7 @@ "main_domain_change_failed": "Unable to change the main domain", "main_domain_changed": "The main domain has been changed", "migration_0027_cleaning_up": "Cleaning up cache and packages not useful anymore…", + "migration_0027_delayed_api_restart": "The YunoHost API will automatically be restarted in 15 seconds. It may be unavailable for a few seconds, and then you will have to login again.", "migration_0027_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade.", "migration_0027_main_upgrade": "Starting main upgrade…", "migration_0027_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}", diff --git a/src/migrations/0027_migrate_to_bookworm.py b/src/migrations/0027_migrate_to_bookworm.py index 9ff497398..17b252871 100644 --- a/src/migrations/0027_migrate_to_bookworm.py +++ b/src/migrations/0027_migrate_to_bookworm.py @@ -1,7 +1,9 @@ import glob import os +import subprocess +from time import sleep -from moulinette import m18n +from moulinette import Moulinette, m18n from yunohost.utils.error import YunohostError from moulinette.utils.process import check_output from moulinette.utils.filesystem import read_file, write_to_file @@ -11,7 +13,7 @@ from yunohost.tools import ( tools_update, ) from yunohost.app import unstable_apps -from yunohost.regenconf import manually_modified_files +from yunohost.regenconf import manually_modified_files, regen_conf from yunohost.utils.system import ( free_space_in_directory, get_ynh_package_version, @@ -175,10 +177,20 @@ class MyMigration(Migration): apps_packages = self.get_apps_equivs_packages() aptitude_with_progress_bar(f"hold yunohost moulinette ssowat yunohost-admin {' '.join(apps_packages)}") - aptitude_with_progress_bar("upgrade cron --show-why -y -o APT::Force-LoopBreak=1 -o Dpkg::Options::='--force-confold'") + # Dirty hack to be able to remove rspamd because it's causing too many issues due to libluajit ... + command = "sed -i /var/lib/dpkg/status -e 's@rspamd, @@g'" + logger.debug(f"Running: {command}") + os.system(command) + + aptitude_with_progress_bar("upgrade cron rspamd- libluajit-5.1-2- --show-why -o APT::Force-LoopBreak=1 -o Dpkg::Options::='--force-confold'") # FIXME : find a way to simulate and validate the upgrade first - aptitude_with_progress_bar("full-upgrade --show-why -y -o Dpkg::Options::='--force-confold'") + aptitude_with_progress_bar("full-upgrade --show-why -o Dpkg::Options::='--force-confold'") + + # Force regenconf of nsswitch because for some reason + # /etc/nsswitch.conf is reset despite the --force-confold? It's a + # disaster because then admins cannot "sudo" >_> ... + regen_conf(names=["nsswitch"], force=True) if self.debian_major_version() == N_CURRENT_DEBIAN: raise YunohostError("migration_0027_still_on_bullseye_after_main_upgrade") @@ -208,8 +220,7 @@ class MyMigration(Migration): aptitude_with_progress_bar(f"unhold yunohost moulinette ssowat yunohost-admin {' '.join(apps_packages)}") # FIXME : find a way to simulate and validate the upgrade first - # FIXME : why were libluajit needed in the first place ? - aptitude_with_progress_bar("full-upgrade --show-why yunohost yunohost-admin moulinette ssowat libluajit-5.1-2- libluajit-5.1-common- -y -o Dpkg::Options::='--force-confold'") + aptitude_with_progress_bar("full-upgrade --show-why yunohost yunohost-admin moulinette ssowat -o Dpkg::Options::='--force-confold'") #cmd = "LC_ALL=C" #cmd += " DEBIAN_FRONTEND=noninteractive" @@ -230,6 +241,16 @@ class MyMigration(Migration): #postupgradecmds += "echo 'Restarting nginx...' >&2\n" #postupgradecmds += "systemctl restart nginx\n" + # If running from the webadmin, restart the API after a delay + if Moulinette.interface.type == "api": + logger.warning(m18n.n("migration_0027_delayed_api_restart")) + sleep(5) + # Restart the API after 10 sec (at now doesn't support sub-minute times...) + # We do this so that the API / webadmin still gets the proper HTTP response + cmd = 'at -M now >/dev/null 2>&1 <<< "sleep 10; systemctl restart nginx yunohost-api"' + # For some reason subprocess doesn't like the redirections so we have to use bash -c explicity... + subprocess.check_call(["bash", "-c", cmd]) + def debian_major_version(self): # The python module "platform" and lsb_release are not reliable because # on some setup, they may still return Release=9 even after upgrading to diff --git a/src/utils/system.py b/src/utils/system.py index 105aea704..9b6de576c 100644 --- a/src/utils/system.py +++ b/src/utils/system.py @@ -20,6 +20,7 @@ import re import os import logging +from moulinette import Moulinette from moulinette.utils.process import check_output from yunohost.utils.error import YunohostError @@ -283,18 +284,27 @@ def aptitude_with_progress_bar(cmd): lambda l: log_apt_status_to_progress_bar(l.rstrip()), ) + original_cmd = cmd cmd = ( f'LC_ALL=C DEBIAN_FRONTEND=noninteractive APT_LISTCHANGES_FRONTEND=none aptitude {cmd} --quiet=2 -o=Dpkg::Use-Pty=0 -o "APT::Status-Fd=$YNH_STDINFO"' ) + # If upgrading yunohost from the API, delay the Yunohost-api restart + # (this should be the last time we need it before bookworm, because on bookworm, yunohost-admin cookies will be persistent upon api restart) + if " yunohost " in cmd and Moulinette.interface.type == "api": + cmd = "YUNOHOST_API_RESTART_WILL_BE_HANDLED_BY_YUNOHOST=yes " + cmd + logger.debug(f"Running: {cmd}") + read, write = os.pipe() + os.write(write, b"y\ny\ny") + os.close(write) ret = call_async_output(cmd, callbacks, shell=True) if log_apt_status_to_progress_bar.previous_package is not None and ret == 0: log_apt_status_to_progress_bar("done::100:Done") elif ret != 0: - raise YunohostError(f"Failed to run command 'aptitude {cmd}'", raw_msg=True) + raise YunohostError(f"Failed to run command 'aptitude {original_cmd}'", raw_msg=True) def _apt_log_line_is_relevant(line):