From 912d9ec9e0b3d40c8dedc97588f683477dd1e876 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Thu, 24 Jun 2021 12:54:34 -0400 Subject: [PATCH] upgrades: Check for held freedombox package in manual update This is to recover from a situation where the package is held, and then plinth process is interrupted so it cannot release the hold. We check for and recover from this situation when installing new apps, and when running dist upgrade. This provides another way to recover from the problem, by running manual update. Tests: - (normal) No hold on freedombox package, and flag is not set. Run manual update. Afterwards, there is no hold, and flag is not set. - (admin preference) Place hold on freedombox package, but flag is not set. Run manual update. Afterwards, there is still a hold, but flag is not set. - (recovery) Place hold on freedombox package, but flag is set. Run manual update. Afterwards, there is no hold, and flag is not set. Signed-off-by: James Valleroy --- actions/upgrades | 13 ++++++++++--- plinth/action_utils.py | 20 +++++++++++++------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/actions/upgrades b/actions/upgrades index 242a87093..313adcf45 100755 --- a/actions/upgrades +++ b/actions/upgrades @@ -14,9 +14,10 @@ import subprocess import sys import time -from plinth.action_utils import (apt_hold, apt_hold_freedombox, - debconf_set_selections, run_apt_command, - service_daemon_reload, service_restart) +from plinth.action_utils import (apt_hold, apt_hold_flag, apt_hold_freedombox, + apt_unhold_freedombox, debconf_set_selections, + run_apt_command, service_daemon_reload, + service_restart) from plinth.modules.apache.components import check_url from plinth.modules.snapshot import (is_apt_snapshots_enabled, is_supported as snapshot_is_supported, load_augeas as @@ -141,6 +142,12 @@ def _run(): """Run unattended-upgrades""" subprocess.run(['dpkg', '--configure', '-a']) run_apt_command(['--fix-broken', 'install']) + + # In case freedombox package was left in held state by an + # interrupted process, release it. + if apt_hold_flag.exists(): + apt_unhold_freedombox() + subprocess.Popen(['systemctl', 'start', 'freedombox-manual-upgrade'], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True, diff --git a/plinth/action_utils.py b/plinth/action_utils.py index cf88ee816..85b5f057c 100644 --- a/plinth/action_utils.py +++ b/plinth/action_utils.py @@ -16,6 +16,11 @@ logger = logging.getLogger(__name__) UWSGI_ENABLED_PATH = '/etc/uwsgi/apps-enabled/{config_name}.ini' UWSGI_AVAILABLE_PATH = '/etc/uwsgi/apps-available/{config_name}.ini' +# Flag on disk to indicate if freedombox package was held by +# plinth. This is a backup in case the process is interrupted and hold +# is not released. +apt_hold_flag = pathlib.Path('/var/lib/freedombox/package-held') + def is_systemd_running(): """Return if we are running under systemd.""" @@ -434,9 +439,6 @@ def apt_hold(packages, ignore_errors=False): @contextmanager def apt_hold_freedombox(): """Prevent freedombox package from being removed during apt operations.""" - # This flag is a backup indicator that we held the package, in - # case the process is interrupted and the 'finally' is not run. - apt_hold_flag = pathlib.Path('/var/lib/freedombox/package-held') current_hold = subprocess.check_output( ['apt-mark', 'showhold', 'freedombox']) try: @@ -450,7 +452,11 @@ def apt_hold_freedombox(): finally: # Was the package held, either in this process or a previous one? if not current_hold or apt_hold_flag.exists(): - subprocess.check_call(['apt-mark', 'unhold', 'freedombox']) - # Clear the flag. - if apt_hold_flag.exists(): - apt_hold_flag.unlink() + apt_unhold_freedombox() + + +def apt_unhold_freedombox(): + """Remove any hold on freedombox package, and clear flag.""" + subprocess.check_call(['apt-mark', 'unhold', 'freedombox']) + if apt_hold_flag.exists(): + apt_hold_flag.unlink()