Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2022-09-28 17:51:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Wed Sep 28 17:51:53 2022 rev:261 rq:1006546 version:4.4.1+20220928.ded85d0a Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2022-09-27 20:14:10.997860443 +0200 +++ /work/SRC/openSUSE:Factory/.crmsh.new.2275/crmsh.changes 2022-09-28 17:51:56.243254489 +0200 @@ -1,0 +2,8 @@ +Wed Sep 28 00:47:23 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20220928.ded85d0a: + * Dev: behave: Add functional test based on previous changes + * Dev: unittest: Adjust unit test based on previous changes + * Dev: bootstrap: Adjust cluster properties including priority-fencing-delay + +------------------------------------------------------------------- Old: ---- crmsh-4.4.1+20220923.9651e0fa.tar.bz2 New: ---- crmsh-4.4.1+20220928.ded85d0a.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.E2nAMZ/_old 2022-09-28 17:51:56.771255551 +0200 +++ /var/tmp/diff_new_pack.E2nAMZ/_new 2022-09-28 17:51:56.779255567 +0200 @@ -36,7 +36,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0-or-later Group: %{pkg_group} -Version: 4.4.1+20220923.9651e0fa +Version: 4.4.1+20220928.ded85d0a Release: 0 URL: http://crmsh.github.io Source0: %{name}-%{version}.tar.bz2 ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.E2nAMZ/_old 2022-09-28 17:51:56.827255664 +0200 +++ /var/tmp/diff_new_pack.E2nAMZ/_new 2022-09-28 17:51:56.827255664 +0200 @@ -9,7 +9,7 @@ </service> <service name="tar_scm"> <param name="url">https://github.com/ClusterLabs/crmsh.git</param> - <param name="changesrevision">6236df2587ced94135a27867f11e442090b8d742</param> + <param name="changesrevision">37d4b63487534aa9de6fbfefb8e87812bfad14be</param> </service> </servicedata> (No newline at EOF) ++++++ crmsh-4.4.1+20220923.9651e0fa.tar.bz2 -> crmsh-4.4.1+20220928.ded85d0a.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/crmsh/bootstrap.py new/crmsh-4.4.1+20220928.ded85d0a/crmsh/bootstrap.py --- old/crmsh-4.4.1+20220923.9651e0fa/crmsh/bootstrap.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/crmsh/bootstrap.py 2022-09-28 02:31:20.000000000 +0200 @@ -1376,7 +1376,7 @@ qdevice_inst.config_and_start_qdevice() if _context.stage == "qdevice": - adjust_pcmk_delay_max_and_stonith_timeout() + adjust_properties() def init(): @@ -1788,7 +1788,7 @@ # attempt to join the cluster failed) init_cluster_local() - adjust_pcmk_delay_max_and_stonith_timeout() + adjust_properties() with logger_utils.status_long("Reloading cluster configuration"): @@ -1844,6 +1844,39 @@ utils.disable_service("corosync-qdevice.service") +def adjust_priority_in_rsc_defaults(is_2node_wo_qdevice): + """ + Adjust priority in rsc_defaults + + Set priority=1 when current cluster is 2 nodes without qdevice; + else set priority=0 + """ + if is_2node_wo_qdevice: + utils.set_property("priority", 1, property_type="rsc_defaults", conditional=True) + else: + utils.set_property("priority", 0, property_type="rsc_defaults") + + +def adjust_priority_fencing_delay(is_2node_wo_qdevice): + """ + Adjust priority-fencing-delay + + When pcmk_delay_max is set in fence agent, + and the current cluster is 2 nodes without qdevice, + set priority-fencing-delay=2*pcmk_delay_max + """ + out = utils.get_stdout_or_raise_error("crm configure show related:stonith") + if not out: + return + pcmk_delay_max_v_list = re.findall("pcmk_delay_max=(\w+)", out) + if pcmk_delay_max_v_list: + max_value = max([int(utils.crm_msec(v)/1000) for v in pcmk_delay_max_v_list]) + if pcmk_delay_max_v_list and is_2node_wo_qdevice: + utils.set_property("priority-fencing-delay", 2*max_value, conditional=True) + else: + utils.set_property("priority-fencing-delay", 0) + + def start_qdevice_on_join_node(seed_host): """ Doing qdevice certificate process and start qdevice service on join node @@ -1922,7 +1955,7 @@ decrease_expected_votes() - adjust_pcmk_delay_max_and_stonith_timeout() + adjust_properties() logger.info("Propagating configuration changes across the remaining nodes") csync2_update(CSYNC2_CFG) @@ -2169,7 +2202,7 @@ else: logger.warning("To remove qdevice service, need to restart cluster service manually on each node") - adjust_pcmk_delay_max_and_stonith_timeout() + adjust_properties() def bootstrap_remove(context): @@ -2408,7 +2441,7 @@ return STONITH_TIMEOUT_DEFAULT + corosync.token_and_consensus_timeout() -def adjust_pcmk_delay_max(): +def adjust_pcmk_delay_max(is_2node_wo_qdevice): """ For each fence agent, add parameter pcmk_delay_max when cluster is two-node cluster without qdevice @@ -2416,7 +2449,7 @@ """ cib_factory.refresh() - if utils.is_2node_cluster_without_qdevice(): + if is_2node_wo_qdevice: for res in cib_factory.fence_id_list_without_pcmk_delay(): cmd = "crm resource param {} set pcmk_delay_max {}s".format(res, PCMK_DELAY_MAX) utils.get_stdout_or_raise_error(cmd) @@ -2438,20 +2471,28 @@ else: value = get_stonith_timeout_generally_expected() if value: - utils.set_property_conditionally("stonith-timeout", value) + utils.set_property("stonith-timeout", value, conditional=True) -def adjust_pcmk_delay_max_and_stonith_timeout(): +def adjust_properties(): """ - Adjust pcmk_delay_max and stonith-timeout for all configured fence agents + Adjust properties for the cluster: + - pcmk_delay_max + - stonith-timeout + - priority in rsc_defaults + - priority-fencing-delay Call it when: - node join/remove - - qdevice add/remove + - add qdevice via stage + - remove qdevice - add sbd via stage """ if not utils.service_is_active("pacemaker.service"): return - adjust_pcmk_delay_max() + is_2node_wo_qdevice = utils.is_2node_cluster_without_qdevice() + adjust_pcmk_delay_max(is_2node_wo_qdevice) adjust_stonith_timeout() + adjust_priority_in_rsc_defaults(is_2node_wo_qdevice) + adjust_priority_fencing_delay(is_2node_wo_qdevice) # EOF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/crmsh/cibconfig.py new/crmsh-4.4.1+20220928.ded85d0a/crmsh/cibconfig.py --- old/crmsh-4.4.1+20220923.9651e0fa/crmsh/cibconfig.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/crmsh/cibconfig.py 2022-09-28 02:31:20.000000000 +0200 @@ -2905,7 +2905,7 @@ if x.node.get("class") != "stonith": continue for c in x.node.xpath('.//nvpair'): - if c.get("name") == "pcmk_delay_max" and int(c.get("value").strip('s')) > 0: + if c.get("name") == "pcmk_delay_max" and utils.crm_msec(c.get("value")) > 0: id_list.append(x.obj_id) break return id_list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/crmsh/ocfs2.py new/crmsh-4.4.1+20220928.ded85d0a/crmsh/ocfs2.py --- old/crmsh-4.4.1+20220923.9651e0fa/crmsh/ocfs2.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/crmsh/ocfs2.py 2022-09-28 02:31:20.000000000 +0200 @@ -301,7 +301,7 @@ no_quorum_policy_value = utils.get_property("no-quorum-policy") if not no_quorum_policy_value or no_quorum_policy_value != "freeze": - utils.set_property(no_quorum_policy="freeze") + utils.set_property("no-quorum-policy", "freeze") logger.info(" 'no-quorum-policy' is changed to \"freeze\"") if self.use_cluster_lvm2: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/crmsh/qdevice.py new/crmsh-4.4.1+20220928.ded85d0a/crmsh/qdevice.py --- old/crmsh-4.4.1+20220923.9651e0fa/crmsh/qdevice.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/crmsh/qdevice.py 2022-09-28 02:31:20.000000000 +0200 @@ -646,7 +646,7 @@ if not res or int(res) < SBDTimeout.SBD_WATCHDOG_TIMEOUT_DEFAULT_WITH_QDEVICE: sbd_watchdog_timeout_qdevice = SBDTimeout.SBD_WATCHDOG_TIMEOUT_DEFAULT_WITH_QDEVICE SBDManager.update_configuration({"SBD_WATCHDOG_TIMEOUT": str(sbd_watchdog_timeout_qdevice)}) - utils.set_property(stonith_timeout=SBDTimeout.get_stonith_timeout()) + utils.set_property("stonith-timeout", SBDTimeout.get_stonith_timeout()) @qnetd_lock_for_same_cluster_name def config_and_start_qdevice(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/crmsh/sbd.py new/crmsh-4.4.1+20220928.ded85d0a/crmsh/sbd.py --- old/crmsh-4.4.1+20220923.9651e0fa/crmsh/sbd.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/crmsh/sbd.py 2022-09-28 02:31:20.000000000 +0200 @@ -219,7 +219,7 @@ """ Adjust stonith-timeout property """ - utils.set_property_conditionally("stonith-timeout", self.get_stonith_timeout_expected()) + utils.set_property("stonith-timeout", self.get_stonith_timeout_expected(), conditional=True) def adjust_sbd_delay_start(self): """ @@ -509,7 +509,7 @@ # disk-based sbd if self._get_sbd_device_from_config(): utils.get_stdout_or_raise_error("crm configure primitive {} {}".format(self.SBD_RA_ID, self.SBD_RA)) - utils.set_property(stonith_enabled="true") + utils.set_property("stonith-enabled", "true") # disk-less sbd else: if self.timeout_inst is None: @@ -520,7 +520,7 @@ # in sbd stage if self._context.cluster_is_running: - bootstrap.adjust_pcmk_delay_max_and_stonith_timeout() + bootstrap.adjust_properties() def join_sbd(self, peer_host): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/crmsh/utils.py new/crmsh-4.4.1+20220928.ded85d0a/crmsh/utils.py --- old/crmsh-4.4.1+20220923.9651e0fa/crmsh/utils.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/crmsh/utils.py 2022-09-28 02:31:20.000000000 +0200 @@ -1001,7 +1001,7 @@ } if not t: return -1 - r = re.match(r"\s*(\d+)\s*([a-zA-Z]+)?", t) + r = re.match(r"\s*(\d+)\s*([a-zA-Z]+)?", str(t)) if not r: return -1 if not r.group(2): @@ -2996,27 +2996,21 @@ return 0 -def get_property(name): +def get_property(name, property_type="crm_config"): """ Get cluster properties + + "property_type" can be crm_config|rsc_defaults|op_defaults """ - cib_path = os.getenv('CIB_file', constants.CIB_RAW_FILE) - cmd = "CIB_file={} crm configure get_property {}".format(cib_path, name) + if property_type == "crm_config": + cib_path = os.getenv('CIB_file', constants.CIB_RAW_FILE) + cmd = "CIB_file={} crm configure get_property {}".format(cib_path, name) + else: + cmd = "crm_attribute -t {} -n {} -Gq".format(property_type, name) rc, stdout, _ = get_stdout_stderr(cmd) return stdout if rc == 0 else None -def set_property(**kwargs): - """ - Set cluster properties - """ - set_str = "" - for key, value in kwargs.items(): - set_str += "{}={} ".format(key, value) - cmd = "crm configure property " + set_str.strip().replace('_', '-') - get_stdout_or_raise_error(cmd) - - def check_no_quorum_policy_with_dlm(): """ Give warning when no-quorum-policy not freeze while configured DLM @@ -3028,15 +3022,24 @@ logger.warning("The DLM cluster best practice suggests to set the cluster property \"no-quorum-policy=freeze\"") -def set_property_conditionally(property_name, value_from_calculation): +def set_property(property_name, property_value, property_type="crm_config", conditional=False): """ - Set cluster property if calculated value is larger then current cib value + Set property for cluster, resource and operator + + "property_type" can be crm_config|rsc_defaults|op_defaults + When "conditional" is True, set the property if given "property_value" is larger then value from cib """ - _value = get_property(property_name) - value_from_cib = int(_value.strip('s')) if _value else 0 - if value_from_cib < value_from_calculation: - cmd = "crm configure property {}={}".format(property_name, value_from_calculation) - get_stdout_or_raise_error(cmd) + origin_value = get_property(property_name, property_type) + if origin_value and str(origin_value) == str(property_value): + return + if conditional: + if crm_msec(origin_value) >= crm_msec(property_value): + return + if origin_value and str(origin_value) != str(property_value): + logger.warning("\"{}\" in {} is set to {}, it was {}".format(property_name, property_type, property_value, origin_value)) + property_sub_cmd = "property" if property_type == "crm_config" else property_type + cmd = "crm configure {} {}={}".format(property_sub_cmd, property_name, property_value) + get_stdout_or_raise_error(cmd) def get_systemd_timeout_start_in_sec(time_res): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/test/features/bootstrap_sbd_delay.feature new/crmsh-4.4.1+20220928.ded85d0a/test/features/bootstrap_sbd_delay.feature --- old/crmsh-4.4.1+20220923.9651e0fa/test/features/bootstrap_sbd_delay.feature 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/test/features/bootstrap_sbd_delay.feature 2022-09-28 02:31:20.000000000 +0200 @@ -249,3 +249,38 @@ Then Service "corosync-qdevice" is "stopped" on "hanode1" And Service "corosync-qdevice" is "stopped" on "hanode2" And Parameter "pcmk_delay_max" configured in "stonith-sbd" + + @clean + Scenario: Test priority-fence-delay and priority + Given Cluster service is "stopped" on "hanode1" + Given Cluster service is "stopped" on "hanode2" + When Run "crm cluster init -y" on "hanode1" + Then Cluster service is "started" on "hanode1" + When Run "crm cluster join -c hanode1 -y" on "hanode2" + Then Cluster service is "started" on "hanode2" + And Property "priority" in "rsc_defaults" is "1" + When Run "crm cluster remove hanode2 -y" on "hanode1" + Then Cluster service is "stopped" on "hanode2" + And Property "priority" in "rsc_defaults" is "0" + When Run "crm cluster join -c hanode1 -y" on "hanode2" + Then Cluster service is "started" on "hanode2" + And Property "priority" in "rsc_defaults" is "1" + When Run "crm cluster init qdevice --qnetd-hostname=qnetd-node -y" on "hanode1" + Then Service "corosync-qdevice" is "started" on "hanode1" + And Service "corosync-qdevice" is "started" on "hanode2" + And Property "priority" in "rsc_defaults" is "0" + When Run "crm cluster remove --qdevice -y" on "hanode1" + Then Service "corosync-qdevice" is "stopped" on "hanode1" + And Service "corosync-qdevice" is "stopped" on "hanode2" + And Property "priority" in "rsc_defaults" is "1" + When Run "crm cluster init sbd -s /dev/sda1 -y" on "hanode1" + Then Service "sbd" is "started" on "hanode1" + And Service "sbd" is "started" on "hanode2" + And Parameter "pcmk_delay_max" configured in "stonith-sbd" + And Cluster property "stonith-timeout" is "83" + And Cluster property "priority-fencing-delay" is "60" + When Run "crm cluster remove hanode2 -y" on "hanode1" + Then Cluster service is "stopped" on "hanode2" + And Property "priority" in "rsc_defaults" is "0" + And Cluster property "priority-fencing-delay" is "0" + And Parameter "pcmk_delay_max" not configured in "stonith-sbd" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/test/features/steps/step_implementation.py new/crmsh-4.4.1+20220928.ded85d0a/test/features/steps/step_implementation.py --- old/crmsh-4.4.1+20220923.9651e0fa/test/features/steps/step_implementation.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/test/features/steps/step_implementation.py 2022-09-28 02:31:20.000000000 +0200 @@ -356,6 +356,12 @@ assert res is not None and str(res) == value +@then('Property "{key}" in "{type}" is "{value}"') +def step_impl(context, key, type, value): + res = crmutils.get_property(key, type) + assert res is not None and str(res) == value + + @then('Parameter "{param_name}" not configured in "{res_id}"') def step_impl(context, param_name, res_id): _, out = run_command(context, "crm configure show {}".format(res_id)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_bootstrap.py new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_bootstrap.py --- old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_bootstrap.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_bootstrap.py 2022-09-28 02:31:20.000000000 +0200 @@ -798,11 +798,13 @@ mock_confirm.assert_called_once_with("Qdevice is already configured - overwrite?") self.qdevice_with_ip.start_qdevice_service.assert_called_once_with() + @mock.patch('crmsh.bootstrap.adjust_priority_fencing_delay') + @mock.patch('crmsh.bootstrap.adjust_priority_in_rsc_defaults') @mock.patch('crmsh.utils.list_cluster_nodes') @mock.patch('crmsh.utils.is_qdevice_configured') @mock.patch('crmsh.utils.check_ssh_passwd_need') @mock.patch('logging.Logger.info') - def test_init_qdevice(self, mock_info, mock_ssh, mock_qdevice_configured, mock_list_nodes): + def test_init_qdevice(self, mock_info, mock_ssh, mock_qdevice_configured, mock_list_nodes, mock_adjust_priority, mock_adjust_fence_delay): bootstrap._context = mock.Mock(qdevice_inst=self.qdevice_with_ip) mock_list_nodes.return_value = [] mock_ssh.return_value = False @@ -905,6 +907,8 @@ mock_qdevice_configured.assert_called_once_with() mock_confirm.assert_called_once_with("Removing QDevice service and configuration from cluster: Are you sure?") + @mock.patch('crmsh.bootstrap.adjust_priority_fencing_delay') + @mock.patch('crmsh.bootstrap.adjust_priority_in_rsc_defaults') @mock.patch('crmsh.qdevice.QDevice.remove_certification_files_on_qnetd') @mock.patch('crmsh.qdevice.QDevice.remove_qdevice_db') @mock.patch('crmsh.qdevice.QDevice.remove_qdevice_config') @@ -917,7 +921,7 @@ @mock.patch('crmsh.bootstrap.confirm') @mock.patch('crmsh.utils.is_qdevice_configured') def test_remove_qdevice_reload(self, mock_qdevice_configured, mock_confirm, mock_reachable, mock_evaluate, - mock_status, mock_invoke, mock_status_long, mock_update_votes, mock_remove_config, mock_remove_db, mock_remove_files): + mock_status, mock_invoke, mock_status_long, mock_update_votes, mock_remove_config, mock_remove_db, mock_remove_files, mock_adjust_priority, mock_adjust_fence_delay): mock_qdevice_configured.return_value = True mock_confirm.return_value = True mock_evaluate.return_value = qdevice.QdevicePolicy.QDEVICE_RELOAD @@ -1007,26 +1011,22 @@ @mock.patch('logging.Logger.debug') @mock.patch('crmsh.utils.get_stdout_or_raise_error') - @mock.patch('crmsh.utils.is_2node_cluster_without_qdevice') @mock.patch('crmsh.bootstrap.cib_factory') - def test_adjust_pcmk_delay_2node(self, mock_cib_factory, mock_2node, mock_run, mock_debug): + def test_adjust_pcmk_delay_2node(self, mock_cib_factory, mock_run, mock_debug): mock_cib_factory.refresh = mock.Mock() mock_cib_factory.fence_id_list_without_pcmk_delay = mock.Mock() mock_cib_factory.fence_id_list_without_pcmk_delay.return_value = ["res_1"] - mock_2node.return_value = True - bootstrap.adjust_pcmk_delay_max() + bootstrap.adjust_pcmk_delay_max(True) mock_run.assert_called_once_with("crm resource param res_1 set pcmk_delay_max {}s".format(constants.PCMK_DELAY_MAX)) @mock.patch('logging.Logger.debug') @mock.patch('crmsh.utils.get_stdout_or_raise_error') - @mock.patch('crmsh.utils.is_2node_cluster_without_qdevice') @mock.patch('crmsh.bootstrap.cib_factory') - def test_adjust_pcmk_delay(self, mock_cib_factory, mock_2node, mock_run, mock_debug): + def test_adjust_pcmk_delay(self, mock_cib_factory, mock_run, mock_debug): mock_cib_factory.refresh = mock.Mock() mock_cib_factory.fence_id_list_with_pcmk_delay = mock.Mock() mock_cib_factory.fence_id_list_with_pcmk_delay.return_value = ["res_1"] - mock_2node.return_value = False - bootstrap.adjust_pcmk_delay_max() + bootstrap.adjust_pcmk_delay_max(False) mock_run.assert_called_once_with("crm resource param res_1 delete pcmk_delay_max") @mock.patch('crmsh.sbd.SBDTimeout') @@ -1037,30 +1037,60 @@ bootstrap.adjust_stonith_timeout() mock_sbd_timeout.adjust_sbd_timeout_related_cluster_configuration.assert_called_once_with() - @mock.patch('crmsh.utils.set_property_conditionally') + @mock.patch('crmsh.utils.set_property') @mock.patch('crmsh.bootstrap.get_stonith_timeout_generally_expected') @mock.patch('crmsh.utils.service_is_active') def test_adjust_stonith_timeout(self, mock_is_active, mock_get_timeout, mock_set): mock_is_active.return_value = False mock_get_timeout.return_value = 30 bootstrap.adjust_stonith_timeout() - mock_set.assert_called_once_with("stonith-timeout", 30) + mock_set.assert_called_once_with("stonith-timeout", 30, conditional=True) + + @mock.patch('crmsh.utils.set_property') + def test_adjust_priority_in_rsc_defaults_2node(self, mock_set): + bootstrap.adjust_priority_in_rsc_defaults(True) + mock_set.assert_called_once_with('priority', 1, property_type='rsc_defaults', conditional=True) + + @mock.patch('crmsh.utils.set_property') + def test_adjust_priority_in_rsc_defaults(self, mock_set): + bootstrap.adjust_priority_in_rsc_defaults(False) + mock_set.assert_called_once_with('priority', 0, property_type='rsc_defaults') + + @mock.patch('crmsh.utils.get_stdout_or_raise_error') + def test_adjust_priority_fencing_delay_no_fence_agent(self, mock_run): + mock_run.return_value = None + bootstrap.adjust_priority_fencing_delay(False) + mock_run.assert_called_once_with("crm configure show related:stonith") + + @mock.patch('crmsh.utils.set_property') + @mock.patch('crmsh.utils.get_stdout_or_raise_error') + def test_adjust_priority_fencing_delay_no_pcmk_delay(self, mock_run, mock_set): + mock_run.return_value = "data" + bootstrap.adjust_priority_fencing_delay(False) + mock_run.assert_called_once_with("crm configure show related:stonith") + mock_set.assert_called_once_with("priority-fencing-delay", 0) @mock.patch('crmsh.utils.service_is_active') - def test_adjust_pcmk_delay_and_stonith_timeout_return(self, mock_is_active): + def test_adjust_properties_no_service(self, mock_is_active): mock_is_active.return_value = False - bootstrap.adjust_pcmk_delay_max_and_stonith_timeout() + bootstrap.adjust_properties() mock_is_active.assert_called_once_with("pacemaker.service") + @mock.patch('crmsh.bootstrap.adjust_priority_fencing_delay') + @mock.patch('crmsh.bootstrap.adjust_priority_in_rsc_defaults') @mock.patch('crmsh.bootstrap.adjust_stonith_timeout') @mock.patch('crmsh.bootstrap.adjust_pcmk_delay_max') + @mock.patch('crmsh.utils.is_2node_cluster_without_qdevice') @mock.patch('crmsh.utils.service_is_active') - def test_adjust_pcmk_delay_and_stonith_timeout(self, mock_is_active, mock_adjust_pcmk_delay, mock_adjust_timeout): + def test_adjust_properties(self, mock_is_active, mock_2node_qdevice, mock_adj_pcmk, mock_adj_stonith, mock_adj_priority, mock_adj_fence): mock_is_active.return_value = True - bootstrap.adjust_pcmk_delay_max_and_stonith_timeout() + mock_2node_qdevice.return_value = True + bootstrap.adjust_properties() mock_is_active.assert_called_once_with("pacemaker.service") - mock_adjust_pcmk_delay.assert_called_once_with() - mock_adjust_timeout.assert_called_once_with() + mock_adj_pcmk.assert_called_once_with(True) + mock_adj_stonith.assert_called_once_with() + mock_adj_priority.assert_called_once_with(True) + mock_adj_fence.assert_called_once_with(True) class TestValidation(unittest.TestCase): @@ -1517,6 +1547,8 @@ ]) mock_error.assert_called_once_with("Removing the node node1 from {} failed".format(bootstrap.CSYNC2_CFG)) + @mock.patch('crmsh.bootstrap.adjust_priority_fencing_delay') + @mock.patch('crmsh.bootstrap.adjust_priority_in_rsc_defaults') @mock.patch('crmsh.bootstrap.csync2_update') @mock.patch('crmsh.bootstrap.decrease_expected_votes') @mock.patch('crmsh.corosync.del_node') @@ -1528,7 +1560,7 @@ @mock.patch('crmsh.bootstrap.stop_services') @mock.patch('crmsh.bootstrap.set_cluster_node_ip') def test_remove_node_from_cluster_hostname(self, mock_get_ip, mock_stop, mock_status, - mock_invoke, mock_invokerc, mock_error, mock_get_values, mock_del, mock_decrease, mock_csync2): + mock_invoke, mock_invokerc, mock_error, mock_get_values, mock_del, mock_decrease, mock_csync2, mock_adjust_priority, mock_adjust_fence_delay): mock_invoke.side_effect = [(True, None, None), (True, None, None), (True, None, None)] mock_invokerc.return_value = True mock_get_values.return_value = ["10.10.10.1"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_qdevice.py new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_qdevice.py --- old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_qdevice.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_qdevice.py 2022-09-28 02:31:20.000000000 +0200 @@ -981,7 +981,7 @@ mock_evaluate.assert_called_once_with(qdevice.QDEVICE_ADD, True) mock_get_sbd_value.assert_called_once_with("SBD_WATCHDOG_TIMEOUT") mock_update_config.assert_called_once_with({"SBD_WATCHDOG_TIMEOUT": str(sbd.SBDTimeout.SBD_WATCHDOG_TIMEOUT_DEFAULT_WITH_QDEVICE)}) - mock_set_property.assert_called_once_with(stonith_timeout=100) + mock_set_property.assert_called_once_with("stonith-timeout", 100) @mock.patch('crmsh.qdevice.QDevice.start_qnetd') @mock.patch('crmsh.qdevice.QDevice.enable_qnetd') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_sbd.py new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_sbd.py --- old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_sbd.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_sbd.py 2022-09-28 02:31:20.000000000 +0200 @@ -689,7 +689,7 @@ mock_enabled.assert_called_once_with("sbd.service") mock_configured.assert_called_once_with(sbd.SBDManager.SBD_RA) mock_run.assert_called_once_with("crm configure primitive {} {}".format(sbd.SBDManager.SBD_RA_ID, sbd.SBDManager.SBD_RA)) - mock_set_property.assert_called_once_with(stonith_enabled="true") + mock_set_property.assert_called_once_with("stonith-enabled", "true") @mock.patch('crmsh.utils.package_is_installed') def test_join_sbd_config_not_installed(self, mock_package): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_utils.py new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_utils.py --- old/crmsh-4.4.1+20220923.9651e0fa/test/unittests/test_utils.py 2022-09-23 10:48:20.000000000 +0200 +++ new/crmsh-4.4.1+20220928.ded85d0a/test/unittests/test_utils.py 2022-09-28 02:31:20.000000000 +0200 @@ -1616,10 +1616,31 @@ mock_run.assert_called_once_with("CIB_file=cib.xml crm configure get_property no-quorum-policy") +@mock.patch('logging.Logger.warning') @mock.patch('crmsh.utils.get_stdout_or_raise_error') -def test_set_property(mock_run): - utils.set_property(no_quorum_policy="stop") +@mock.patch('crmsh.utils.get_property') +def test_set_property(mock_get, mock_run, mock_warn): + mock_get.return_value = "start" + utils.set_property("no-quorum-policy", "stop") mock_run.assert_called_once_with("crm configure property no-quorum-policy=stop") + mock_warn.assert_called_once_with('"no-quorum-policy" in crm_config is set to stop, it was start') + + +@mock.patch('crmsh.utils.get_property') +def test_set_property_the_same(mock_get): + mock_get.return_value = "value1" + utils.set_property("no-quorum-policy", "value1") + mock_get.assert_called_once_with("no-quorum-policy", "crm_config") + + +@mock.patch('crmsh.utils.crm_msec') +@mock.patch('crmsh.utils.get_property') +def test_set_property_conditional(mock_get, mock_msec): + mock_get.return_value = "10s" + mock_msec.side_effect = ["1000", "1000"] + utils.set_property("timeout", "10", conditional=True) + mock_get.assert_called_once_with("timeout", "crm_config") + mock_msec.assert_has_calls([mock.call("10s"), mock.call("10")]) @mock.patch('crmsh.utils.is_dlm_configured') @@ -1657,14 +1678,6 @@ assert res == 91 -@mock.patch('crmsh.utils.get_stdout_or_raise_error') -@mock.patch('crmsh.utils.get_property') -def test_set_property_conditionally(mock_get_property, mock_run): - mock_get_property.return_value = "100s" - utils.set_property_conditionally("stonith-timeout", 101) - mock_run.assert_called_once_with("crm configure property stonith-timeout=101") - - @mock.patch('crmsh.utils.is_larger_than_min_version') @mock.patch('crmsh.cibconfig.cib_factory') def test_is_ocf_1_1_cib_schema_detected(mock_cib, mock_larger):