From f99dc1043e84bff9378d531b94fc18996e6e584f Mon Sep 17 00:00:00 2001 From: jxy_git Date: Wed, 13 Dec 2023 13:45:52 +0800 Subject: [PATCH] Sync master branch code to openEuler-22.03-LTS-SP3 (cherry picked from commit ec8912f8280623c849b9a7234a0bc9a9cb31d063) --- Fix-CVE-2022-1049.patch | 56 ++ Fix-CVE-2022-2735.patch | 46 ++ Fix-typing-in-resource_agent-package.patch | 147 ++++++ fix-pcs-config-checkpoint-diff-command.patch | 106 ++++ fix-pcs-quorum-device-remove.patch | 25 + fix-serving-static-files.patch | 33 ++ ...-error-messages-in-pcs-resource-move.patch | 484 ++++++++++++++++++ pcs.spec | 35 +- tests-fix-datetime-race-condition.patch | 27 + 9 files changed, 958 insertions(+), 1 deletion(-) create mode 100644 Fix-CVE-2022-1049.patch create mode 100644 Fix-CVE-2022-2735.patch create mode 100644 Fix-typing-in-resource_agent-package.patch create mode 100644 fix-pcs-config-checkpoint-diff-command.patch create mode 100644 fix-pcs-quorum-device-remove.patch create mode 100644 fix-serving-static-files.patch create mode 100644 improve-error-messages-in-pcs-resource-move.patch create mode 100644 tests-fix-datetime-race-condition.patch diff --git a/Fix-CVE-2022-1049.patch b/Fix-CVE-2022-1049.patch new file mode 100644 index 0000000..f17e146 --- /dev/null +++ b/Fix-CVE-2022-1049.patch @@ -0,0 +1,56 @@ +From 32d90eab80ee957350c4c218ecf7ed5ac7efc7d0 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 19 Oct 2023 16:54:43 +0800 +Subject: [PATCH] FIX CVE-2022-1049 + +--- + CHANGELOG.md | 4 +++- + pcs/daemon/auth.py | 3 +++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG.md b/CHANGELOG.md +index 7949064..c6007ac 100644 +--- a/CHANGELOG.md ++++ b/CHANGELOG.md +@@ -17,7 +17,8 @@ + cluster cib-upgrade` manually is not needed ([rhbz#2022463]) + - Fix displaying differences between configuration checkpoints in + `pcs config checkpoint diff` command ([rhbz#2175881]) +- ++- Pcs daemon was allowing expired accounts, and accounts with expired ++ passwords to login when using PAM auth. ([huntr#220307]) + + [ghissue#441]: https://github.com/ClusterLabs/pcs/issues/441 + [ghpull#431]: https://github.com/ClusterLabs/pcs/pull/431 +@@ -28,6 +29,7 @@ + [rhbz#2033248]: https://bugzilla.redhat.com/show_bug.cgi?id=2033248 + [rhbz#2036633]: https://bugzilla.redhat.com/show_bug.cgi?id=2036633 + [rhbz#2175881]: https://bugzilla.redhat.com/show_bug.cgi?id=2175881 ++[huntr#220307]: https://huntr.dev/bounties/7aa921fc-a568-4fd8-96f4-7cd826246aa5/ + + ## [0.11.1] - 2021-11-30 + +diff --git a/pcs/daemon/auth.py b/pcs/daemon/auth.py +index 592aa63..1ae2ed2 100644 +--- a/pcs/daemon/auth.py ++++ b/pcs/daemon/auth.py +@@ -52,6 +52,7 @@ libpam = CDLL(find_library("pam")) + strdup = prep_fn(libc.strdup, POINTER(c_char), [c_char_p]) + calloc = prep_fn(libc.calloc, c_void_p, [c_uint, c_uint]) + pam_authenticate = prep_fn(libpam.pam_authenticate, c_int, [pam_handle, c_int]) ++pam_acct_mgmt = prep_fn(libpam.pam_acct_mgmt, c_int, [pam_handle, c_int]) + pam_end = prep_fn(libpam.pam_end, c_int, [pam_handle, c_int]) + pam_start = prep_fn( + libpam.pam_start, +@@ -90,6 +91,8 @@ def authenticate_by_pam(username, password): + ) + if returncode == PAM_SUCCESS: + returncode = pam_authenticate(pamh, 0) ++ if returncode == PAM_SUCCESS: ++ returncode = pam_acct_mgmt(pamh, 0) + pam_end(pamh, returncode) + return returncode == PAM_SUCCESS + +-- +2.27.0 + diff --git a/Fix-CVE-2022-2735.patch b/Fix-CVE-2022-2735.patch new file mode 100644 index 0000000..fb41b5e --- /dev/null +++ b/Fix-CVE-2022-2735.patch @@ -0,0 +1,46 @@ +From c44b3139334dc6f132d73e0771b0e3254756df20 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 19 Oct 2023 17:02:43 +0800 +Subject: [PATCH] Fix CVE-2022-2735 + +--- + pcsd/rserver.rb | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/pcsd/rserver.rb b/pcsd/rserver.rb +index e2c5e2a..4fde639 100644 +--- a/pcsd/rserver.rb ++++ b/pcsd/rserver.rb +@@ -7,6 +7,29 @@ require 'thin' + + require 'settings.rb' + ++# Replace Thin::Backends::UnixServer:connect ++# The only change is 'File.umask(0o777)' instead of 'File.umask(0)' to properly ++# set python-ruby socket permissions ++module Thin ++ module Backends ++ class UnixServer < Base ++ def connect ++ at_exit { remove_socket_file } # In case it crashes ++ old_umask = File.umask(0o077) ++ begin ++ EventMachine.start_unix_domain_server(@socket, UnixConnection, &method(:initialize_connection)) ++ # HACK EventMachine.start_unix_domain_server doesn't return the connection signature ++ # so we have to go in the internal stuff to find it. ++ @signature = EventMachine.instance_eval{@acceptors.keys.first} ++ ensure ++ File.umask(old_umask) ++ end ++ end ++ end ++ end ++end ++ ++ + def pack_response(response) + return [200, {}, [response.to_json.to_str]] + end +-- +2.27.0 + diff --git a/Fix-typing-in-resource_agent-package.patch b/Fix-typing-in-resource_agent-package.patch new file mode 100644 index 0000000..e483d71 --- /dev/null +++ b/Fix-typing-in-resource_agent-package.patch @@ -0,0 +1,147 @@ +From 5fe9bf04c46bfcbb4008d8d2a51b74c6c1693ec3 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 22 Aug 2023 18:25:34 +0800 +Subject: [PATCH] Fix typing in resource_agent package + +--- + mypy.ini | 10 +++++----- + pcs/lib/resource_agent/error.py | 4 ++-- + pcs/lib/resource_agent/facade.py | 12 +++++++----- + pcs/lib/resource_agent/types.py | 4 ++-- + 4 files changed, 16 insertions(+), 14 deletions(-) + +diff --git a/mypy.ini b/mypy.ini +index f34b513..a3f7d07 100644 +--- a/mypy.ini ++++ b/mypy.ini +@@ -48,19 +48,19 @@ disallow_untyped_defs = True + # this is a temporary solution for legacy code + disallow_untyped_defs = False + +-[mypy-pcs.common.ssl] ++[mypy-pcs.common.services.*] + disallow_untyped_defs = True + disallow_untyped_calls = True + +-[mypy-pcs.common.types] ++[mypy-pcs.common.ssl] + disallow_untyped_defs = True + disallow_untyped_calls = True + +-[mypy-pcs.common.validate] ++[mypy-pcs.common.types] + disallow_untyped_defs = True + disallow_untyped_calls = True + +-[mypy-pcs.common.services.*] ++[mypy-pcs.common.validate] + disallow_untyped_defs = True + disallow_untyped_calls = True + +@@ -113,7 +113,7 @@ disallow_untyped_defs = True + disallow_untyped_defs = True + disallow_untyped_calls = True + +-[mypy-pcs.lib.resource_agent] ++[mypy-pcs.lib.resource_agent.*] + disallow_untyped_defs = True + disallow_untyped_calls = True + +diff --git a/pcs/lib/resource_agent/error.py b/pcs/lib/resource_agent/error.py +index d417833..f61f196 100644 +--- a/pcs/lib/resource_agent/error.py ++++ b/pcs/lib/resource_agent/error.py +@@ -17,13 +17,13 @@ class AgentNameGuessFoundMoreThanOne(ResourceAgentError): + self.names_found = names_found + + @property +- def searched_name(self): ++ def searched_name(self) -> str: + return self.agent_name + + + class AgentNameGuessFoundNone(ResourceAgentError): + @property +- def searched_name(self): ++ def searched_name(self) -> str: + return self.agent_name + + +diff --git a/pcs/lib/resource_agent/facade.py b/pcs/lib/resource_agent/facade.py +index 4dbb59b..d5a28f3 100644 +--- a/pcs/lib/resource_agent/facade.py ++++ b/pcs/lib/resource_agent/facade.py +@@ -1,6 +1,6 @@ + from collections import defaultdict + from dataclasses import replace as dc_replace +-from typing import Dict, Iterable, List, Optional, Set ++from typing import Dict, Iterable, List, Optional, Set, cast + + from pcs.common import reports + from pcs.lib import validate +@@ -12,6 +12,7 @@ from .name import name_to_void_metadata + from .ocf_transform import ocf_version_to_ocf_unified + from .pcs_transform import get_additional_trace_parameters, ocf_unified_to_pcs + from .types import ( ++ FakeAgentName, + ResourceAgentMetadata, + ResourceAgentName, + ResourceAgentParameter, +@@ -154,7 +155,7 @@ class ResourceAgentFacade: + return validators + + @property +- def _validator_option_type(self): ++ def _validator_option_type(self) -> str: + return "stonith" if self.metadata.name.is_stonith else "resource" + + def _get_all_params_deprecated_by(self) -> Dict[str, Set[str]]: +@@ -185,7 +186,7 @@ class ResourceAgentFacadeFactory: + ) -> None: + self._runner = runner + self._report_processor = report_processor +- self._fenced_metadata = None ++ self._fenced_metadata: Optional[ResourceAgentMetadata] = None + + def facade_from_parsed_name( + self, name: ResourceAgentName +@@ -226,7 +227,7 @@ class ResourceAgentFacadeFactory: + ) + return ResourceAgentFacade(metadata, additional_parameters) + +- def _get_fenced_parameters(self): ++ def _get_fenced_parameters(self) -> List[ResourceAgentParameter]: + if self._fenced_metadata is None: + agent_name = ResourceAgentName( + const.FAKE_AGENT_STANDARD, None, const.PACEMAKER_FENCED +@@ -237,7 +238,8 @@ class ResourceAgentFacadeFactory: + parse_metadata( + agent_name, + load_fake_agent_metadata( +- self._runner, agent_name.type ++ self._runner, ++ cast(FakeAgentName, agent_name.type), + ), + ) + ) +diff --git a/pcs/lib/resource_agent/types.py b/pcs/lib/resource_agent/types.py +index ffa5a51..d045e01 100644 +--- a/pcs/lib/resource_agent/types.py ++++ b/pcs/lib/resource_agent/types.py +@@ -26,11 +26,11 @@ class ResourceAgentName: + return ":".join(filter(None, [self.standard, self.provider, self.type])) + + @property +- def is_pcmk_fake_agent(self): ++ def is_pcmk_fake_agent(self) -> bool: + return self.standard == _FAKE_AGENT_STANDARD + + @property +- def is_stonith(self): ++ def is_stonith(self) -> bool: + return self.standard == "stonith" + + def to_dto(self) -> ResourceAgentNameDto: +-- +2.41.0 + diff --git a/fix-pcs-config-checkpoint-diff-command.patch b/fix-pcs-config-checkpoint-diff-command.patch new file mode 100644 index 0000000..00ce964 --- /dev/null +++ b/fix-pcs-config-checkpoint-diff-command.patch @@ -0,0 +1,106 @@ +From 81cefe083678b88ca475c0d3f0eea962ed3a5035 Mon Sep 17 00:00:00 2001 +From: bizhiyuan +Date: Thu, 31 Aug 2023 04:25:52 +0800 +Subject: [PATCH] fix pcs config checkpoint diff command + +--- + CHANGELOG.md | 5 ++++- + pcs/cli/common/lib_wrapper.py | 13 +------------ + pcs/config.py | 3 +++ + 3 files changed, 8 insertions(+), 13 deletions(-) + +diff --git a/CHANGELOG.md b/CHANGELOG.md +index 9741670..7949064 100644 +--- a/CHANGELOG.md ++++ b/CHANGELOG.md +@@ -15,6 +15,9 @@ + - Multiple improvements of `pcs resource move` command ([rhbz#1996062]) + - Pcs no longer creates Pacemaker-1.x CIB when `-f` is used, so running `pcs + cluster cib-upgrade` manually is not needed ([rhbz#2022463]) ++- Fix displaying differences between configuration checkpoints in ++ `pcs config checkpoint diff` command ([rhbz#2175881]) ++ + + [ghissue#441]: https://github.com/ClusterLabs/pcs/issues/441 + [ghpull#431]: https://github.com/ClusterLabs/pcs/pull/431 +@@ -24,7 +27,7 @@ + [rhbz#2028902]: https://bugzilla.redhat.com/show_bug.cgi?id=2028902 + [rhbz#2033248]: https://bugzilla.redhat.com/show_bug.cgi?id=2033248 + [rhbz#2036633]: https://bugzilla.redhat.com/show_bug.cgi?id=2036633 +- ++[rhbz#2175881]: https://bugzilla.redhat.com/show_bug.cgi?id=2175881 + + ## [0.11.1] - 2021-11-30 + +diff --git a/pcs/cli/common/lib_wrapper.py b/pcs/cli/common/lib_wrapper.py +index 6600497..c6c9dba 100644 +--- a/pcs/cli/common/lib_wrapper.py ++++ b/pcs/cli/common/lib_wrapper.py +@@ -1,6 +1,5 @@ + import logging + from collections import namedtuple +-from typing import Dict, Any + + from pcs.cli.common import middleware + from pcs.lib.commands import ( +@@ -34,10 +33,6 @@ from pcs.lib.commands.constraint import ( + from pcs.lib.env import LibraryEnvironment + + +-# Note: not properly typed +-_CACHE: Dict[Any, Any] = {} +- +- + def wrapper(dictionary): + return namedtuple("wrapper", dictionary.keys())(**dictionary) + +@@ -104,12 +99,6 @@ def bind_all(env, run_with_middleware, dictionary): + ) + + +-def get_module(env, middleware_factory, name): +- if name not in _CACHE: +- _CACHE[name] = load_module(env, middleware_factory, name) +- return _CACHE[name] +- +- + def load_module(env, middleware_factory, name): + # pylint: disable=too-many-return-statements, too-many-branches + if name == "acl": +@@ -518,4 +507,4 @@ class Library: + self.middleware_factory = middleware_factory + + def __getattr__(self, name): +- return get_module(self.env, self.middleware_factory, name) ++ return load_module(self.env, self.middleware_factory, name) +diff --git a/pcs/config.py b/pcs/config.py +index 32f6a50..83884ec 100644 +--- a/pcs/config.py ++++ b/pcs/config.py +@@ -678,6 +678,7 @@ def _checkpoint_to_lines(lib, checkpoint_number): + orig_usefile = utils.usefile + orig_filename = utils.filename + orig_middleware = lib.middleware_factory ++ orig_env = lib.env + # configure old code to read the CIB from a file + utils.usefile = True + utils.filename = os.path.join( +@@ -687,6 +688,7 @@ def _checkpoint_to_lines(lib, checkpoint_number): + lib.middleware_factory = orig_middleware._replace( + cib=middleware.cib(utils.filename, utils.touch_cib_file) + ) ++ lib.env = utils.get_cli_env() + # export the CIB to text + result = False, [] + if os.path.isfile(utils.filename): +@@ -695,6 +697,7 @@ def _checkpoint_to_lines(lib, checkpoint_number): + utils.usefile = orig_usefile + utils.filename = orig_filename + lib.middleware_factory = orig_middleware ++ lib.env = orig_env + return result + + +-- +2.27.0 + diff --git a/fix-pcs-quorum-device-remove.patch b/fix-pcs-quorum-device-remove.patch new file mode 100644 index 0000000..45b079f --- /dev/null +++ b/fix-pcs-quorum-device-remove.patch @@ -0,0 +1,25 @@ +From 0b2dc6cc49715d8ae006b9f6877324e76ea9a271 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Mon, 4 Sep 2023 18:20:31 +0800 +Subject: [PATCH] fix pcs quorum device remove + +--- + pcsd/remote.rb | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pcsd/remote.rb b/pcsd/remote.rb +index 9dabdd0..ed5f347 100644 +--- a/pcsd/remote.rb ++++ b/pcsd/remote.rb +@@ -1987,7 +1987,7 @@ def qdevice_net_client_destroy(param, request, auth_user) + end + stdout, stderr, retval = run_cmd( + auth_user, +- PCS, '--' 'qdevice', 'net-client', 'destroy' ++ PCS, '--', 'qdevice', 'net-client', 'destroy' + ) + if retval != 0 + return [400, stderr.join('')] +-- +2.39.1 + diff --git a/fix-serving-static-files.patch b/fix-serving-static-files.patch new file mode 100644 index 0000000..72dcf27 --- /dev/null +++ b/fix-serving-static-files.patch @@ -0,0 +1,33 @@ +From 272009b4e3582f9b7a045c3f4ee867f9e943ee9e Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Mon, 27 Nov 2023 09:34:46 +0800 +Subject: [PATCH] fix serving static files + +--- + pcs/daemon/app/ui.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pcs/daemon/app/ui.py b/pcs/daemon/app/ui.py +index cad6824..11440a0 100644 +--- a/pcs/daemon/app/ui.py ++++ b/pcs/daemon/app/ui.py +@@ -67,14 +67,14 @@ class Logout(app_session.Mixin, AjaxMixin, BaseHandler): + + class StaticFileMayBe(StaticFile): + # pylint: disable=abstract-method +- def get(self, *args, **kwargs): ++ async def get(self, *args, **kwargs): + # pylint: disable=signature-differs + # pylint: disable=invalid-overridden-method + if not os.path.isdir(str(self.root)): + # spa is probably not installed + self.set_status(404, "Not Found") + return None +- return super().get(*args, **kwargs) ++ return await super().get(*args, **kwargs) + + + def get_routes( +-- +2.33.0 + diff --git a/improve-error-messages-in-pcs-resource-move.patch b/improve-error-messages-in-pcs-resource-move.patch new file mode 100644 index 0000000..7fa718a --- /dev/null +++ b/improve-error-messages-in-pcs-resource-move.patch @@ -0,0 +1,484 @@ +From f240edb5dc9637d7fbd0a134fb45610fba6a3950 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Wed, 25 Oct 2023 14:18:19 +0800 +Subject: [PATCH] improve error messages in pcs resource move + +--- + CHANGELOG.md | 3 + + pcs/cli/reports/messages.py | 13 ++ + pcs/common/reports/messages.py | 17 ++- + pcs/lib/commands/resource.py | 116 ++++++++++++------ + pcs/pcs.8.in | 2 +- + pcs/usage.py | 8 +- + pcs_test/tier0/cli/reports/test_messages.py | 49 ++++++++ + .../tier0/common/reports/test_messages.py | 34 ++++- + .../resource/test_resource_move_autoclean.py | 8 ++ + 9 files changed, 206 insertions(+), 44 deletions(-) + +diff --git a/CHANGELOG.md b/CHANGELOG.md +index c6007ac..9a32655 100644 +--- a/CHANGELOG.md ++++ b/CHANGELOG.md +@@ -19,11 +19,14 @@ + `pcs config checkpoint diff` command ([rhbz#2175881]) + - Pcs daemon was allowing expired accounts, and accounts with expired + passwords to login when using PAM auth. ([huntr#220307]) ++- Improved error messages and documentation of `pcs resource move` command ++ ([rhbz#2219554]) + + [ghissue#441]: https://github.com/ClusterLabs/pcs/issues/441 + [ghpull#431]: https://github.com/ClusterLabs/pcs/pull/431 + [rhbz#1996062]: https://bugzilla.redhat.com/show_bug.cgi?id=1996062 + [rhbz#2019836]: https://bugzilla.redhat.com/show_bug.cgi?id=2019836 ++[rhbz#2219554]: https://bugzilla.redhat.com/show_bug.cgi?id=2219554 + [rhbz#2022463]: https://bugzilla.redhat.com/show_bug.cgi?id=2022463 + [rhbz#2028902]: https://bugzilla.redhat.com/show_bug.cgi?id=2028902 + [rhbz#2033248]: https://bugzilla.redhat.com/show_bug.cgi?id=2033248 +diff --git a/pcs/cli/reports/messages.py b/pcs/cli/reports/messages.py +index 892ec15..5e1741b 100644 +--- a/pcs/cli/reports/messages.py ++++ b/pcs/cli/reports/messages.py +@@ -516,6 +516,19 @@ class InvalidStonithAgentName(CliReportMessageCustom): + ) + + ++class ResourceMoveAutocleanSimulationFailure(CliReportMessageCustom): ++ _obj: messages.ResourceMoveAutocleanSimulationFailure ++ ++ @property ++ def message(self) -> str: ++ if not self._obj.move_constraint_left_in_cib: ++ return self._obj.message ++ node = format_optional(self._obj.node, " {}") ++ return ( ++ f"{self._obj.message} Run 'pcs resource clear " ++ f"{self._obj.resource_id}{node}' to remove the constraint." ++ ) ++ + def _create_report_msg_map() -> Dict[str, type]: + result: Dict[str, type] = {} + for report_msg_cls in get_all_subclasses(CliReportMessageCustom): +diff --git a/pcs/common/reports/messages.py b/pcs/common/reports/messages.py +index 37c79ba..c183e96 100644 +--- a/pcs/common/reports/messages.py ++++ b/pcs/common/reports/messages.py +@@ -6195,19 +6195,32 @@ class ResourceMoveAutocleanSimulationFailure(ReportItemMessage): + resource_id -- id of the resource to be moved + others_affected -- True if also other resource would be affected, False + otherwise ++ node -- target node the resource should be moved to ++ move_constraint_left_in_cib -- move has happened and the failure occurred ++ when trying to remove the move constraint from the live cib + """ + + resource_id: str + others_affected: bool ++ node: Optional[str] = None ++ move_constraint_left_in_cib: bool = False + _code = codes.RESOURCE_MOVE_AUTOCLEAN_SIMULATION_FAILURE + + @property + def message(self) -> str: +- return ( ++ template = ( + "Unable to ensure that moved resource '{resource_id}'{others} will " + "stay on the same node after a constraint used for moving it is " + "removed." +- ).format( ++ ) ++ if self.move_constraint_left_in_cib: ++ template += ( ++ " The constraint to move the resource has not been removed " ++ "from configuration. Consider removing it manually. Be aware " ++ "that removing the constraint may cause resources to move " ++ "to other nodes." ++ ) ++ return template.format( + resource_id=self.resource_id, + others=" or other resources" if self.others_affected else "", + ) +diff --git a/pcs/lib/commands/resource.py b/pcs/lib/commands/resource.py +index 82ce73e..39b24f0 100644 +--- a/pcs/lib/commands/resource.py ++++ b/pcs/lib/commands/resource.py +@@ -1602,6 +1602,14 @@ def _nodes_exist_reports( + for node_name in (set(node_names) - existing_node_names) + ] + ++class ResourceMoveAutocleanSimulationFailure(Exception): ++ def __init__(self, other_resources_affected: bool): ++ super().__init__() ++ self._other_resources_affected = other_resources_affected ++ ++ @property ++ def other_resources_affected(self) -> bool: ++ return self._other_resources_affected + + def move_autoclean( + env: LibraryEnvironment, +@@ -1624,7 +1632,9 @@ def move_autoclean( + strict -- if True affecting other resources than the specified resource + will cause failure. If False affecting other resources is alowed. + """ ++ # pylint: disable=too-many-branches + # pylint: disable=too-many-locals ++ # pylint: disable=too-many-statements + wait_timeout = max(wait_timeout, 0) + if not env.is_cib_live: + raise LibraryError( +@@ -1655,6 +1665,8 @@ def move_autoclean( + reports.messages.CannotMoveResourceNotRunning(resource_id) + ) + ) ++ # add a move constraint to a temporary cib and get a cib diff which adds ++ # the move constraint + with get_tmp_cib(env.report_processor, cib_xml) as rsc_moved_cib_file: + stdout, stderr, retval = resource_move( + env.cmd_runner(dict(CIB_file=rsc_moved_cib_file.name)), +@@ -1676,6 +1688,8 @@ def move_autoclean( + add_constraint_cib_diff = diff_cibs_xml( + env.cmd_runner(), env.report_processor, cib_xml, rsc_moved_cib_xml + ) ++ # clear the move constraint from the temporary cib and get a cib diff which ++ # removes the move constraint + with get_tmp_cib( + env.report_processor, rsc_moved_cib_xml + ) as rsc_moved_constraint_cleared_cib_file: +@@ -1703,17 +1717,18 @@ def move_autoclean( + rsc_moved_cib_xml, + constraint_removed_cib, + ) +- ++ # if both the diffs are no-op, nothing needs to be done + if not (add_constraint_cib_diff and remove_constraint_cib_diff): + env.report_processor.report( + reports.ReportItem.info(reports.messages.NoActionNecessary()) + ) + return +- ++ # simulate applying the diff which adds the move constraint + _, move_transitions, after_move_simulated_cib = simulate_cib( + env.cmd_runner(), get_cib(rsc_moved_cib_xml) + ) + if strict: ++ # check if other resources would be affected + resources_affected_by_move = ( + simulate_tools.get_resources_from_operations( + simulate_tools.get_operations_from_transitions( +@@ -1730,16 +1745,37 @@ def move_autoclean( + ) + ) + ) +- _ensure_resource_moved_and_not_moved_back( +- env.cmd_runner, +- env.report_processor, +- etree_to_str(after_move_simulated_cib), +- remove_constraint_cib_diff, +- resource_id, +- strict, +- resource_state_before, +- node, +- ) ++ # verify that: ++ # - a cib with added move constraint causes the resource to move by ++ # comparing the original status of the resource with a status computed ++ # from the cib with the added constraint ++ # - applying the diff which removes the move constraint won't trigger ++ # moving the resource (or other resources) around ++ try: ++ _ensure_resource_moved_and_not_moved_back( ++ env.cmd_runner, ++ env.report_processor, ++ etree_to_str(after_move_simulated_cib), ++ remove_constraint_cib_diff, ++ resource_id, ++ strict, ++ resource_state_before, ++ node, ++ ) ++ except ResourceMoveAutocleanSimulationFailure as e: ++ raise LibraryError( ++ reports.ReportItem.error( ++ reports.messages.ResourceMoveAutocleanSimulationFailure( ++ resource_id, ++ e.other_resources_affected, ++ node=node, ++ move_constraint_left_in_cib=False, ++ ) ++ ) ++ ) from e ++ ++ # apply the diff which adds the move constraint to the live cib and wait ++ # for the cluster to settle + push_cib_diff_xml(env.cmd_runner(), add_constraint_cib_diff) + env.report_processor.report( + ReportItem.info( +@@ -1747,16 +1783,36 @@ def move_autoclean( + ) + ) + env.wait_for_idle(wait_timeout) +- _ensure_resource_moved_and_not_moved_back( +- env.cmd_runner, +- env.report_processor, +- get_cib_xml(env.cmd_runner()), +- remove_constraint_cib_diff, +- resource_id, +- strict, +- resource_state_before, +- node, +- ) ++ # verify that: ++ # - the live cib (now containing the move constraint) causes the resource ++ # to move by comparing the original status of the resource with a status ++ # computed from the live cib ++ # - applying the diff which removes the move constraint won't trigger ++ # moving the resource (or other resources) around ++ try: ++ _ensure_resource_moved_and_not_moved_back( ++ env.cmd_runner, ++ env.report_processor, ++ get_cib_xml(env.cmd_runner()), ++ remove_constraint_cib_diff, ++ resource_id, ++ strict, ++ resource_state_before, ++ node, ++ ) ++ except ResourceMoveAutocleanSimulationFailure as e: ++ raise LibraryError( ++ reports.ReportItem.error( ++ reports.messages.ResourceMoveAutocleanSimulationFailure( ++ resource_id, ++ e.other_resources_affected, ++ node=node, ++ move_constraint_left_in_cib=True, ++ ) ++ ) ++ ) from e ++ # apply the diff which removes the move constraint to the live cib and wait ++ # for the cluster to settle + push_cib_diff_xml(env.cmd_runner(), remove_constraint_cib_diff) + env.report_processor.report( + ReportItem.info( +@@ -1822,13 +1878,7 @@ def _ensure_resource_moved_and_not_moved_back( + ) + if strict: + if clean_operations: +- raise LibraryError( +- reports.ReportItem.error( +- reports.messages.ResourceMoveAutocleanSimulationFailure( +- resource_id, others_affected=True +- ) +- ) +- ) ++ raise ResourceMoveAutocleanSimulationFailure(True) + else: + if any( + rsc == resource_id +@@ -1836,13 +1886,7 @@ def _ensure_resource_moved_and_not_moved_back( + clean_operations + ) + ): +- raise LibraryError( +- reports.ReportItem.error( +- reports.messages.ResourceMoveAutocleanSimulationFailure( +- resource_id, others_affected=False +- ) +- ) +- ) ++ raise ResourceMoveAutocleanSimulationFailure(False) + + + def ban(env, resource_id, node=None, master=False, lifetime=None, wait=False): +diff --git a/pcs/pcs.8.in b/pcs/pcs.8.in +index 94514c1..8f4b647 100644 +--- a/pcs/pcs.8.in ++++ b/pcs/pcs.8.in +@@ -152,7 +152,7 @@ debug\-monitor [\fB\-\-full\fR] + This command will force the specified resource to be monitored on this node ignoring the cluster recommendations and print the output from monitoring the resource. Using \fB\-\-full\fR will give more detailed output. This is mainly used for debugging resources that fail to be monitored. + .TP + move [destination node] [\fB\-\-promoted\fR] [\fB\-\-strict\fR] [\fB\-\-wait\fR[=n]] +-Move the resource off the node it is currently running on. This is achieved by creating a \-INFINITY location constraint to ban the node. If destination node is specified the resource will be moved to that node by creating an INFINITY location constraint to prefer the destination node. The constraint needed for moving the resource will be automatically removed once the resource is running on it's new location. The command will fail in case it is not possible to verify that the resource will not be moved back after deleting the constraint. ++Move the resource off the node it is currently running on. This is achieved by creating a \-INFINITY location constraint to ban the node. If destination node is specified the resource will be moved to that node by creating an INFINITY location constraint to prefer the destination node. The constraint needed for moving the resource will be automatically removed once the resource is running on its new location. The command will fail in case it is not possible to verify that the resource will not be moved back after deleting the constraint. If this happens after the location constraint has been created, the constraint will be left in the configuration. + + If \fB\-\-strict\fR is specified, the command will also fail if other resources would be affected. + +diff --git a/pcs/usage.py b/pcs/usage.py +index bc88591..aab6a78 100644 +--- a/pcs/usage.py ++++ b/pcs/usage.py +@@ -369,9 +369,11 @@ Commands: + If destination node is specified the resource will be moved to that + node by creating an INFINITY location constraint to prefer the + destination node. The constraint needed for moving the resource will be +- automatically removed once the resource is running on it's new +- location. The command will fail in case it is not possible to verify +- that the resource will not be moved back after deleting the constraint. ++ automatically removed once the resource is running on its new location. ++ The command will fail in case it is not possible to verify that the ++ resource will not be moved back after deleting the constraint. If this ++ happens after the location constraint has been created, the constraint ++ will be left in the configuration. + + If --strict is specified, the command will also fail if other resources + would be affected. +diff --git a/pcs_test/tier0/cli/reports/test_messages.py b/pcs_test/tier0/cli/reports/test_messages.py +index 6671021..ac8625c 100644 +--- a/pcs_test/tier0/cli/reports/test_messages.py ++++ b/pcs_test/tier0/cli/reports/test_messages.py +@@ -618,3 +618,52 @@ class StonithRestartlessUpdateUnableToPerform(CliReportMessageTestBase): + report_msg, + f"{report_msg.message}, please use command 'pcs stonith update' instead", + ) ++ ++class ResourceMoveAutocleanSimulationFailure(CliReportMessageTestBase): ++ def test_constraint_not_created(self): ++ self.assert_message( ++ messages.ResourceMoveAutocleanSimulationFailure( ++ "R1", others_affected=True ++ ), ++ ( ++ "Unable to ensure that moved resource 'R1' or other resources " ++ "will stay on the same node after a constraint used for moving " ++ "it is removed." ++ ), ++ ) ++ ++ def test_without_node(self): ++ self.assert_message( ++ messages.ResourceMoveAutocleanSimulationFailure( ++ "R1", others_affected=True, move_constraint_left_in_cib=True ++ ), ++ ( ++ "Unable to ensure that moved resource 'R1' or other resources " ++ "will stay on the same node after a constraint used for moving " ++ "it is removed." ++ " The constraint to move the resource has not been removed " ++ "from configuration. Consider removing it manually. Be aware " ++ "that removing the constraint may cause resources to move to " ++ "other nodes." ++ " Run 'pcs resource clear R1' to remove the constraint." ++ ), ++ ) ++ ++ def test_with_node(self): ++ self.assert_message( ++ messages.ResourceMoveAutocleanSimulationFailure( ++ "R1", ++ others_affected=False, ++ node="node1", ++ move_constraint_left_in_cib=True, ++ ), ++ ( ++ "Unable to ensure that moved resource 'R1' will stay on the " ++ "same node after a constraint used for moving it is removed." ++ " The constraint to move the resource has not been removed " ++ "from configuration. Consider removing it manually. Be aware " ++ "that removing the constraint may cause resources to move to " ++ "other nodes." ++ " Run 'pcs resource clear R1 node1' to remove the constraint." ++ ), ++ ) +\ No newline at end of file +diff --git a/pcs_test/tier0/common/reports/test_messages.py b/pcs_test/tier0/common/reports/test_messages.py +index a56ef38..7b1b799 100644 +--- a/pcs_test/tier0/common/reports/test_messages.py ++++ b/pcs_test/tier0/common/reports/test_messages.py +@@ -4542,7 +4542,7 @@ class ResourceMoveAffectsOtherResources(NameBuildTest): + + + class ResourceMoveAutocleanSimulationFailure(NameBuildTest): +- def test_success(self): ++ def test_simulation(self): + self.assert_message_from_report( + ( + "Unable to ensure that moved resource 'R1' will stay on the " +@@ -4553,7 +4553,7 @@ class ResourceMoveAutocleanSimulationFailure(NameBuildTest): + ), + ) + +- def test_others_affected(self): ++ def test_simulation_others_affected(self): + self.assert_message_from_report( + ( + "Unable to ensure that moved resource 'R1' or other resources " +@@ -4565,6 +4565,36 @@ class ResourceMoveAutocleanSimulationFailure(NameBuildTest): + ), + ) + ++ def test_live(self): ++ self.assert_message_from_report( ++ ( ++ "Unable to ensure that moved resource 'R1' will stay on the " ++ "same node after a constraint used for moving it is removed." ++ " The constraint to move the resource has not been removed " ++ "from configuration. Consider removing it manually. Be aware " ++ "that removing the constraint may cause resources to move to " ++ "other nodes." ++ ), ++ reports.ResourceMoveAutocleanSimulationFailure( ++ "R1", others_affected=False, move_constraint_left_in_cib=True ++ ), ++ ) ++ ++ def test_live_others_affected(self): ++ self.assert_message_from_report( ++ ( ++ "Unable to ensure that moved resource 'R1' or other resources " ++ "will stay on the same node after a constraint used for moving " ++ "it is removed." ++ " The constraint to move the resource has not been removed " ++ "from configuration. Consider removing it manually. Be aware " ++ "that removing the constraint may cause resources to move to " ++ "other nodes." ++ ), ++ reports.ResourceMoveAutocleanSimulationFailure( ++ "R1", others_affected=True, move_constraint_left_in_cib=True ++ ), ++ ) + + class ParseErrorJsonFile(NameBuildTest): + def test_success(self): +diff --git a/pcs_test/tier0/lib/commands/resource/test_resource_move_autoclean.py b/pcs_test/tier0/lib/commands/resource/test_resource_move_autoclean.py +index 90ed2d8..6e5c286 100644 +--- a/pcs_test/tier0/lib/commands/resource/test_resource_move_autoclean.py ++++ b/pcs_test/tier0/lib/commands/resource/test_resource_move_autoclean.py +@@ -1261,6 +1261,8 @@ class MoveAutocleanFailures(MoveAutocleanCommonSetup): + reports.codes.RESOURCE_MOVE_AUTOCLEAN_SIMULATION_FAILURE, + resource_id=self.resource_id, + others_affected=False, ++ node=None, ++ move_constraint_left_in_cib=False, + ) + ], + expected_in_processor=False, +@@ -1292,6 +1294,8 @@ class MoveAutocleanFailures(MoveAutocleanCommonSetup): + reports.codes.RESOURCE_MOVE_AUTOCLEAN_SIMULATION_FAILURE, + resource_id=self.resource_id, + others_affected=True, ++ node=None, ++ move_constraint_left_in_cib=False, + ) + ], + expected_in_processor=False, +@@ -1324,6 +1328,8 @@ class MoveAutocleanFailures(MoveAutocleanCommonSetup): + reports.codes.RESOURCE_MOVE_AUTOCLEAN_SIMULATION_FAILURE, + resource_id=self.resource_id, + others_affected=False, ++ node=None, ++ move_constraint_left_in_cib=True, + ) + ], + expected_in_processor=False, +@@ -1355,6 +1361,8 @@ class MoveAutocleanFailures(MoveAutocleanCommonSetup): + reports.codes.RESOURCE_MOVE_AUTOCLEAN_SIMULATION_FAILURE, + resource_id=self.resource_id, + others_affected=True, ++ node=None, ++ move_constraint_left_in_cib=True, + ) + ], + expected_in_processor=False, +-- +2.33.0 + diff --git a/pcs.spec b/pcs.spec index 6bbde61..de666ea 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.2 -Release: 2 +Release: 10 License: GPLv2 and BSD-2-Clause and ASL 2.0 and MIT URL: https://github.com/ClusterLabs/pcs Summary: Pacemaker Configuration System @@ -41,6 +41,15 @@ Patch1: fix-backend-parameter-all-in-cluster-destroy.patch Patch2: bz2093935-01-Python-3.11-related-fixes.patch Patch3: Support-for-openEuler.patch Patch4: Adjust-regex-to-support-json-2.6.3-error.patch +Patch5: Fix-typing-in-resource_agent-package.patch +Patch6: fix-pcs-config-checkpoint-diff-command.patch +#https://github.com/ClusterLabs/pcs/pull/522 +Patch7: fix-pcs-quorum-device-remove.patch +Patch8: tests-fix-datetime-race-condition.patch +Patch9: Fix-CVE-2022-1049.patch +Patch10: Fix-CVE-2022-2735.patch +Patch11: improve-error-messages-in-pcs-resource-move.patch +Patch12: fix-serving-static-files.patch # git for patches BuildRequires: git-core BuildRequires: make @@ -403,6 +412,30 @@ run_all_tests %license pyagentx_LICENSE.txt %changelog +* Thu Nov 23 2023 bixiaoyan - 0.11.2-10 +- Fix serving static files + +* Wed Oct 25 2023 zouzhimin - 0.11.2-9 +- improve error messages in pcs resource move + +* Fri Oct 20 2023 bizhiyuan - 0.11.2-8 +- Fix-CVE-2022-2735 + +* Thu Oct 19 2023 bizhiyuan - 0.11.2-7 +- Fix CVE-2022-1049 + +* Wed Sep 06 2023 bizhiyuan - 0.11.2-6 +- fix datetime race condition + +* Tue Sep 05 2023 zouzhimin - 0.11.2-5 +- Fix pcs quorum device remove + +* Thu Aug 31 2023 bizhiyuan - 0.11.2-4 +- Fix pcs config checkpoint diff command + +* Wed Aug 23 2023 jiangxinyu - 0.11.2-3 +- Fix typing in resource_agent package + * Mon Aug 07 2023 bizhiyuan - 0.11.2-2 - Adjust regex pattern for ruby to support json 2.6.3 build error diff --git a/tests-fix-datetime-race-condition.patch b/tests-fix-datetime-race-condition.patch new file mode 100644 index 0000000..ad14a94 --- /dev/null +++ b/tests-fix-datetime-race-condition.patch @@ -0,0 +1,27 @@ +From b8e186f82cafea79e0ebf9beb1627ce0c62a8b16 Mon Sep 17 00:00:00 2001 +From: bizhiyuan +Date: Wed, 6 Sep 2023 01:02:45 +0800 +Subject: [PATCH] tests: fix datetime race condition + +--- + pcs_test/tier1/legacy/test_constraints.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/pcs_test/tier1/legacy/test_constraints.py b/pcs_test/tier1/legacy/test_constraints.py +index 963fbe8..90c8d7f 100644 +--- a/pcs_test/tier1/legacy/test_constraints.py ++++ b/pcs_test/tier1/legacy/test_constraints.py +@@ -4709,7 +4709,9 @@ class LocationAdd(ConstraintEffect): + + @skip_unless_crm_rule() + class ExpiredConstraints(ConstraintBaseTest): +- _tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).strftime( ++ # Setting tomorrow to the day after tomorrow in case the tests run close to ++ # midnight. ++ _tomorrow = (datetime.date.today() + datetime.timedelta(days=2)).strftime( + "%Y-%m-%d" + ) + +-- +2.27.0 +