Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2025-02-11 21:25:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new.19470 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Tue Feb 11 21:25:30 2025 rev:355 rq:1244739 version:5.0.0+20250210.db3e9f28 Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2025-01-23 18:06:09.501981858 +0100 +++ /work/SRC/openSUSE:Factory/.crmsh.new.19470/crmsh.changes 2025-02-11 21:27:14.792747875 +0100 @@ -1,0 +2,40 @@ +Mon Feb 10 11:03:40 UTC 2025 - xli...@suse.com + +- Update to version 5.0.0+20250210.db3e9f28: + * Dev: Add cancel option when confirming to commit for the pending changes + +------------------------------------------------------------------- +Mon Feb 10 03:19:01 UTC 2025 - xli...@suse.com + +- Update to version 5.0.0+20250210.5c190a8d: + * Dev: unittests: Adjust unit test for previous commit + * Fix: sbd: Detect if sbd package is missing on peer nodes + +------------------------------------------------------------------- +Sat Feb 08 03:47:46 UTC 2025 - xli...@suse.com + +- Update to version 5.0.0+20250208.0b368d36: + * Dev: Refactor: Introduce custom sort order enable/disable functions + * Dev: ui_configure: Add completer for 'configure schema' command + * Revert "Fix: ui_context: Don't complete for unknown argument" + +------------------------------------------------------------------- +Fri Feb 07 08:34:23 UTC 2025 - xli...@suse.com + +- Update to version 5.0.0+20250207.bbfaace1: + * Dev: Replace "stonith:external/<agent>" to fence_agents in multiple places (jsc#PED-8733) + +------------------------------------------------------------------- +Fri Feb 07 04:18:05 UTC 2025 - xli...@suse.com + +- Update to version 5.0.0+20250207.7601cb12: + * Fix: bootstrap: Local joining node should be included when merging known_hosts (bsc#1229419) + +------------------------------------------------------------------- +Thu Feb 06 03:37:35 UTC 2025 - xli...@suse.com + +- Update to version 5.0.0+20250206.325350ba: + * Dev: unittests: Adjust unit test for previous commit + * Dev: bootstrap: Check if core packages like corosync/pacemaker are installed + +------------------------------------------------------------------- Old: ---- crmsh-5.0.0+20250123.155bd2c2.tar.bz2 New: ---- crmsh-5.0.0+20250210.db3e9f28.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.ibTRzR/_old 2025-02-11 21:27:16.804830873 +0100 +++ /var/tmp/diff_new_pack.ibTRzR/_new 2025-02-11 21:27:16.804830873 +0100 @@ -36,7 +36,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0-or-later Group: %{pkg_group} -Version: 5.0.0+20250123.155bd2c2 +Version: 5.0.0+20250210.db3e9f28 Release: 0 URL: http://crmsh.github.io Source0: %{name}-%{version}.tar.bz2 ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.ibTRzR/_old 2025-02-11 21:27:16.848832688 +0100 +++ /var/tmp/diff_new_pack.ibTRzR/_new 2025-02-11 21:27:16.848832688 +0100 @@ -9,7 +9,7 @@ </service> <service name="tar_scm"> <param name="url">https://github.com/ClusterLabs/crmsh.git</param> - <param name="changesrevision">155bd2c2325b48888c62c8e51e36b2b051dcb066</param> + <param name="changesrevision">db3e9f282c8741061be9fbb354949c2ae43279c0</param> </service> </servicedata> (No newline at EOF) ++++++ crmsh-5.0.0+20250123.155bd2c2.tar.bz2 -> crmsh-5.0.0+20250210.db3e9f28.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/bootstrap.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/bootstrap.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/bootstrap.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/bootstrap.py 2025-02-10 11:35:30.000000000 +0100 @@ -85,6 +85,7 @@ DEFAULT_PROFILE_NAME = "default" KNET_DEFAULT_PROFILE_NAME = "knet-default" S390_PROFILE_NAME = "s390" + CORE_PACKAGES = ("corosync", "pacemaker") def __init__(self): ''' @@ -215,24 +216,29 @@ """ Validate sbd options """ - with_sbd_option = self.sbd_devices or self.diskless_sbd - sbd_installed = utils.package_is_installed("sbd") - - if with_sbd_option and not sbd_installed: - utils.fatal(SBDManager.SBD_NOT_INSTALLED_MSG) if self.sbd_devices and self.diskless_sbd: utils.fatal("Can't use -s and -S options together") if self.sbd_devices: SBDUtils.verify_sbd_device(self.sbd_devices) + + with_sbd_option = self.sbd_devices or self.diskless_sbd + if self.stage == "sbd": - if not sbd_installed: + if self.cluster_is_running: + utils.check_all_nodes_reachable() + for node in utils.list_cluster_nodes(): + if not utils.package_is_installed("sbd", node): + utils.fatal(SBDManager.SBD_NOT_INSTALLED_MSG + f" on {node}") + elif not utils.package_is_installed("sbd"): utils.fatal(SBDManager.SBD_NOT_INSTALLED_MSG) + if not with_sbd_option and self.yes_to_all: utils.fatal("Stage sbd should specify sbd device by -s or diskless sbd by -S option") if ServiceManager().service_is_active(constants.SBD_SERVICE) and not config.core.force: utils.fatal("Can't configure stage sbd: sbd.service already running! Please use crm option '-F' if need to redeploy") - if self.cluster_is_running: - utils.check_all_nodes_reachable() + + elif with_sbd_option and not utils.package_is_installed("sbd"): + utils.fatal(SBDManager.SBD_NOT_INSTALLED_MSG) def _validate_nodes_option(self): """ @@ -289,10 +295,13 @@ if self.stage in ("cluster", ) and self.cluster_is_running: utils.fatal(f"Cluster is active, can't run '{self.stage}' stage") - def validate_option(self): + def validate(self): """ - Validate options + Validate packages and options """ + for package in self.CORE_PACKAGES: + if not utils.package_is_installed(package): + utils.fatal(f"Package '{package}' is not installed") if self.qdevice_inst: self.qdevice_inst.valid_qdevice_options() if self.ocfs2_devices or self.gfs2_devices or self.stage in ("ocfs2", "gfs2"): @@ -1777,7 +1786,7 @@ """ logger.info("Merging known_hosts") - hosts = _context.node_list_in_cluster + hosts = _context.node_list_in_cluster + [utils.this_node()] shell = sh.cluster_shell() # create local entry in known_hosts @@ -1786,7 +1795,6 @@ known_hosts_new: set[str] = set() cat_cmd = "[ -e ~/.ssh/known_hosts ] && cat ~/.ssh/known_hosts || true" - #logger_utils.log_only_to_file("parallax.call {} : {}".format(hosts, cat_cmd)) for host in hosts: known_hosts_content = shell.get_stdout_or_raise_error(cat_cmd, host) if known_hosts_content: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/command.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/command.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/command.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/command.py 2025-02-10 11:35:30.000000000 +0100 @@ -535,10 +535,7 @@ ''' ret = [] if self.completer is not None: - if sort_completion_inst is not None and sort_completion_inst.value == 0: - # Restore the original value of rl_sort_completion_matches - # before calling the completer again - sort_completion_inst.value = orig_sort_completion_value + disable_custom_sort_order() specs = inspect.getfullargspec(self.completer) if 'context' in specs.args: ret = self.completer([self.name] + args, context) @@ -566,6 +563,18 @@ ": Expected method with signature " + repr(expected)) +def enable_custom_sort_order(): + if sort_completion_inst is not None: + sort_completion_inst.value = 0 + + +def disable_custom_sort_order(): + if sort_completion_inst is not None and sort_completion_inst.value == 0: + # Restore the original value of rl_sort_completion_matches + # before calling the completer again + sort_completion_inst.value = orig_sort_completion_value + + readline_path = ctypes.util.find_library('readline') sort_completion_inst = None if readline_path: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/sbd.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/sbd.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/sbd.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/sbd.py 2025-02-10 11:35:30.000000000 +0100 @@ -436,7 +436,7 @@ NO_SBD_WARNING = "Not configuring SBD - STONITH will be disabled." DISKLESS_SBD_MIN_EXPECTED_VOTE = 3 DISKLESS_SBD_WARNING = "Diskless SBD requires cluster with three or more nodes. If you want to use diskless SBD for 2-node cluster, should be combined with QDevice." - SBD_NOT_INSTALLED_MSG = "Package sbd is not installed." + SBD_NOT_INSTALLED_MSG = "Package sbd is not installed" FENCE_SBD_NOT_EXISTED_MSG = "fence_sbd command does not exist." SBD_RA = "stonith:fence_sbd" SBD_RA_ID = "stonith-sbd" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/ui_cluster.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/ui_cluster.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/ui_cluster.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/ui_cluster.py 2025-02-10 11:35:30.000000000 +0100 @@ -467,7 +467,7 @@ boot_context.cluster_is_running = ServiceManager(sh.ClusterShellAdaptorForLocalShell(sh.LocalShell())).service_is_active("pacemaker.service") boot_context.type = "init" boot_context.initialize_qdevice() - boot_context.validate_option() + boot_context.validate() bootstrap.bootstrap_init(boot_context) bootstrap.bootstrap_add(boot_context) @@ -526,7 +526,7 @@ join_context.stage = stage join_context.cluster_is_running = ServiceManager(sh.ClusterShellAdaptorForLocalShell(sh.LocalShell())).service_is_active("pacemaker.service") join_context.type = "join" - join_context.validate_option() + join_context.validate() bootstrap.bootstrap_join(join_context) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/ui_configure.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/ui_configure.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/ui_configure.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/ui_configure.py 2025-02-10 11:35:30.000000000 +0100 @@ -2,8 +2,10 @@ # Copyright (C) 2013 Kristoffer Gronlund <kgronl...@suse.com> # See COPYING for license information. +import os import re import time +from packaging import version from . import command from . import completers as compl from . import config @@ -191,6 +193,23 @@ return agent +def schema_completer(args): + complete_results = [] + + directory = '/usr/share/pacemaker/' + version_pattern = re.compile(r'^pacemaker-(\d+\.\d+)') + for filename in os.listdir(directory): + if version_pattern.match(filename): + complete_results.append(filename.strip('.rng')) + + if complete_results: + # Sort files using packaging.version + complete_results.sort(key=lambda x: version.parse(version_pattern.match(x).group(1))) + command.enable_custom_sort_order() + + return complete_results + + class CompletionHelp(object): ''' Print some help on whatever last word in the line. @@ -231,9 +250,7 @@ return [] elif '=' in completing: return [] - if command.sort_completion_inst is not None: - # Set the value to 0 to use the costum sort order - command.sort_completion_inst.value = 0 + command.enable_custom_sort_order() return utils.filter_keys(agent.params(), args) @@ -958,6 +975,7 @@ return cib_factory.upgrade_validate_with(force=config.core.force or force) @command.skill_level('administrator') + @command.completers(schema_completer) def do_schema(self, context, schema_st=None): "usage: schema [<schema>]" if not schema_st: @@ -1256,7 +1274,10 @@ if cib_factory.has_cib_changed(): if no_questions_asked or not options.interactive: ok = self._commit() - elif utils.ask("There are changes pending. Do you want to commit them?"): - ok = self._commit() + else: + confirm_msg = "There are changes pending. Do you want to commit them, or cancel the operation?" + rc = utils.ask(confirm_msg, cancel_option=True) + if rc: + ok = self._commit() cib_factory.reset() return ok diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/ui_context.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/ui_context.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/ui_context.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/ui_context.py 2025-02-10 11:35:30.000000000 +0100 @@ -143,12 +143,7 @@ # use the completer for the command ret = self.command_info.complete(self, tokens) if tokens: - last_token = tokens[-1] - if last_token: - ret = [t for t in ret if t.startswith(last_token)] - elif len(tokens) > 1: - # don't complete for the unknown token - ret = [t for t in ret if t in tokens[:-1]] + ret = [t for t in ret if t.startswith(tokens[-1])] if not ret or self.command_info.aliases: if not token in self.current_level().get_completions(): @@ -352,7 +347,10 @@ ''' Exit from the top level ''' - ok = self.current_level().end_game() + try: + ok = self.current_level().end_game() + except utils.TerminateSubCommand: + return if options.interactive and not options.batch: if constants.need_reset: utils.ext_cmd("reset") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/crmsh/utils.py new/crmsh-5.0.0+20250210.db3e9f28/crmsh/utils.py --- old/crmsh-5.0.0+20250123.155bd2c2/crmsh/utils.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/crmsh/utils.py 2025-02-10 11:35:30.000000000 +0100 @@ -289,7 +289,7 @@ return can_ask -def ask(msg, background_wait=True): +def ask(msg, background_wait=True, cancel_option=False): """Ask for user confirmation. Parameters: @@ -306,9 +306,10 @@ if not can_ask(background_wait): return False + option_str = "y/n" + "/c" if cancel_option else "" msg += ' ' if msg.endswith('? '): - msg = msg[:-2] + ' (y/n)? ' + msg = msg[:-2] + f' ({option_str})? ' while True: try: @@ -317,6 +318,8 @@ ans = 'n' if ans: ans = ans[0].lower() + if ans == 'c': + raise TerminateSubCommand if ans in 'yn': return ans == 'y' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/doc/crm.8.adoc new/crmsh-5.0.0+20250210.db3e9f28/doc/crm.8.adoc --- old/crmsh-5.0.0+20250123.155bd2c2/doc/crm.8.adoc 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/doc/crm.8.adoc 2025-02-10 11:35:30.000000000 +0100 @@ -222,16 +222,19 @@ ocf: stonith: systemd: crm(live)configure# primitive fence-1 stonith:<TAB><TAB> -apcmaster external/ippower9258 fence_legacy -apcmastersnmp external/kdumpcheck ibmhmc -apcsmart external/libvirt ipmilan +stonith:apcmaster stonith:fence_compute stonith:fence_ipmilanplus +stonith:apcmastersnmp stonith:fence_docker stonith:fence_ironic +stonith:apcsmart stonith:fence_drac5 stonith:fence_kdump +... -crm(live)configure# primitive fence-1 stonith:ipmilan params <TAB><TAB> -auth= hostname= ipaddr= login= password= port= priv= +crm(live)configure# primitive fence-1 stonith:fence_ipmilan params <TAB><TAB> +action= ip= passwd= pcmk_host_list= +auth= ipaddr= passwd_script= pcmk_host_map= +... -crm(live)configure# primitive fence-1 stonith:ipmilan params auth=<TAB><TAB> -auth* (string) - The authorization type of the IPMI session ("none", "straight", "md2", or "md5") +crm(live)configure# primitive fence-1 stonith:fence_ipmilan params auth=<TAB><TAB> +auth (select): IPMI Lan Auth type. + Allowed values: md5, password, none ............... `crmsh` also comes with bash completion usable directly from the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/scripts/sbd/main.yml new/crmsh-5.0.0+20250210.db3e9f28/scripts/sbd/main.yml --- old/crmsh-5.0.0+20250123.155bd2c2/scripts/sbd/main.yml 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/scripts/sbd/main.yml 2025-02-10 11:35:30.000000000 +0100 @@ -31,7 +31,7 @@ - include: sbd-device - cib: | - primitive {{id}} stonith:external/sbd + primitive {{id}} stonith:fence_sbd pcmk_delay_max=30s property stonith-enabled=true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/templates/sbd new/crmsh-5.0.0+20250210.db3e9f28/templates/sbd --- old/crmsh-5.0.0+20250123.155bd2c2/templates/sbd 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/templates/sbd 2025-02-10 11:35:30.000000000 +0100 @@ -6,7 +6,7 @@ # Shared storage based fencing. # -# This template generates a single instance of external/sbd. +# This template generates a single instance of fence_sbd. # # There is quite a bit more to do to make this stonith operational. # See http://www.linux-ha.org/wiki/SBD_Fencing for information. @@ -19,16 +19,8 @@ # %% id stonith-sbd %% id -# Name of the device (shared disk). -# NB: Make sure that the device remains the same on reboots. It's -# preferable to use udev generated names rather than the usual -# /dev/sd? -# %% sbd_device /dev/sda -%% sbd_device - %generate -primitive %_:id stonith:external/sbd - params sbd_device="%_:sbd_device" +primitive %_:id stonith:fence_sbd op monitor interval=15s timeout=60s op start timeout=60s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/test/testcases/ra new/crmsh-5.0.0+20250210.db3e9f28/test/testcases/ra --- old/crmsh-5.0.0+20250123.155bd2c2/test/testcases/ra 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/test/testcases/ra 2025-02-10 11:35:30.000000000 +0100 @@ -3,5 +3,4 @@ providers IPaddr2 providers Dummy info ocf:pacemaker:Dummy -info stonith:external/ssh . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/test/testcases/ra.exp new/crmsh-5.0.0+20250210.db3e9f28/test/testcases/ra.exp --- old/crmsh-5.0.0+20250123.155bd2c2/test/testcases/ra.exp 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/test/testcases/ra.exp 2025-02-10 11:35:30.000000000 +0100 @@ -46,106 +46,3 @@ reload-agent timeout=20s migrate_to timeout=20s migrate_from timeout=20s -.INP: info stonith:external/ssh -.EXT crm_resource --show-metadata stonith:external/ssh -.EXT stonithd metadata -ssh STONITH device (stonith:external/ssh) - -ssh-based host reset -Fine for testing, but not suitable for production! -Only reboot action supported, no poweroff, and, surprisingly enough, no poweron. - -Parameters (*: required, []: default): - -hostlist* (string): Hostlist - The list of hosts that the STONITH device controls - -livedangerously (enum): Live Dangerously!! - Set to "yes" if you want to risk your system's integrity. - Of course, since this plugin isn't for production, using it - in production at all is a bad idea. On the other hand, - setting this parameter to yes makes it an even worse idea. - Viva la Vida Loca! - -pcmk_host_argument (string, [port]): *** Advanced Use Only *** An alternate parameter to supply instead of 'port' - Some devices do not support the standard 'port' parameter or may provide additional ones. Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced. A value of "none" can be used to tell the cluster not to supply any additional parameters. - -pcmk_host_map (string): A mapping of node names to port numbers for devices that do not support node names. - For example, "node1:1;node2:2,3" would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2. - -pcmk_host_list (string): Nodes targeted by this device - Comma-separated list of nodes that can be targeted by this device (for example, "node1,node2,node3"). If pcmk_host_check is "static-list", either this or pcmk_host_map must be set. - -pcmk_host_check (select): How to determine which nodes can be targeted by the device - Use "dynamic-list" to query the device via the 'list' command; "static-list" to check the pcmk_host_list attribute; "status" to query the device via the 'status' command; or "none" to assume every device can fence every node. The default value is "static-list" if pcmk_host_map or pcmk_host_list is set; otherwise "dynamic-list" if the device supports the list operation; otherwise "status" if the device supports the status operation; otherwise "none" Allowed values: dynamic-list, static-list, status, none - Allowed values: dynamic-list, static-list, status, none - -pcmk_delay_max (time, [0s]): Enable a delay of no more than the time specified before executing fencing actions. - Enable a delay of no more than the time specified before executing fencing actions. Pacemaker derives the overall delay by taking the value of pcmk_delay_base and adding a random delay value such that the sum is kept below this maximum. - -pcmk_delay_base (string, [0s]): Enable a base delay for fencing actions and specify base delay value. - This enables a static delay for fencing actions, which can help avoid "death matches" where two nodes try to fence each other at the same time. If pcmk_delay_max is also used, a random delay will be added such that the total delay is kept below that value. This can be set to a single time value to apply to any node targeted by this device (useful if a separate device is configured for each target), or to a node map (for example, "node1:1s;node2:5") to set a different value for each target. - -pcmk_action_limit (integer, [1]): The maximum number of actions can be performed in parallel on this device - Cluster property concurrent-fencing="true" needs to be configured first. Then use this to specify the maximum number of actions can be performed in parallel on this device. A value of -1 means an unlimited number of actions can be performed in parallel. - -pcmk_reboot_action (string, [reboot]): *** Advanced Use Only *** An alternate command to run instead of 'reboot' - Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'reboot' action. - -pcmk_reboot_timeout (time, [60s]): *** Advanced Use Only *** Specify an alternate timeout to use for 'reboot' actions instead of stonith-timeout - Some devices need much more/less time to complete than normal.Use this to specify an alternate, device-specific, timeout for 'reboot' actions. - -pcmk_reboot_retries (integer, [2]): *** Advanced Use Only *** The maximum number of times to try the 'reboot' command within the timeout period - Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'reboot' action before giving up. - -pcmk_off_action (string, [off]): *** Advanced Use Only *** An alternate command to run instead of 'off' - Some devices do not support the standard commands or may provide additional ones.Use this to specify an alternate, device-specific, command that implements the 'off' action. - -pcmk_off_timeout (time, [60s]): *** Advanced Use Only *** Specify an alternate timeout to use for 'off' actions instead of stonith-timeout - Some devices need much more/less time to complete than normal.Use this to specify an alternate, device-specific, timeout for 'off' actions. - -pcmk_off_retries (integer, [2]): *** Advanced Use Only *** The maximum number of times to try the 'off' command within the timeout period - Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'off' action before giving up. - -pcmk_on_action (string, [on]): *** Advanced Use Only *** An alternate command to run instead of 'on' - Some devices do not support the standard commands or may provide additional ones.Use this to specify an alternate, device-specific, command that implements the 'on' action. - -pcmk_on_timeout (time, [60s]): *** Advanced Use Only *** Specify an alternate timeout to use for 'on' actions instead of stonith-timeout - Some devices need much more/less time to complete than normal.Use this to specify an alternate, device-specific, timeout for 'on' actions. - -pcmk_on_retries (integer, [2]): *** Advanced Use Only *** The maximum number of times to try the 'on' command within the timeout period - Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'on' action before giving up. - -pcmk_list_action (string, [list]): *** Advanced Use Only *** An alternate command to run instead of 'list' - Some devices do not support the standard commands or may provide additional ones.Use this to specify an alternate, device-specific, command that implements the 'list' action. - -pcmk_list_timeout (time, [60s]): *** Advanced Use Only *** Specify an alternate timeout to use for 'list' actions instead of stonith-timeout - Some devices need much more/less time to complete than normal.Use this to specify an alternate, device-specific, timeout for 'list' actions. - -pcmk_list_retries (integer, [2]): *** Advanced Use Only *** The maximum number of times to try the 'list' command within the timeout period - Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'list' action before giving up. - -pcmk_monitor_action (string, [monitor]): *** Advanced Use Only *** An alternate command to run instead of 'monitor' - Some devices do not support the standard commands or may provide additional ones.Use this to specify an alternate, device-specific, command that implements the 'monitor' action. - -pcmk_monitor_timeout (time, [60s]): *** Advanced Use Only *** Specify an alternate timeout to use for 'monitor' actions instead of stonith-timeout - Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'monitor' actions. - -pcmk_monitor_retries (integer, [2]): *** Advanced Use Only *** The maximum number of times to try the 'monitor' command within the timeout period - Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'monitor' action before giving up. - -pcmk_status_action (string, [status]): *** Advanced Use Only *** An alternate command to run instead of 'status' - Some devices do not support the standard commands or may provide additional ones.Use this to specify an alternate, device-specific, command that implements the 'status' action. - -pcmk_status_timeout (time, [60s]): *** Advanced Use Only *** Specify an alternate timeout to use for 'status' actions instead of stonith-timeout - Some devices need much more/less time to complete than normal.Use this to specify an alternate, device-specific, timeout for 'status' actions. - -pcmk_status_retries (integer, [2]): *** Advanced Use Only *** The maximum number of times to try the 'status' command within the timeout period - Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'status' action before giving up. - -Operations' defaults (advisory minimum): - - start timeout=20s - stop timeout=15s - status timeout=20s - monitor timeout=20s interval=3600s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/test/testcases/ra.filter new/crmsh-5.0.0+20250210.db3e9f28/test/testcases/ra.filter --- old/crmsh-5.0.0+20250123.155bd2c2/test/testcases/ra.filter 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/test/testcases/ra.filter 2025-02-10 11:35:30.000000000 +0100 @@ -12,6 +12,5 @@ n==1 { n=0; print reduce(a); next; } /providers IPaddr/ { n=1; } /providers Dummy/ { n=1; } -/^ssh STONITH/ { sub(" external",""); } /^state \(string, \[(.*)\]\):/ { gsub(/\[.*\]/, "[state-file]") } { print } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-5.0.0+20250123.155bd2c2/test/unittests/test_bootstrap.py new/crmsh-5.0.0+20250210.db3e9f28/test/unittests/test_bootstrap.py --- old/crmsh-5.0.0+20250123.155bd2c2/test/unittests/test_bootstrap.py 2025-01-23 08:03:29.000000000 +0100 +++ new/crmsh-5.0.0+20250210.db3e9f28/test/unittests/test_bootstrap.py 2025-02-10 11:35:30.000000000 +0100 @@ -166,20 +166,26 @@ mock_error.assert_called_once_with("Can't configure stage sbd: sbd.service already running! Please use crm option '-F' if need to redeploy") mock_active.assert_called_once_with("sbd.service") + @mock.patch('crmsh.utils.fatal') + @mock.patch('crmsh.utils.list_cluster_nodes') @mock.patch('crmsh.utils.package_is_installed') @mock.patch('crmsh.utils.check_all_nodes_reachable') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - def test_validate_sbd_option_error_sbd_stage(self, mock_active, mock_check_all, mock_installed): + def test_validate_sbd_option_error_sbd_stage(self, mock_check_all, mock_installed, mock_list, mock_fatal): + mock_fatal.side_effect = ValueError + mock_list.return_value = ["node1", "node2"] options = mock.Mock(stage="sbd", diskless_sbd=True, cluster_is_running=True) - mock_installed.return_value = True + mock_installed.side_effect = [True, False] ctx = crmsh.bootstrap.Context() ctx.stage = "sbd" ctx.diskless_sbd = True ctx.cluster_is_running = True - mock_active.return_value = False - ctx._validate_sbd_option() - mock_active.assert_called_once_with("sbd.service") + with self.assertRaises(ValueError): + ctx._validate_sbd_option() mock_check_all.assert_called_once_with() + mock_installed.assert_has_calls([ + mock.call("sbd", "node1"), + mock.call("sbd", "node2") + ]) @mock.patch('crmsh.utils.fatal') @mock.patch('socket.gethostbyname') @@ -210,13 +216,15 @@ @mock.patch('logging.Logger.warning') @mock.patch('crmsh.bootstrap.Validation.valid_admin_ip') - def test_validate_option(self, mock_admin_ip, mock_warn): + @mock.patch('crmsh.utils.package_is_installed') + def test_validate(self, mock_installed, mock_admin_ip, mock_warning): + mock_installed.side_effect = [True, True] ctx = crmsh.bootstrap.Context() ctx.admin_ip = "10.10.10.123" ctx.qdevice_inst = mock.Mock() ctx._validate_sbd_option = mock.Mock() ctx._validate_nodes_option = mock.Mock() - ctx.validate_option() + ctx.validate() mock_admin_ip.assert_called_once_with("10.10.10.123") ctx.qdevice_inst.valid_qdevice_options.assert_called_once_with() ctx._validate_sbd_option.assert_called_once_with()