Skip to content

Commit

Permalink
[crmsh-4.6] Use crm_attribute --list-options (#1646)
Browse files Browse the repository at this point in the history
backport #1379
  • Loading branch information
liangxin1300 authored Jan 2, 2025
2 parents 9fab03a + a802e6e commit ebef61d
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 7 deletions.
4 changes: 3 additions & 1 deletion crmsh/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@
meta_progs_20 = ("pacemaker-controld", "pacemaker-schedulerd", "pacemaker-fenced", "pacemaker-based")

# elide these properties from tab completion
crmd_metadata_do_not_complete = ("dc-version",
controld_metadata_do_not_complete = ("dc-version",
"cluster-infrastructure",
"crmd-integration-timeout",
"crmd-finalization-timeout",
Expand Down Expand Up @@ -511,6 +511,8 @@
RSC_ROLE_PROMOTED_LEGACY = "Master"
RSC_ROLE_UNPROMOTED_LEGACY = "Slave"
PCMK_VERSION_DEFAULT = "2.0.0"
# pacemaker 2.1.8 introduced `crm_attribute --list-options`
PCMK_MIN_VERSION_SUPPORT_LIST_OPTIONS = "2.1.8"

COROSYNC_STATUS_TYPES = ("ring", "quorum", "qdevice", "qnetd", "cpg")

Expand Down
39 changes: 35 additions & 4 deletions crmsh/ra.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def get_pe_meta():
@utils.memoize
def get_crmd_meta():
return RAInfo(utils.pacemaker_controld(), "metadata",
exclude_from_completion=constants.crmd_metadata_do_not_complete)
exclude_from_completion=constants.controld_metadata_do_not_complete)


@utils.memoize
Expand All @@ -253,6 +253,13 @@ def get_cib_meta():

@utils.memoize
def get_properties_meta():
cluster_option_meta = utils.get_cluster_option_metadata()
if cluster_option_meta:
return RAInfo("cluster_option", None,
exclude_from_completion=constants.controld_metadata_do_not_complete,
meta_string=cluster_option_meta)
# get_xxx_meta() is a legacy code to get the metadata of the pacemaker daemons,
# which will be dropped when we fully adopt to crmsh-5.x with pacemaker 3.x.
meta = copy.deepcopy(get_crmd_meta())
meta.add_ra_params(get_pe_meta())
meta.add_ra_params(get_cib_meta())
Expand Down Expand Up @@ -308,7 +315,7 @@ class RAInfo(object):
skip_ops = ("meta-data", "validate-all")
skip_op_attr = ("name",)

def __init__(self, ra_class, ra_type, ra_provider="heartbeat", exclude_from_completion=None):
def __init__(self, ra_class, ra_type, ra_provider="heartbeat", exclude_from_completion=None, meta_string=None):
self.excluded_from_completion = exclude_from_completion or []
self.ra_class = ra_class
self.ra_type = ra_type
Expand All @@ -317,6 +324,7 @@ def __init__(self, ra_class, ra_type, ra_provider="heartbeat", exclude_from_comp
self.ra_provider = "heartbeat"
self.ra_elem = None
self.broken_ra = False
self.meta_string = meta_string

def __str__(self):
return "%s:%s:%s" % (self.ra_class, self.ra_provider, self.ra_type) \
Expand Down Expand Up @@ -684,7 +692,9 @@ def meta(self):
sid = "ra_meta-%s" % self
if cache.is_cached(sid):
return cache.retrieve(sid)
if self.ra_class in constants.meta_progs:
if self.meta_string:
l = self.meta_string.split('\n')
elif self.ra_class in constants.meta_progs:
l = prog_meta(self.ra_class)
elif self.ra_class in constants.meta_progs_20:
l = prog_meta(self.ra_class)
Expand All @@ -697,6 +707,8 @@ def meta(self):
except Exception:
self.error("Cannot parse meta-data XML")
return None
if xml.tag == "pacemaker-result":
xml = xml.xpath("//resource-agent")[0]
self.debug("read and cached meta-data")
return cache.store(sid, xml)

Expand Down Expand Up @@ -758,10 +770,29 @@ def meta_param_head():
return ""
l = [head]
longdesc = get_nodes_text(n, "longdesc")
select_values = self.get_selecte_value_list(n)
if n.get("advanced") == "1":
l.append(self.ra_tab + "*** Advanced Use Only ***")
if n.get("generated") == "1":
l.append(self.ra_tab + "*** Automatically generated by pacemaker ***")
if n.find("deprecated") is not None:
l.append(self.ra_tab + "*** Deprecated ***")
if longdesc:
l.append(self.ra_tab + longdesc.replace("\n", "\n" + self.ra_tab) + '\n')
l.append(self.ra_tab + longdesc.replace("\n", "\n" + self.ra_tab))
if select_values:
l.append(self.ra_tab + "Allowed values: " + ', '.join(select_values))
l.append('')
return '\n'.join(l)

def get_selecte_value_list(self, node):
"""
Get the list of select values from the node
"""
content = node.find("content")
if content is None:
return []
return [x.get("value") for x in content.findall("option")]

def meta_parameter(self, param):
if self.mk_ra_node() is None:
return ''
Expand Down
19 changes: 18 additions & 1 deletion crmsh/ui_ra.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
from . import ra
from . import constants
from . import options
from . import log


logger = log.setup_logger(__name__)


def complete_class_provider_type(args):
Expand Down Expand Up @@ -108,12 +112,25 @@ def do_info(self, context, *args):
"usage: info [<class>:[<provider>:]]<type>"
if len(args) == 0:
context.fatal_error("Expected [<class>:[<provider>:]]<type>")
elif len(args) > 1: # obsolete syntax
if args[0] == "cluster":
meta_string = utils.get_cluster_option_metadata(show_xml=False)
if not meta_string:
context.fatal_error("No metadata found for cluster option (supports since pacemaker 2.1.8)")
utils.page_string(meta_string)
return True
if len(args) > 1: # obsolete syntax
if len(args) < 3:
ra_type, ra_class, ra_provider = args[0], args[1], "heartbeat"
else:
ra_type, ra_class, ra_provider = args[0], args[1], args[2]
elif args[0] in constants.meta_progs:
if utils.is_min_pcmk_ver(constants.PCMK_MIN_VERSION_SUPPORT_LIST_OPTIONS):
if args[0] == "stonithd":
alternative = r"`crm ra info pacemaker-fenced`"
else:
alternative = r"`crm configure property <property_name> --help`"
warning_msg = f"`crm ra info {args[0]}` is deprecated and is replaced by {alternative} going forward."
logger.warning(warning_msg)
ra_class, ra_provider, ra_type = args[0], None, None
elif args[0] in constants.meta_progs_20:
ra_class, ra_provider, ra_type = args[0], None, None
Expand Down
9 changes: 9 additions & 0 deletions crmsh/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ def isexec(filename):
return None


def get_cluster_option_metadata(show_xml=True) -> str:
output_type = "xml" if show_xml else "text"
cmd = f"crm_attribute --list-options=cluster --all --output-as={output_type}"
rc, out, _ = ShellUtils().get_stdout_stderr(cmd)
if rc == 0 and out:
return out
return None


def pacemaker_20_daemon(new, old):
"helper to discover renamed pacemaker daemons"
if is_program(new):
Expand Down
4 changes: 3 additions & 1 deletion doc/crm.8.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3508,7 +3508,9 @@ primitive A ocf:pacemaker:Dummy \
Set cluster configuration properties. To list the
available cluster configuration properties, use the
<<cmdhelp_ra_info,`ra info`>> command with +pengine+, +crmd+,
+cib+ and +stonithd+ as arguments.
+cib+ and +stonithd+ as arguments; Since pacemaker 2.1.8,
use the <<cmdhelp_ra_info,`ra info`>> command with +cluster+ as an argument.

When setting the +maintenance-mode+ property, it will
inform the user if there are nodes or resources that
have the +maintenance+ property.
Expand Down
1 change: 1 addition & 0 deletions test/testcases/acl.exp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
.INP: acl_target cyrus cyrus-role
.INP: _test
.INP: verify
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
Expand Down
1 change: 1 addition & 0 deletions test/testcases/bundle.exp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
.INP: property stonith-enabled=true
.INP: _test
.INP: verify
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
Expand Down
2 changes: 2 additions & 0 deletions test/testcases/confbasic.exp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ INFO: 37: "collocation" is accepted as "colocation"
.INP: _test
.INP: verify
WARNING: 53: c2: resource d1 is grouped, constraints should apply to the group
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
Expand Down Expand Up @@ -194,6 +195,7 @@ WARNING: 55: c2: resource d1 is grouped, constraints should apply to the group
INFO: 'maintenance' attribute already exists in d1. Remove it? [YES]
INFO: 'maintenance' attribute already exists in g1. Remove it? [YES]
INFO: 'maintenance' attribute already exists in node1. Remove it? [YES]
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
1 change: 1 addition & 0 deletions test/testcases/edit.exp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ rsc_defaults rsc_options: \
op_defaults op-options: \
timeout=60s
.INP: commit
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
Expand Down
1 change: 1 addition & 0 deletions test/testcases/file.exp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ op_defaults op-options: \
.INP: property cluster-recheck-interval="10m"
.INP: load update sample.txt
ERROR: 4: syntax: Unknown command near <op> parsing 'op stop timeout=20s interval=0s'
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
Expand Down
1 change: 1 addition & 0 deletions test/testcases/newfeatures.exp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ alert notify_9 "/usr/share/pacemaker/alerts/alert_snmp.sh" \
to 192.168.40.9
.INP: _test
.INP: verify
.EXT crm_attribute --list-options=cluster --all --output-as=xml
.EXT crmd metadata
.EXT pengine metadata
.EXT cib metadata
Expand Down

0 comments on commit ebef61d

Please sign in to comment.