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-12-01 17:21:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Thu Dec 1 17:21:11 2022 rev:268 rq:1039249 version:4.4.1+20221201.bdfb0f2c Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2022-11-23 09:48:27.999154228 +0100 +++ /work/SRC/openSUSE:Factory/.crmsh.new.1835/crmsh.changes 2022-12-01 17:22:05.914520486 +0100 @@ -1,0 +2,46 @@ +Thu Dec 01 06:28:39 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221201.bdfb0f2c: + * Change: store the upgrade_seq in /etc/crm/ + +------------------------------------------------------------------- +Thu Dec 01 04:31:00 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221201.280e5afb: + * Fix: qdevice: Adjust SBD_WATCHDOG_TIMEOUT when configuring qdevice not using stage (bsc#1205727) + +------------------------------------------------------------------- +Wed Nov 30 02:00:58 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221130.c3547a20: + * Dev: testcases: Adjust original regression test based on previous changes + * Dev: behave: Add functional test for previous changes + * Fix: cibconfig: Complete promotable=true and interlave=true for Promoted/Unpromoted resource (bsc#1205522) + +------------------------------------------------------------------- +Mon Nov 28 09:03:47 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221128.75c824f5: + * Dev: bootstrap: return when -N option not specified + * Dev: unittest: Add unit test for previous commit + * Dev: bootstrap: join process return immediately when joining itself + +------------------------------------------------------------------- +Mon Nov 28 07:51:22 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221128.1b8068a8: + * Dev: log: Use original way for the prompt input + +------------------------------------------------------------------- +Fri Nov 25 07:39:10 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221125.ef74cf11: + * Dev: bootstrap: add timeout to wait_for_cluster and wait_for_resource + +------------------------------------------------------------------- +Thu Nov 24 08:45:07 UTC 2022 - xli...@suse.com + +- Update to version 4.4.1+20221124.37ac467f: + * Fix: corosync: show corosync ring status if has fault (bsc#1205615) + +------------------------------------------------------------------- Old: ---- crmsh-4.4.1+20221122.102a8e11.tar.bz2 New: ---- crmsh-4.4.1+20221201.bdfb0f2c.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.Pvd32a/_old 2022-12-01 17:22:06.546523942 +0100 +++ /var/tmp/diff_new_pack.Pvd32a/_new 2022-12-01 17:22:06.550523964 +0100 @@ -36,7 +36,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0-or-later Group: %{pkg_group} -Version: 4.4.1+20221122.102a8e11 +Version: 4.4.1+20221201.bdfb0f2c Release: 0 URL: http://crmsh.github.io Source0: %{name}-%{version}.tar.bz2 ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.Pvd32a/_old 2022-12-01 17:22:06.606524270 +0100 +++ /var/tmp/diff_new_pack.Pvd32a/_new 2022-12-01 17:22:06.610524292 +0100 @@ -9,7 +9,7 @@ </service> <service name="tar_scm"> <param name="url">https://github.com/ClusterLabs/crmsh.git</param> - <param name="changesrevision">5baaacb0a20a8ed89adaa403a50dacde998688f6</param> + <param name="changesrevision">bdfb0f2ca98a8d652455b883049070054e677869</param> </service> </servicedata> (No newline at EOF) ++++++ crmsh-4.4.1+20221122.102a8e11.tar.bz2 -> crmsh-4.4.1+20221201.bdfb0f2c.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/bootstrap.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/bootstrap.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/bootstrap.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/bootstrap.py 2022-12-01 07:11:27.000000000 +0100 @@ -20,6 +20,7 @@ import readline import shutil import yaml +import socket from string import Template from lxml import etree from pathlib import Path @@ -33,7 +34,7 @@ from . import tmpfiles from . import lock from . import userdir -from .constants import SSH_OPTION, QDEVICE_HELP_INFO, STONITH_TIMEOUT_DEFAULT, REJOIN_COUNT, REJOIN_INTERVAL, PCMK_DELAY_MAX +from .constants import SSH_OPTION, QDEVICE_HELP_INFO, STONITH_TIMEOUT_DEFAULT, REJOIN_COUNT, REJOIN_INTERVAL, PCMK_DELAY_MAX, WAIT_TIMEOUT_MS_DEFAULT from . import ocfs2 from . import qdevice from . import parallax @@ -174,6 +175,8 @@ """ Validate -N/--nodes option """ + if not self.node_list: + return self.node_list = utils.parse_append_action_argument(self.node_list) me = utils.this_node() if me in self.node_list: @@ -185,6 +188,19 @@ for node in self.node_list: utils.ping_node(node) + def _validate_cluster_node(self): + """ + Validate cluster_node on join side + """ + if self.cluster_node and self.type == 'join': + try: + # self.cluster_node might be hostname or IP address + ip_addr = socket.gethostbyname(self.cluster_node) + if utils.InterfacesInfo.ip_in_local(ip_addr): + utils.fatal("Please specify peer node's hostname or IP address") + except socket.gaierror as err: + utils.fatal("\"{}\": {}".format(self.cluster_node, err)) + def validate_option(self): """ Validate options @@ -204,6 +220,7 @@ logger.warning("-w option is deprecated and will be removed in future versions") if self.ocfs2_devices or self.stage == "ocfs2": ocfs2.OCFS2Manager.verify_ocfs2(self) + self._validate_cluster_node() self._validate_nodes_option() self._validate_sbd_option() @@ -358,24 +375,30 @@ utils.fatal("Failed to commit cluster configuration") -def wait_for_resource(message, resource): +def wait_for_resource(message, resource, timeout_ms=WAIT_TIMEOUT_MS_DEFAULT): """ Wait for resource started """ with logger_utils.status_long(message) as progress_bar: + start_time = int(time.clock_gettime(time.CLOCK_MONOTONIC) * 1000) while True: if xmlutil.CrmMonXmlParser.is_resource_started(resource): break status_progress(progress_bar) + if 0 < timeout_ms <= (int(time.clock_gettime(time.CLOCK_MONOTONIC) * 1000) - start_time): + utils.fatal('Time out waiting for resource.') sleep(1) -def wait_for_cluster(): +def wait_for_cluster(timeout_ms=WAIT_TIMEOUT_MS_DEFAULT): with logger_utils.status_long("Waiting for cluster") as progress_bar: + start_time = int(time.clock_gettime(time.CLOCK_MONOTONIC) * 1000) while True: if is_online(): break status_progress(progress_bar) + if 0 < timeout_ms <= (int(time.clock_gettime(time.CLOCK_MONOTONIC) * 1000) - start_time): + utils.fatal('Time out waiting for cluster.') sleep(2) @@ -2108,7 +2131,6 @@ init() _context.init_sbd_manager() - _context.validate_option() check_tty() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/cibconfig.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/cibconfig.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/cibconfig.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/cibconfig.py 2022-12-01 07:11:27.000000000 +0100 @@ -25,7 +25,7 @@ from . import crm_gv from . import ui_utils from . import userdir -from .ra import get_ra, get_properties_list, get_pe_meta, get_properties_meta +from .ra import get_ra, get_properties_list, get_pe_meta, get_properties_meta, RAInfo from .utils import ext_cmd, safe_open_w, pipe_string, safe_close_w, crm_msec from .utils import ask, lines2cli, olist from .utils import page_string, cibadmin_can_patch, str2tmp, ensure_sudo_readable @@ -42,7 +42,7 @@ from .xmlutil import is_simpleconstraint, is_template, rmnode, is_defaults, is_live_cib from .xmlutil import get_rsc_operations, delete_rscref, xml_equals, lookup_node, RscState from .xmlutil import text2elem, is_related, check_id_ref, xml_tostring -from .xmlutil import sanitize_cib_for_patching +from .xmlutil import sanitize_cib_for_patching, is_attr_set, get_set_nodes, set_attr from .cliformat import get_score, nvpairs2list, abs_pos_score, cli_acl_roleref, nvpair_format from .cliformat import cli_nvpair, cli_acl_rule, rsc_set_constraint, get_kind, head_id_format from .cliformat import simple_rsc_constraint, cli_rule, cli_format @@ -793,7 +793,7 @@ return obj_id -def postprocess_cli(node, oldnode=None, id_hint=None): +def postprocess_cli(node, oldnode=None, id_hint=None, complete_advised=False): """ input: unprocessed but parsed XML output: XML, obj_type, obj_id @@ -816,26 +816,58 @@ resolve_references(node) if oldnode is not None: remove_id_used_attributes(oldnode) + if complete_advised: + complete_advised_meta(node) return node, obj_type, obj_id +def complete_advised_meta(node): + """ + Complete advised meta attributes + """ + if node.tag != "clone": + return + primitive_list = node.xpath('primitive') + if not primitive_list: + return + set_list = [] + for meta_item in ["promotable", "interleave"]: + if not is_attr_set(node, meta_item): + set_list.append(meta_item) + if not set_list: + return + + meta_node = get_set_nodes(node, "meta_attributes", create=True)[0] + p = primitive_list[0] + ra_inst = RAInfo(p.get('class'), p.get('type'), p.get('provider')) + ra_actions_dict = ra_inst.actions() + if ra_actions_dict and "promote" in ra_actions_dict and "demote" in ra_actions_dict: + for item in set_list: + set_attr(meta_node, item, "true") + # Add interleave=true as long as it's not set, no matter if it's promotable clone or not + elif "interleave" in set_list: + set_attr(meta_node, "interleave", "true") + + def parse_cli_to_xml(cli, oldnode=None): """ input: CLI text output: XML, obj_type, obj_id """ node = None + complete = False comments = [] if isinstance(cli, str): for s in lines2cli(cli): node = parse.parse(s, comments=comments) else: # should be a pre-tokenized list - node = parse.parse(cli, comments=comments, ignore_empty=False, complete_op_advised=True) + complete = True + node = parse.parse(cli, comments=comments, ignore_empty=False, complete_advised=complete) if node is False: return None, None, None elif node is None: return None, None, None - return postprocess_cli(node, oldnode) + return postprocess_cli(node, oldnode, complete_advised=complete) # # cib element classes (CibObject the parent class) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/constants.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/constants.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/constants.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/constants.py 2022-12-01 07:11:27.000000000 +0100 @@ -528,4 +528,6 @@ ADVISED_KEY_LIST = ['timeout', 'interval', 'role'] DEFAULT_INTERVAL_IN_ACTION = "20s" DEFAULT_TIMEOUT_IN_ACTION = "60s" + +WAIT_TIMEOUT_MS_DEFAULT = 120000 # vim:ts=4:sw=4:et: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/corosync.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/corosync.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/corosync.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/corosync.py 2022-12-01 07:11:27.000000000 +0100 @@ -62,7 +62,7 @@ rc, out, err = utils.get_stdout_stderr("corosync-cfgtool -s") if rc != 0 and err: raise ValueError(err) - if rc == 0 and out: + if out: print(out) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/log.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/log.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/log.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/log.py 2022-12-01 07:11:27.000000000 +0100 @@ -332,12 +332,11 @@ """ Wrap input function with recording prompt string and input result """ - with self.suppress_new_line(): + with self.only_file(): self.logger.info(prompt_string) - value = input() + value = input(prompt_string) if not value: value = default - print() with self.only_file(): self.logger.info("input result: %s", value) return value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/parse.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/parse.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/parse.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/parse.py 2022-12-01 07:11:27.000000000 +0100 @@ -170,13 +170,13 @@ self.begin(cmd, min_args=min_args) return self.match_dispatch(errmsg="Unknown command") - def do_parse(self, cmd, ignore_empty, complete_op_advised): + def do_parse(self, cmd, ignore_empty, complete_advised): """ Called by CliParser. Calls parse() Parsers should pass their return value through this method. """ self.ignore_empty = ignore_empty - self.complete_op_advised = complete_op_advised + self.complete_advised = complete_advised out = self.parse(cmd) if self.has_tokens(): self.err("Unknown arguments: " + ' '.join(self._cmd[self._currtok:])) @@ -661,7 +661,7 @@ """ Complete operation actions advised values """ - if not self.complete_op_advised or out.tag != "primitive": + if not self.complete_advised or out.tag != "primitive": return ra_inst = ra.RAInfo(out.get('class'), out.get('type'), out.get('provider')) ra_actions_dict = ra_inst.actions() @@ -1774,7 +1774,7 @@ return ret -def parse(s, comments=None, ignore_empty=True, complete_op_advised=False): +def parse(s, comments=None, ignore_empty=True, complete_advised=False): ''' Input: a list of tokens (or a CLI format string). Return: a cibobject @@ -1820,7 +1820,7 @@ return False try: - ret = parser.do_parse(s, ignore_empty, complete_op_advised) + ret = parser.do_parse(s, ignore_empty, complete_advised) if ret is not None and len(comments) > 0: if ret.tag in constants.defaults_tags: xmlutil.stuff_comments(ret[0], comments) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/qdevice.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/qdevice.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/qdevice.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/qdevice.py 2022-12-01 07:11:27.000000000 +0100 @@ -3,6 +3,7 @@ import socket import functools from enum import Enum +from . import constants from . import utils from . import parallax from . import corosync @@ -635,18 +636,17 @@ """ Adjust SBD_WATCHDOG_TIMEOUT when configuring qdevice and diskless SBD """ - if self.is_stage: - from .sbd import SBDManager, SBDTimeout - utils.check_all_nodes_reachable() - using_diskless_sbd = SBDManager.is_using_diskless_sbd() - self.qdevice_reload_policy = evaluate_qdevice_quorum_effect(QDEVICE_ADD, using_diskless_sbd) - # add qdevice after diskless sbd started - if using_diskless_sbd: - res = SBDManager.get_sbd_value_from_config("SBD_WATCHDOG_TIMEOUT") - 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()) + from .sbd import SBDManager, SBDTimeout + utils.check_all_nodes_reachable() + using_diskless_sbd = SBDManager.is_using_diskless_sbd() + self.qdevice_reload_policy = evaluate_qdevice_quorum_effect(QDEVICE_ADD, using_diskless_sbd) + # add qdevice after diskless sbd started + if using_diskless_sbd: + res = SBDManager.get_sbd_value_from_config("SBD_WATCHDOG_TIMEOUT") + 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()) @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+20221122.102a8e11/crmsh/ui_cluster.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/ui_cluster.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/ui_cluster.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/ui_cluster.py 2022-12-01 07:11:27.000000000 +0100 @@ -478,6 +478,7 @@ join_context.ui_context = context join_context.stage = stage join_context.type = "join" + join_context.validate_option() bootstrap.bootstrap_join(join_context) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/upgradeutil.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/upgradeutil.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/upgradeutil.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/upgradeutil.py 2022-12-01 07:11:27.000000000 +0100 @@ -12,7 +12,7 @@ # pump this seq when upgrade check need to be run CURRENT_UPGRADE_SEQ = (1, 0) -DATA_DIR = os.path.expanduser('~hacluster/crmsh') +DATA_DIR = '/var/lib/crmsh' SEQ_FILE_PATH = DATA_DIR + '/upgrade_seq' # touch this file to force a upgrade process FORCE_UPGRADE_FILE_PATH = DATA_DIR + '/upgrade_forced' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/crmsh/xmlutil.py new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/xmlutil.py --- old/crmsh-4.4.1+20221122.102a8e11/crmsh/xmlutil.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/crmsh/xmlutil.py 2022-12-01 07:11:27.000000000 +0100 @@ -550,10 +550,14 @@ return node.tag == "group" +def is_attr_set(node, attr): + return get_attr_value(get_child_nvset_node(node), attr) is not None + + def is_ms_or_promotable_clone(node): - is_promotable = is_boolean_true(get_attr_value(get_child_nvset_node(node), "promotable")) - is_ms = node.tag in ("master", "ms") - return is_ms or is_promotable + is_promotable_type = is_boolean_true(is_attr_set(node, "promotable")) + is_ms_type = node.tag in ("master", "ms") + return is_ms_type or is_promotable_type def is_clone(node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/features/resource_set.feature new/crmsh-4.4.1+20221201.bdfb0f2c/test/features/resource_set.feature --- old/crmsh-4.4.1+20221122.102a8e11/test/features/resource_set.feature 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/features/resource_set.feature 2022-12-01 07:11:27.000000000 +0100 @@ -129,3 +129,15 @@ Then Run "ls /trace_log_d/Dummy/d.monitor.*" OK When Run "crm resource untrace d" on "hanode1" Then Expected "Stop tracing d" in stdout + + @clean + Scenario: Add promotable=true and interleave=true automatically (bsc#1205522) + When Run "crm configure primitive s2 ocf:pacemaker:Stateful" on "hanode1" + And Run "crm configure clone p2 s2" on "hanode1" + Then Run "sleep 2;crm configure show|grep -A1 'clone p2 s2'|grep 'promotable=true interleave=true'" OK + When Run "crm configure primitive s3 ocf:pacemaker:Stateful" on "hanode1" + And Run "crm configure clone p3 s3 meta promotable=false" on "hanode1" + Then Run "sleep 2;crm configure show|grep -A1 'clone p3 s3'|grep 'promotable=false interleave=true'" OK + When Run "crm configure primitive d2 Dummy" on "hanode1" + And Run "crm configure clone p4 d2" on "hanode1" + Then Run "sleep 2;crm configure show|grep -A1 'clone p4 d2'|grep 'interleave=true'" OK diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/testcases/bugs.exp new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/bugs.exp --- old/crmsh-4.4.1+20221122.102a8e11/test/testcases/bugs.exp 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/bugs.exp 2022-12-01 07:11:27.000000000 +0100 @@ -58,7 +58,8 @@ op monitor timeout=20s interval=10s \ op start timeout=20s interval=0s \ op stop timeout=20s interval=0s -clone cl-p5 p5 +clone cl-p5 p5 \ + meta interleave=true colocation c2 inf: ( p1 p2 ) p3 p4 .INP: commit .INP: _test @@ -95,7 +96,8 @@ op monitor timeout=20s interval=10s \ op start timeout=20s interval=0s \ op stop timeout=20s interval=0s -clone cl-p5 p5 +clone cl-p5 p5 \ + meta interleave=true colocation c2 inf: ( p1 p2 ) p3 p4 .TRY Unordered load file .INP: options @@ -141,7 +143,8 @@ group g1 gr1 gr2 group g2 gr3 group g3 gr4 -clone cl-p5 p5 +clone cl-p5 p5 \ + meta interleave=true colocation c2 inf: ( p1 p2 ) p3 p4 location loc1 g1 \ rule 200: #uname eq node1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/testcases/confbasic-xml.exp new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/confbasic-xml.exp --- old/crmsh-4.4.1+20221122.102a8e11/test/testcases/confbasic-xml.exp 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/confbasic-xml.exp 2022-12-01 07:11:27.000000000 +0100 @@ -75,6 +75,7 @@ <clone id="c"> <meta_attributes id="c-meta_attributes"> <nvpair name="clone-max" value="1" id="c-meta_attributes-clone-max"/> + <nvpair name="interleave" value="true" id="c-meta_attributes-interleave"/> </meta_attributes> <primitive id="d3" class="ocf" provider="pacemaker" type="Dummy"> <operations> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/testcases/confbasic.exp new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/confbasic.exp --- old/crmsh-4.4.1+20221122.102a8e11/test/testcases/confbasic.exp 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/confbasic.exp 2022-12-01 07:11:27.000000000 +0100 @@ -145,9 +145,9 @@ ms m5 s5 ms m6 s6 clone c d3 \ - meta clone-max=1 + meta clone-max=1 interleave=true clone m7 d8 \ - meta promotable=true \ + meta promotable=true interleave=true \ meta promoted-max=1 \ meta promoted-node-max=1 tag t1 m5 m6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/testcases/file.exp new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/file.exp --- old/crmsh-4.4.1+20221122.102a8e11/test/testcases/file.exp 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/file.exp 2022-12-01 07:11:27.000000000 +0100 @@ -23,9 +23,10 @@ op monitor timeout=20 interval=3600 \ op start timeout=20 interval=0s \ op stop timeout=15 interval=0s -clone c1 p1 +clone c1 p1 \ + meta interleave=true clone m1 p2 \ - meta promotable=true + meta promotable=true interleave=true rsc_defaults build-resource-defaults: \ resource-stickiness=1 op_defaults op-options: \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/testcases/resource.exp new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/resource.exp --- old/crmsh-4.4.1+20221122.102a8e11/test/testcases/resource.exp 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/testcases/resource.exp 2022-12-01 07:11:27.000000000 +0100 @@ -65,6 +65,7 @@ <resources> <clone id="c1"> <meta_attributes id="c1-meta_attributes"> + <nvpair id="c1-meta_attributes-interleave" name="interleave" value="true"/> <nvpair id="c1-meta_attributes-is-managed" name="is-managed" value="true"/> </meta_attributes> <primitive id="p1" class="ocf" provider="pacemaker" type="Dummy"> @@ -92,6 +93,7 @@ <resources> <clone id="c1"> <meta_attributes id="c1-meta_attributes"> + <nvpair id="c1-meta_attributes-interleave" name="interleave" value="true"/> <nvpair id="c1-meta_attributes-is-managed" name="is-managed" value="false"/> </meta_attributes> <primitive id="p1" class="ocf" provider="pacemaker" type="Dummy"> @@ -121,6 +123,7 @@ <clone id="m1"> <meta_attributes id="m1-meta_attributes"> <nvpair name="promotable" value="true" id="m1-meta_attributes-promotable"/> + <nvpair id="m1-meta_attributes-interleave" name="interleave" value="true"/> <nvpair id="m1-meta_attributes-maintenance" name="maintenance" value="true"/> </meta_attributes> <primitive id="p2" class="ocf" provider="heartbeat" type="Delay"> @@ -154,6 +157,7 @@ <clone id="m1"> <meta_attributes id="m1-meta_attributes"> <nvpair name="promotable" value="true" id="m1-meta_attributes-promotable"/> + <nvpair id="m1-meta_attributes-interleave" name="interleave" value="true"/> <nvpair id="m1-meta_attributes-maintenance" name="maintenance" value="false"/> </meta_attributes> <primitive id="p2" class="ocf" provider="heartbeat" type="Delay"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.1+20221122.102a8e11/test/unittests/test_bootstrap.py new/crmsh-4.4.1+20221201.bdfb0f2c/test/unittests/test_bootstrap.py --- old/crmsh-4.4.1+20221122.102a8e11/test/unittests/test_bootstrap.py 2022-11-22 15:17:41.000000000 +0100 +++ new/crmsh-4.4.1+20221201.bdfb0f2c/test/unittests/test_bootstrap.py 2022-12-01 07:11:27.000000000 +0100 @@ -13,6 +13,7 @@ import os import unittest import yaml +import socket try: from unittest import mock @@ -131,6 +132,30 @@ ctx.validate_option() mock_error.assert_called_once_with("Duplicated input for -i/--interface option") + @mock.patch('crmsh.utils.fatal') + @mock.patch('socket.gethostbyname') + @mock.patch('crmsh.utils.InterfacesInfo.ip_in_local') + def test_validate_cluster_node_same_name(self, mock_ip_in_local, mock_gethost, mock_fatal): + options = mock.Mock(cluster_node="me", type="join") + ctx = self.ctx_inst.set_context(options) + mock_fatal.side_effect = SystemExit + mock_gethost.return_value = ("10.10.10.41", None) + mock_ip_in_local.return_value = True + with self.assertRaises(SystemExit): + ctx._validate_cluster_node() + mock_fatal.assert_called_once_with("Please specify peer node's hostname or IP address") + + @mock.patch('crmsh.utils.fatal') + @mock.patch('socket.gethostbyname') + def test_validate_cluster_node_unknown_name(self, mock_gethost, mock_fatal): + options = mock.Mock(cluster_node="xxxx", type="join") + ctx = self.ctx_inst.set_context(options) + mock_fatal.side_effect = SystemExit + mock_gethost.side_effect = socket.gaierror("gethostbyname error") + with self.assertRaises(SystemExit): + ctx._validate_cluster_node() + mock_fatal.assert_called_once_with('"xxxx": gethostbyname error') + @mock.patch('logging.Logger.warning') @mock.patch('crmsh.bootstrap.Validation.valid_admin_ip') def test_validate_option(self, mock_admin_ip, mock_warn):