165 lines
6.6 KiB
Diff
165 lines
6.6 KiB
Diff
From f5a3d626cf97c193ab1523401827c2a4c89310ea Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Matej=20Matu=C5=A1ka?= <mmatuska@redhat.com>
|
|
Date: Fri, 20 Jan 2023 14:03:59 +0100
|
|
Subject: [PATCH 60/63] Prevent failed upgrade from restarting in initramfs
|
|
(#996)
|
|
|
|
* Prevent failed upgrade from restarting in initramfs
|
|
|
|
When the upgrade fails in the initramfs the dracut shell is entered.
|
|
Upon exiting the dracut shell, the upgrade.target is restarted which
|
|
causes the upgrade.service, which runs the leapp upgrade, to rerun as
|
|
well.
|
|
|
|
This commit fixes that by creating a "flag" file when the upgrade
|
|
fails, whose existence is checked before reruning the upgrade and the
|
|
upgrade is prevented in such case.
|
|
|
|
Also, a new removeupgradeartifacts actor is introduced to clean up leftover upgrade artifacts, including the upgrade failed flag file, at the beginning of the upgrade process.
|
|
|
|
Jira ref.: OAMG-4224
|
|
---
|
|
.../dracut/85sys-upgrade-redhat/do-upgrade.sh | 20 +++++++++++++
|
|
.../actors/removeupgradeartifacts/actor.py | 23 +++++++++++++++
|
|
.../libraries/removeupgradeartifacts.py | 17 +++++++++++
|
|
.../tests/test_removeupgradeartifacts.py | 28 +++++++++++++++++++
|
|
4 files changed, 88 insertions(+)
|
|
create mode 100644 repos/system_upgrade/common/actors/removeupgradeartifacts/actor.py
|
|
create mode 100644 repos/system_upgrade/common/actors/removeupgradeartifacts/libraries/removeupgradeartifacts.py
|
|
create mode 100644 repos/system_upgrade/common/actors/removeupgradeartifacts/tests/test_removeupgradeartifacts.py
|
|
|
|
diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh
|
|
index 0763d5b3..04540c1d 100755
|
|
--- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh
|
|
+++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh
|
|
@@ -46,6 +46,8 @@ fi
|
|
export NSPAWN_OPTS="$NSPAWN_OPTS --keep-unit --register=no --timezone=off --resolv-conf=off"
|
|
|
|
|
|
+export LEAPP_FAILED_FLAG_FILE="/root/tmp_leapp_py3/.leapp_upgrade_failed"
|
|
+
|
|
#
|
|
# Temp for collecting and preparing tarball
|
|
#
|
|
@@ -268,6 +270,15 @@ do_upgrade() {
|
|
rv=$?
|
|
fi
|
|
|
|
+ if [ "$rv" -ne 0 ]; then
|
|
+ # set the upgrade failed flag to prevent the upgrade from running again
|
|
+ # when the emergency shell exits and the upgrade.target is restarted
|
|
+ local dirname
|
|
+ dirname="$("$NEWROOT/bin/dirname" "$NEWROOT$LEAPP_FAILED_FLAG_FILE")"
|
|
+ [ -d "$dirname" ] || mkdir "$dirname"
|
|
+ "$NEWROOT/bin/touch" "$NEWROOT$LEAPP_FAILED_FLAG_FILE"
|
|
+ fi
|
|
+
|
|
# Dump debug data in case something went wrong
|
|
if want_inband_dump "$rv"; then
|
|
collect_and_dump_debug_data
|
|
@@ -338,6 +349,15 @@ mount -o "remount,rw" "$NEWROOT"
|
|
|
|
##### do the upgrade #######
|
|
(
|
|
+ # check if leapp previously failed in the initramfs, if it did return to the emergency shell
|
|
+ [ -f "$NEWROOT$LEAPP_FAILED_FLAG_FILE" ] && {
|
|
+ echo >&2 "Found file $NEWROOT$LEAPP_FAILED_FLAG_FILE"
|
|
+ echo >&2 "Error: Leapp previously failed and cannot continue, returning back to emergency shell"
|
|
+ echo >&2 "Please file a support case with $NEWROOT/var/log/leapp/leapp-upgrade.log attached"
|
|
+ echo >&2 "To rerun the upgrade upon exiting the dracut shell remove the $NEWROOT$LEAPP_FAILED_FLAG_FILE file"
|
|
+ exit 1
|
|
+ }
|
|
+
|
|
[ ! -x "$NEWROOT$LEAPPBIN" ] && {
|
|
warn "upgrade binary '$LEAPPBIN' missing!"
|
|
exit 1
|
|
diff --git a/repos/system_upgrade/common/actors/removeupgradeartifacts/actor.py b/repos/system_upgrade/common/actors/removeupgradeartifacts/actor.py
|
|
new file mode 100644
|
|
index 00000000..5eb60d27
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/removeupgradeartifacts/actor.py
|
|
@@ -0,0 +1,23 @@
|
|
+from leapp.actors import Actor
|
|
+from leapp.libraries.actor import removeupgradeartifacts
|
|
+from leapp.tags import InterimPreparationPhaseTag, IPUWorkflowTag
|
|
+
|
|
+
|
|
+class RemoveUpgradeArtifacts(Actor):
|
|
+ """
|
|
+ Removes artifacts left over by previous leapp runs
|
|
+
|
|
+ After the upgrade process, there might be some leftover files, which need
|
|
+ to be cleaned up before running another upgrade.
|
|
+
|
|
+ Removed artifacts:
|
|
+ - /root/tmp_leapp_py3/ directory (includes ".leapp_upgrade_failed" flag file)
|
|
+ """
|
|
+
|
|
+ name = 'remove_upgrade_artifacts'
|
|
+ consumes = ()
|
|
+ produces = ()
|
|
+ tags = (InterimPreparationPhaseTag, IPUWorkflowTag)
|
|
+
|
|
+ def process(self):
|
|
+ removeupgradeartifacts.process()
|
|
diff --git a/repos/system_upgrade/common/actors/removeupgradeartifacts/libraries/removeupgradeartifacts.py b/repos/system_upgrade/common/actors/removeupgradeartifacts/libraries/removeupgradeartifacts.py
|
|
new file mode 100644
|
|
index 00000000..aa748d9d
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/removeupgradeartifacts/libraries/removeupgradeartifacts.py
|
|
@@ -0,0 +1,17 @@
|
|
+import os
|
|
+
|
|
+from leapp.libraries.stdlib import api, CalledProcessError, run
|
|
+
|
|
+UPGRADE_ARTIFACTS_DIR = '/root/tmp_leapp_py3/'
|
|
+
|
|
+
|
|
+def process():
|
|
+ if os.path.exists(UPGRADE_ARTIFACTS_DIR):
|
|
+ api.current_logger().debug(
|
|
+ "Removing leftover upgrade artifacts dir: {} ".format(UPGRADE_ARTIFACTS_DIR))
|
|
+
|
|
+ try:
|
|
+ run(['rm', '-rf', UPGRADE_ARTIFACTS_DIR])
|
|
+ except (CalledProcessError, OSError) as e:
|
|
+ api.current_logger().debug(
|
|
+ 'Failed to remove leftover upgrade artifacts dir: {}'.format(e))
|
|
diff --git a/repos/system_upgrade/common/actors/removeupgradeartifacts/tests/test_removeupgradeartifacts.py b/repos/system_upgrade/common/actors/removeupgradeartifacts/tests/test_removeupgradeartifacts.py
|
|
new file mode 100644
|
|
index 00000000..aee4d7c6
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/removeupgradeartifacts/tests/test_removeupgradeartifacts.py
|
|
@@ -0,0 +1,28 @@
|
|
+import os
|
|
+
|
|
+import pytest
|
|
+
|
|
+from leapp.libraries.actor import removeupgradeartifacts
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize(('exists', 'should_remove'), [
|
|
+ (True, True),
|
|
+ (False, False),
|
|
+])
|
|
+def test_remove_upgrade_artifacts(monkeypatch, exists, should_remove):
|
|
+
|
|
+ called = [False]
|
|
+
|
|
+ def mocked_run(cmd, *args, **kwargs):
|
|
+ assert cmd[0] == 'rm'
|
|
+ assert cmd[1] == '-rf'
|
|
+ assert cmd[2] == removeupgradeartifacts.UPGRADE_ARTIFACTS_DIR
|
|
+ called[0] = True
|
|
+ return {'exit_code': 0, 'stdout': '', 'stderr': ''}
|
|
+
|
|
+ monkeypatch.setattr(os.path, 'exists', lambda _: exists)
|
|
+ monkeypatch.setattr(removeupgradeartifacts, 'run', mocked_run)
|
|
+
|
|
+ removeupgradeartifacts.process()
|
|
+
|
|
+ assert called[0] == should_remove
|
|
--
|
|
2.39.0
|
|
|