From 57e173485530d9d68efd0945a676e3d3084e03ad Mon Sep 17 00:00:00 2001 From: wang-guangge Date: Mon, 18 Dec 2023 22:39:00 +0800 Subject: [PATCH] improve dnf hotupgrade and dnf upgrade-en (cherry picked from commit aead98b0b118fb009d69c722e892f9d7415ca5ef) --- ...tatus-judgement-and-hotupgrade-logic.patch | 202 ++++++++++++++++++ aops-ceres.spec | 7 +- 2 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 0001-improve-status-judgement-and-hotupgrade-logic.patch diff --git a/0001-improve-status-judgement-and-hotupgrade-logic.patch b/0001-improve-status-judgement-and-hotupgrade-logic.patch new file mode 100644 index 0000000..a252255 --- /dev/null +++ b/0001-improve-status-judgement-and-hotupgrade-logic.patch @@ -0,0 +1,202 @@ +From 2229dade5b178fa2f6a3b572f110eb4fe6677935 Mon Sep 17 00:00:00 2001 +From: wang-guangge +Date: Mon, 18 Dec 2023 21:59:46 +0800 +Subject: [PATCH] improve task execution status code and hotupgrade logic of + reinstalling active/accept hotpatch + +--- + hotpatch/hotupgrade.py | 69 +++++++++++++++++++++++++++++++----------- + hotpatch/upgrade_en.py | 6 ++-- + 2 files changed, 54 insertions(+), 21 deletions(-) + +diff --git a/hotpatch/hotupgrade.py b/hotpatch/hotupgrade.py +index 5dfee0d..37497cf 100644 +--- a/hotpatch/hotupgrade.py ++++ b/hotpatch/hotupgrade.py +@@ -13,6 +13,7 @@ + from __future__ import print_function + + from time import sleep ++from typing import Tuple + + import dnf.base + import dnf.exceptions +@@ -28,6 +29,8 @@ from .upgrade_en import UpgradeEnhanceCommand + from .version import Versions + + EMPTY_TAG = "-" ++SUCCEED = 0 ++FAIL = 255 + + + @dnf.plugin.register_command +@@ -94,9 +97,14 @@ class HotupgradeCommand(dnf.cli.Command): + logger.info(_('No hot patches marked for install.')) + return + +- applied_old_patches = self._get_applied_old_patch(list(available_hp_dict.values())) +- if applied_old_patches: +- self._remove_hot_patches(applied_old_patches) ++ uneffectived_old_patches, effectived_old_patches = self._get_applied_old_patch(list(available_hp_dict.values())) ++ # remove effectived hp from self.hp_list and available_hp_dict ++ effectived_hp_list = [key for key, value in available_hp_dict.items() if value in effectived_old_patches] ++ self.hp_list = [hp for hp in self.hp_list if hp not in effectived_hp_list] ++ available_hp_dict = {key: value for key, value in available_hp_dict.items() if value not in effectived_hp_list} ++ ++ if uneffectived_old_patches: ++ self._remove_hot_patches(uneffectived_old_patches) + else: + self.syscare.save() + success = self._install_rpm_pkg(list(available_hp_dict.keys())) +@@ -143,14 +151,24 @@ class HotupgradeCommand(dnf.cli.Command): + if str(ts_item.pkg) == self.kernel_coldpatch: + self.is_kernel_coldpatch_installed = True + +- self.keep_hp_operation_atomic(is_all_kernel_hp_actived, target_remove_hp) ++ is_task_success = True ++ is_task_success &= self.keep_hp_operation_atomic(is_all_kernel_hp_actived, target_remove_hp) + + if self.is_need_accept_kernel_hp and acceptable_hp: ++ is_accept_success = True + logger.info(_('No available kernel cold patch for takeover, gonna accept available kernel hot patch.')) + for hp in acceptable_hp: +- self._accept_kernel_hp(hp) ++ pkg_info = self._parse_hp_name(hp) ++ if pkg_info['target_name'] != "kernel": ++ continue ++ is_accept_success &= False if self._accept_hp(hp) != SUCCEED else True ++ # if need accept operation but failed, it indicates hotupgrade task failed ++ is_task_success &= is_accept_success ++ ++ if not is_task_success: ++ exit(1) + +- def keep_hp_operation_atomic(self, is_all_kernel_hp_actived, target_remove_hp): ++ def keep_hp_operation_atomic(self, is_all_kernel_hp_actived, target_remove_hp) -> bool: + """ + Keep hotpatch related operation atomic. Once one kernel hotpatch is not successfully activated or + kabi check fails, uninstall the kernel coldpatch. And unsuccessfully activated hotpatch package +@@ -159,9 +177,13 @@ class HotupgradeCommand(dnf.cli.Command): + Args: + is_all_kernel_hp_actived(bool): are all kernel related hotpatches activated + target_remove_hp(list): target remove hotpatch list ++ ++ Returns: ++ bool: if hotupgrade task success + """ + upgrade_en = UpgradeEnhanceCommand(self.cli) + ++ is_task_success = True + if self.is_kernel_coldpatch_installed: + if not is_all_kernel_hp_actived: + logger.info(_('Gonna remove %s due to some kernel hotpatch activation failed.'), self.kernel_coldpatch) +@@ -177,8 +199,12 @@ class HotupgradeCommand(dnf.cli.Command): + + if target_remove_hp: + logger.info(_('Gonna remove unsuccessfully activated hotpatch rpm.')) ++ # when processing remove operation, do not achieve the expected result of activating hotpatch rpm, ++ # it indicates that the hotupgrade task failed ++ is_task_success &= False + for hotpatch in target_remove_hp: + upgrade_en.remove_rpm(hotpatch) ++ return is_task_success + + def _apply_hp(self, hp_full_name): + pkg_info = self._parse_hp_name(hp_full_name) +@@ -264,7 +290,7 @@ class HotupgradeCommand(dnf.cli.Command): + return hp_map + + @staticmethod +- def _get_applied_old_patch(available_hp_list: list) -> list: ++ def _get_applied_old_patch(available_hp_list: list) -> Tuple[list, list]: + """ + get targets' applied accumulative hot patches. + User can install and apply multiple sgl (single) hot patches because the rpm name is different, +@@ -273,9 +299,11 @@ class HotupgradeCommand(dnf.cli.Command): + available_hp_list: e.g. ['redis-1.0-1/ACC-1-1', 'redis-1.0-1/SGL_CVE_2022_1-1-1'] + + Returns: +- list: applied hot patches. e.g. ['redis-1.0-1/ACC-1-1'] ++ Tuple[str, str]: a tuple containing two elements (uneffectived hot patches, effectived hot patches). ++ e.g. (['redis-1.0-1/ACC-1-1'], ['redis-1.0-1/SGL_CVE_2022_3047-1-1']) + """ +- hotpatch_set = set() ++ uneffectived_hotpatch_set = set() ++ effectived_hotpatch_set = set() + hps_info = Syscare.list() + for hp_info in hps_info: + # hp_info[Name] is the middle column of syscare list. format: {target_rpm_name}/{hp_name}/{binary_file} +@@ -297,9 +325,12 @@ class HotupgradeCommand(dnf.cli.Command): + hp_info["Status"], + binary_file, + ) +- if hotpatch not in hotpatch_set: +- hotpatch_set.add(hotpatch) +- return list(hotpatch_set) ++ if hp_info["Status"] in ["ACTIVED", "ACCEPTED"]: ++ effectived_hotpatch_set.add(hotpatch) ++ continue ++ if hotpatch not in uneffectived_hotpatch_set: ++ uneffectived_hotpatch_set.add(hotpatch) ++ return list(uneffectived_hotpatch_set), list(effectived_hotpatch_set) + + def _remove_hot_patches(self, applied_old_patches: list) -> None: + # output = Output(self.base, dnf.conf.Conf()) +@@ -548,19 +579,21 @@ class HotupgradeCommand(dnf.cli.Command): + parsed_nevra = parsed_nevras[0] + return parsed_nevra.name, "%s-%s" % (parsed_nevra.version, parsed_nevra.release) + +- def _accept_kernel_hp(self, hp_full_name: str): ++ def _accept_hp(self, hp_full_name: str) -> int: + """ +- accept kernel hot patch ++ accept hot patch + + Args: + str: hp_full_name: full name of hot patch. e.g. patch-kernel-5.10.0-1-ACC-1-1.x86_64 ++ ++ Returns: ++ int: status + """ + pkg_info = self._parse_hp_name(hp_full_name) +- if pkg_info['target_name'] != "kernel": +- return + hp_subname = self._get_hp_subname_for_syscare(pkg_info) + output, status = self.syscare.accept(hp_subname) + if status: +- logger.info(_('Accept kernel hot patch failed: %s.'), hp_subname) ++ logger.info(_('Accept hot patch failed: %s.'), hp_subname) + else: +- logger.info(_('Accept kernel hot patch succeed: %s.'), hp_subname) ++ logger.info(_('Accept hot patch succeed: %s.'), hp_subname) ++ return status +diff --git a/hotpatch/upgrade_en.py b/hotpatch/upgrade_en.py +index 3053179..94ba4da 100644 +--- a/hotpatch/upgrade_en.py ++++ b/hotpatch/upgrade_en.py +@@ -97,7 +97,10 @@ class UpgradeEnhanceCommand(dnf.cli.Command): + print('Gonna remove %s due to kabi check failed.' % kernel_pkg) + # rebuild rpm database for processing kernel rpm remove operation + self.rebuild_rpm_db() ++ # when processing remove operation, do not achieve the expected result of installing related rpm, ++ # it indicates that the upgrade task failed + self.remove_rpm(kernel_pkg) ++ exit(1) + + def remove_rpm(self, pkg: str): + """ +@@ -113,11 +116,8 @@ class UpgradeEnhanceCommand(dnf.cli.Command): + if return_code != SUCCEED: + print('Remove package failed: %s.' % pkg) + print(output) +- exit(1) + else: + print('Remove package succeed: %s.' % pkg) +- # do not achieve the expected result of installing related rpm +- exit(1) + + def rebuild_rpm_db(self): + """ +-- +2.27.0 + diff --git a/aops-ceres.spec b/aops-ceres.spec index 3e6a17d..ad83e3a 100644 --- a/aops-ceres.spec +++ b/aops-ceres.spec @@ -2,7 +2,7 @@ Name: aops-ceres Version: v1.4.1 -Release: 1 +Release: 2 Summary: An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on. License: MulanPSL2 URL: https://gitee.com/openeuler/%{name} @@ -13,7 +13,7 @@ Requires: python3-requests python3-jsonschema python3-libconf Requires: python3-concurrent-log-handler dmidecode dnf-hotpatch-plugin >= v1.3.4 Provides: aops-ceres Conflicts: aops-agent - +Patch0001: 0001-improve-status-judgement-and-hotupgrade-logic.patch %description An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on. @@ -86,6 +86,9 @@ install -b -m500 ./extra-tools/da-tool/script/da-tool.sh ${RPM_BUILD_ROOT} %attr(0500, root, root) %{_bindir}/da-tool-analysis %changelog +* Mon Dec 18 2023 wangguangge - v1.4.1-2 +- improve task execution status code and hotupgrade logic of reinstalling active/accept hotpatch + * Mon Dec 18 2023 wangguangge - v1.4.1-1 - update to v1.4.1 - update cve fix logic