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 <jvalleroy@mailbox.org>
This commit is contained in:
James Valleroy 2021-06-24 12:54:34 -04:00
parent 856a83c890
commit 912d9ec9e0
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
2 changed files with 23 additions and 10 deletions

View File

@ -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,

View File

@ -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()