From 1f8c7ccb9a405d6a53898936cb4ef99da6b00369 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 24 Mar 2026 14:37:16 -0400 Subject: [PATCH 1/9] Refactor: build: Add BUILD_DATE as a subsitutable variable. Man pages should have the date they were last built as a part of their title information, so define a variable that we can use for that purpose. Ref T638 --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 4204b86fa15..54e4b722a2c 100644 --- a/configure.ac +++ b/configure.ac @@ -610,6 +610,8 @@ api_schemas="$(schemas_for_make "xml/api")" CONFIG_STATUS_DEPENDENCIES="$cib_schemas $api_schemas" AC_SUBST(CONFIG_STATUS_DEPENDENCIES) +AC_SUBST(BUILD_DATE, [$(date +"%Y-%m-%d")]) + dnl ============================================== dnl Process simple options From 013230d474426dcf9c752a09b2b9858ea48b0146 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 24 Mar 2026 14:04:19 -0400 Subject: [PATCH 2/9] Doc: man: Add a hand-written man page for attrd_updater. There are various pros and cons for this. The most obvious cons are that we have to keep the man page up-to-date when we modify the command line tool and that we have to write groff now. The most obvious pros are that we can write better documentation that's not constrained by having to fit in --help output. Ref T638 --- configure.ac | 2 + doc/Makefile.am | 6 +- doc/man/Makefile.am | 11 ++ doc/man/attrd_updater.8.in | 226 +++++++++++++++++++++++++++++++++++++ mk/man.mk | 3 +- tools/attrd_updater.8.inc | 5 - 6 files changed, 244 insertions(+), 9 deletions(-) create mode 100644 doc/man/Makefile.am create mode 100644 doc/man/attrd_updater.8.in delete mode 100644 tools/attrd_updater.8.inc diff --git a/configure.ac b/configure.ac index 54e4b722a2c..b7ab964da76 100644 --- a/configure.ac +++ b/configure.ac @@ -2030,6 +2030,8 @@ AC_CONFIG_FILES(Makefile \ devel/Makefile \ doc/Doxyfile \ doc/Makefile \ + doc/man/Makefile \ + doc/man/attrd_updater.8 \ doc/sphinx/Makefile \ etc/Makefile \ etc/init.d/pacemaker \ diff --git a/doc/Makefile.am b/doc/Makefile.am index 140786596ce..f206b29d8e5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2003-2025 the Pacemaker project contributors +# Copyright 2003-2026 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -25,7 +25,7 @@ dist_mib_DATA = PCMK-MIB.txt noinst_SCRIPTS = abi-check -SUBDIRS = sphinx +SUBDIRS = man sphinx EXTRA_DIST = clusterlabs-logo-55x55.png @@ -58,7 +58,7 @@ global-clean: # Man pages as HTML -MANPAGE_DIRS = ../agents ../daemons ../tools +MANPAGE_DIRS = ../agents ../daemons man ../tools %.8.html: %.8 groff -mandoc `man -w ./$<` -T html > $@ diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am new file mode 100644 index 00000000000..3d6533d441c --- /dev/null +++ b/doc/man/Makefile.am @@ -0,0 +1,11 @@ +# +# Copyright 2026 the Pacemaker project contributors +# +# The version control history for this file may have further details. +# +# This source code is licensed under the GNU General Public License version 2 +# or later (GPLv2+) WITHOUT ANY WARRANTY. +# +include $(top_srcdir)/mk/common.mk + +man8_MANS = attrd_updater.8 diff --git a/doc/man/attrd_updater.8.in b/doc/man/attrd_updater.8.in new file mode 100644 index 00000000000..f2db847908d --- /dev/null +++ b/doc/man/attrd_updater.8.in @@ -0,0 +1,226 @@ +.TH ATTRD_UPDATER "8" "@BUILD_DATE@" "@PACKAGE@ @VERSION@" "Pacemaker Manual" +.SH "NAME" +attrd_updater \- query and update Pacemaker node attributes +. +.SH "SYNOPSIS" +.SY attrd_updater +.B { \-n \fIattribute\fB \|| \-P \fIpattern\fB } +.RI [ option\~ ...] +.YS +. +.SH "DESCRIPTION" +.B attrd_updater +manages transient and private node attributes. Transient node attributes are +recorded in the CIB, but will be erased when the cluster is restarted. Private +node attributes are never recorded in the CIB. They exist only in memory in the +Pacemaker attribute daemon (\fBpacemaker\-attrd\fR) and will therefore also be +erased when the cluster is restarted. +.P +.B attrd_updater +can also be used to create attributes for cluster nodes that do not yet exist, +and can manage how often attribute changes are flushed to the CIB (called +"dampening") to minimize disk writes for frequent changes. It is also used by +resource agents, particularly node health agents, for setting and querying +node status. +. +.SH "OPTIONS" +.SS "Required arguments" +One of the following arguments must be provided. These arguments are mutually +exclusive. +.TP +.BR \-n ", " \-\-name =\fINAME\fR +The attribute's name. +.TP +.BR \-P ", " \-\-pattern =\fIPATTERN\fR +Operate on all attributes matching this pattern (with \fB\-B\fR, \fB\-D\fR, +\fB\-U\fR, or \fB\-Y\fR). Patterns are regular expressions as understood by +.MR regex 7 . +. +.SS "Commands" +One of the following commands must be provided. These options are mutually +exclusive. +.TP +.BR \-B ", " \-\-update\-both =\fIVALUE\fR +Set the value of the given attribute (creating it if it does not already exist), +or all attributes matched by the given pattern, to \fIVALUE\fR. Additionally, +set the attribute's time to wait (dampening) in the attribute manager to the +value given by \fB\-\-delay\fR/\fB\-d\fR. If this changes the value or dampening, +the attribute will also be written to the cluster configuration, so be aware +that repeatedly changing the dampening reduces its effectiveness. +.TP +.BR \-D ", " \-\-delete +Unset the value of the given attribute, or all attributes matched by the given +pattern, in the attribute manager. At the moment, there is no way to remove +an attribute. This option will instead set its value to the empty string. +.TP +.BR \-N ", " \-\-node =\fINODE\fR +Use \fINODE\fR as the node for setting and querying the attribute instead of +the local one. +.TP +.BR \-Q ", " \-\-query +Query the attribute's value from the attribute manager. By default, this will +query the value of the attribute on the local node. Use \fB\-\-node\fR/\fB\-N\fR +for the value on a given node, or \fB\-\-all\fR/\fB\-A\fR for the value on all +nodes. +.TP +.BR \-R ", " \-\-refresh +(Advanced) Force the attribute manager to resend all current values to the CIB. +.TP +.BR \-U ", " \-\-update =\fIVALUE\fR +Set the value of the given attribute (creating it if it does not already exist), +or all attributes matched by the given pattern, to \fIVALUE\fR. If +\fB\-\-delay\fR/\fB\-d\fR is specified, the delay will be used if the attribute +needs to be created and ignored otherwise. +.TP +.BR \-Y ", " \-\-update-delay +Set the dampening in the attribute manager for the given attribute, or all +attributes matched by the given pattern, to the value given by +\fB\-\-delay\fR/\fB\-d\fR. If this changes the dampening, the attribute will +also be written to the cluster configuration, so be aware that repeatedly +changing the dampening reduces its effectiveness. +. +.SS "Additional options" +.TP +.BR \-A ", " \-\-all +Show values of the given attribute on all nodes (query only). +.TP +.BR \-d ", " \-\-delay =\fISECONDS\fR +The time to wait (dampening) for further changes before sending to the CIB. +.TP +.BR \-l ", " \-\-lifetime =\fITIMESPEC\fR +Use the ISO-8601 \fITIMESPEC\fR as the lifetime of the attribute. \fITIMESPEC\fR +is given according to +.UR https://\:en\:.wikipedia\:.org/\:wiki/\:ISO_8601#Durations +.UE . +This option is not yet implemented and will be silently ignored by the cluster. +.TP +.BR \-p ", " \-\-private +If a new attribute is created, do not write it to the CIB. +.TP +.BR \-s ", " \-\-set =\fISET\fR +(Advanced) The attribute set in which to place the value. +.TP +.BR \-w ", " \-\-wait =\fIUNTIL\fR +Wait for some event to occur before returning to the shell. Values are: +.RS +.IP \fIno\fR (default) +Wait only for the attribute manager to acknowledge the request. +.IP \fIlocal\fR +Wait until the change has propagated to where a local query will return the +request value, or the value set by a later request. +.IP \fIcluster\fR +Wait until the change has propagated to where a query anywhere on the cluster +will return the requested value, or the value set by a later request. +.RE +.TP +.BR \-z ", " \-\-utilization +When creating a new attribute, create it as a node utilization attribute +instead of an instance attribute. If the attribute already exists, its +existing type will be used regardless (with \fB\-B\fR, \fB\-U\fR, or \fB\-Y\fR). +. +.SS "Output options" +.TP +.BI \-\-output\-as= FORMAT +Specify output format as one of: text (default), xml. +.TP +.BI \-\-output\-to= DEST +Specify file name for output (or "\-" for stdout). +. +.SS "Help options" +.TP +.BR \-h ", " \-\-help +Show basic help options. +.TP +.B \-\-help\-additional +Show additional options. +.TP +.B \-\-help\-all +Show all help options. +.TP +.B \-\-help\-command +Show program commands. +.TP +.B \-\-help\-output +Show output-related help options. +.TP +.B \-\-help\-required +Show required arguments. +. +.SS "Application options" +.TP +.BR \-$ ", " \-\-version +Display software version and exit. +.TP +.BR \-V ", " \-\-verbose +Increase debug output (may be specified multiple times). +. +.SH "EXIT STATUS" +This is not an exhaustive list of exit statuses for \fBattrd_updater\fR. See +.MR crm_error 8 +for more information on converting between error codes and their names. +.TP +.B CRM_EX_CONFIG +The given attribute does not exist. +.TP +.B ENOTCONN, ECONNREFUSED +\fBattrd_updater\fR had problems connecting to or communicating with +\fBpacemaker-attrd\fR. +. +.SH "EXAMPLES" +.EX +# \fBattrd_updater \-n "#health-cpu" \-Q +.EE +.RS +Query the value of the \fB#health\-cpu\fR attribute on the current node +.RE +.P +.EX +# \fBattrd_updater \-n "#health-cpu" \-Q \-A +.EE +.RS +Query the value of the \fB#health\-cpu\fR attribute on all cluster nodes +.RE +.P +.EX +# \fBattrd_updater \-n ABC \-U 111 +.EE +.RS +Set the value of the \fBABC\fR attribute to \fB111\fR on the current node +.RE +.P +.EX +# \fBattrd_updater \-n ABD \-U 222 \-w cluster +.EE +.RS +Set the value of the \fBABD\fR attribute to \fB222\fR on the current node, and +do not return until this change has propagated to all cluster nodes +.RE +.P +.EX +# \fBattrd_updater \-n ABE \-U 333 \-Y \-d 15 +.EE +.RS +Set the value of the \fBABE\fR attribute to \fB333\fR on the current node, and +wait 15 seconds before sending any changes to this attribute to the CIB +.RE +.P +.EX +# \fBattrd_updater \-P "AB.*" \-D +.EE +.RS +Unset the value of all attributes matching the regular expression \fBAB.*\fR +.RE +. +.SH "REPORTING BUGS" +Report bugs to https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker +. +.SH "COPYRIGHT" +Copyright © 2004-2026 the Pacemaker project contributors. +.P +This program is licensed under the GNU General Public License version 2 or +later (GPLv2+) WITHOUT ANY WARRANTY. +. +.SH "SEE ALSO" +.BR crm_attribute (8), +.BR crm_error (8), +.BR regex (7) diff --git a/mk/man.mk b/mk/man.mk index bf8ac5d991d..5631353c270 100644 --- a/mk/man.mk +++ b/mk/man.mk @@ -21,7 +21,8 @@ # if BUILD_HELP -man8_MANS = $(sbin_PROGRAMS:%=%.8) $(sbin_SCRIPTS:%=%.8) +manpages = $(sbin_PROGRAMS:%=%.8) $(sbin_SCRIPTS:%=%.8) +man8_MANS = $(filter-out attrd_updater.8,$(manpages)) HELP2MAN_ARGS = -N --section 8 --name "Part of the Pacemaker cluster resource manager" diff --git a/tools/attrd_updater.8.inc b/tools/attrd_updater.8.inc deleted file mode 100644 index 780e6a49adb..00000000000 --- a/tools/attrd_updater.8.inc +++ /dev/null @@ -1,5 +0,0 @@ -[synopsis] -attrd_updater {-n | -P } [options] - -/node attributes/ -.SH OPTIONS From 985cec234f4f8828d7ea84a91741228109d414b4 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 28 Apr 2026 15:48:29 -0400 Subject: [PATCH 3/9] Refactor: tools: Simplify attrd_updater help output. With an improved man page, we now have the problem that everything is duplicated between the help output and the man page. I think the man page makes a better source of documentation, so I've made the following changes to the help output: * Simplify every option's description down to just a single sentence * Be more consistent in line wrapping (wish there were an automated way to do this in glib) * Be more consistent with the phrasing of the Required/with parts and put them on their own lines Ref T638 --- tools/attrd_updater.c | 72 +++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/tools/attrd_updater.c b/tools/attrd_updater.c index 6dca3a51f91..660fa82af96 100644 --- a/tools/attrd_updater.c +++ b/tools/attrd_updater.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2025 the Pacemaker project contributors + * Copyright 2004-2026 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -141,46 +141,32 @@ static GOptionEntry required_entries[] = { static GOptionEntry command_entries[] = { { "update", 'U', 0, G_OPTION_ARG_CALLBACK, command_cb, - "Update attribute's value. Required: -n/--name or -P/--pattern.\n" - INDENT "Optional: -d/--delay (if specified, the delay will be used if\n" - INDENT "the attribute needs to be created, but ignored if the\n" - INDENT "attribute already exists), -s/--set, -p/--private, -W/--wait,\n" - INDENT "-z/--utilization.", + "Update attribute's value\n" + INDENT "Required: -n/--name or -P/--pattern.", "VALUE" }, { "update-both", 'B', 0, G_OPTION_ARG_CALLBACK, command_cb, - "Update attribute's value and time to wait (dampening) in the\n" - INDENT "attribute manager. If this changes the value or dampening,\n" - INDENT "the attribute will also be written to the cluster configuration,\n" - INDENT "so be aware that repeatedly changing the dampening reduces its\n" - INDENT "effectiveness.\n" - INDENT "Requires -d/--delay", + "Update attribute's value and time to wait (dampening)\n" + INDENT "in the attribute manager\n" + INDENT "Required: -d/--delay", "VALUE" }, { "update-delay", 'Y', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Update attribute's dampening in the attribute manager. If this\n" - INDENT "changes the dampening, the attribute will also be written\n" - INDENT "to the cluster configuration, so be aware that repeatedly\n" - INDENT "changing the dampening reduces its effectiveness.\n" - INDENT "Requires -d/--delay", + "Update attribute's dampening in the attribute manager\n" + INDENT "Required: -d/--delay", NULL }, { "query", 'Q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Query the attribute's value from the attribute manager. By default\n" - INDENT "this will query the value of the attribute on the local node.\n" - INDENT "Use -N/--node for the value on a given node, or -A/--all for the\n" - INDENT "value on all nodes.", + "Query the attribute's value from the attribute manager", NULL }, { "delete", 'D', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Unset attribute from the attribute manager. At the moment, there is no\n" - INDENT "way to remove an attribute. This option will instead set its\n" - INDENT "value to the empty string.", + "Unset attribute from the attribute manager", NULL }, { "refresh", 'R', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "(Advanced) Force the attribute manager to resend all current\n" - INDENT "values to the CIB", + "(Advanced) Force the attribute manager to resend all\n" + INDENT "current values to the CIB", NULL }, { NULL } @@ -188,46 +174,44 @@ static GOptionEntry command_entries[] = { static GOptionEntry addl_entries[] = { { "delay", 'd', 0, G_OPTION_ARG_STRING, &options.attr_dampen, - "The time to wait (dampening) in seconds for further changes\n" + "The time to wait (dampening) for further changes\n" INDENT "before sending to the CIB", "SECONDS" }, { "set", 's', 0, G_OPTION_ARG_STRING, &options.attr_set, - "(Advanced) The attribute set in which to place the value", + "(Advanced) The attribute set in which to place the\n" + INDENT "value", "SET" }, { "node", 'N', 0, G_OPTION_ARG_STRING, &options.attr_node, - "Use the named node for setting and querying the attribute (instead\n" - INDENT "of the local one)", + "Use the named node for setting and querying the\n" + INDENT "attribute (instead of the local one)", "NODE" }, { "all", 'A', 0, G_OPTION_ARG_NONE, &options.query_all, - "Show values of the attribute for all nodes (query only)", + "Show values of the attribute for all nodes (query\n" + INDENT "only)", NULL }, { "lifetime", 'l', 0, G_OPTION_ARG_CALLBACK, section_cb, - "(Not yet implemented) Lifetime of the node attribute (silently\n" - INDENT "ignored by cluster)", + "(Not yet implemented) Lifetime of the node attribute\n" + INDENT "(silently ignored by cluster)", "SECTION" }, { "private", 'p', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, private_cb, - "If this creates a new attribute, never write the attribute to CIB", + "If this creates a new attribute, never write the\n" + INDENT "attribute to CIB", NULL }, { "wait", 'W', 0, G_OPTION_ARG_CALLBACK, wait_cb, - "Wait for some event to occur before returning. Values are 'no' (wait\n" - INDENT "only for the attribute daemon to acknowledge the request),\n" - INDENT "'local' (wait until the change has propagated to where a local\n" - INDENT "query will return the request value, or the value set by a\n" - INDENT "later request), or 'cluster' (wait until the change has propagated\n" - INDENT "to where a query anywhere on the cluster will return the requested\n" - INDENT "value, or the value set by a later request). Default is 'no'.", + "Wait for some event to occur before returning\n" + INDENT "Values: 'no' (default), 'local', 'cluster'", "UNTIL" }, { "utilization", 'z', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, attr_set_type_cb, - "When creating a new attribute, create it as a node utilization attribute\n" - INDENT "instead of an instance attribute. If the attribute already exists,\n" - INDENT "its existing type (utilization vs. instance) will be used regardless.\n" + "When creating a new attribute, create it as a node\n" + INDENT "utilization attribute instead of an instance\n" + INDENT "attribute\n" INDENT "(with -B, -U, -Y)", NULL }, From a531f3105eaf7792e26519c165d345e7cbc0f5f9 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 24 Mar 2026 14:49:17 -0400 Subject: [PATCH 4/9] Doc: man: Add a hand-written man page for cibadmin. Ref T638 --- configure.ac | 1 + doc/man/Makefile.am | 1 + doc/man/cibadmin.8.in | 328 ++++++++++++++++++++++++++++++++++++++++++ mk/man.mk | 2 +- tools/cibadmin.8.inc | 5 - 5 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 doc/man/cibadmin.8.in delete mode 100644 tools/cibadmin.8.inc diff --git a/configure.ac b/configure.ac index b7ab964da76..0c3e7038234 100644 --- a/configure.ac +++ b/configure.ac @@ -2032,6 +2032,7 @@ AC_CONFIG_FILES(Makefile \ doc/Makefile \ doc/man/Makefile \ doc/man/attrd_updater.8 \ + doc/man/cibadmin.8 \ doc/sphinx/Makefile \ etc/Makefile \ etc/init.d/pacemaker \ diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 3d6533d441c..ac89008c74b 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -9,3 +9,4 @@ include $(top_srcdir)/mk/common.mk man8_MANS = attrd_updater.8 +man8_MANS += cibadmin.8 diff --git a/doc/man/cibadmin.8.in b/doc/man/cibadmin.8.in new file mode 100644 index 00000000000..fece828fc33 --- /dev/null +++ b/doc/man/cibadmin.8.in @@ -0,0 +1,328 @@ +.TH CIBADMIN "8" "@BUILD_DATE@" "@PACKAGE@ @VERSION@" "Pacemaker Manual" +.SH "NAME" +cibadmin \- query and edit the cluster information base +. +.SH "SYNOPSIS" +.SY cibadmin +.B +.RI [ option\~ ...] +.YS +. +.SH "DESCRIPTION" +.B cibadmin +is used to query, add, remove, update or replace any part of the cluster +information base (CIB). It can operate on the CIB currently in use in the +cluster, or it can operate on a file that can later be loaded into the cluster. +It is a highly flexible tool with a large number of command line options. +.P +This is a low-level tool for expert users. Most users should use +.B pcs +instead. +. +.SH "OPTIONS" +.SS "Commands" +One of the following commands must be provided. These options are mutually +exclusive. +.TP +.BR \-5 ", " \-\-md5\-sum +Calculate the on\-disk CIB digest. +.TP +.BR \-6 ", " \-\-md5\-sum\-versioned +Calculate an on\-the\-wire versioned CIB digest. +.TP +.BR \-a ", " \-\-empty =\fR[\fISCHEMA\fR] +Output an empty CIB. Accepts an optional \fISCHEMA\fR name argument to use as +the validate\-with value. If no schema is given, the latest will be used. +.TP +.BR \-B ", " \-\-bump +Increase the CIB's epoch value by 1. +.TP +.BR \-C ", " \-\-create +Create an object in the CIB (will fail if object already exists). +.TP +.BR \-D ", " \-\-delete +Delete the first object matching supplied criteria (for example, +\fB)\fR. The XML element name and all +attributes must match in order for the element to be deleted. +.TP +.BR \-d ", " \-\-delete\-all +When used with \fB\-\-xpath\fR, remove all matching objects in the configuration +instead of just the first one. +.TP +.BR \-E ", " \-\-erase +Erase the contents of the whole CIB. +.TP +.BR \-M ", " \-\-modify +Find object somewhere in CIB's XML tree and update it (fails if object does not +exist unless \fB\-c\fR is also specified). +.TP +.BR \-P ", " \-\-patch +Supply an update in the form of an XML diff (see +.MR crm_diff 8 ). +.TP +.BR \-Q ", " \-\-query +Query the contents of the CIB. +.TP +.BR \-R ", " \-\-replace +Recursively replace an object in the CIB. +.TP +.BR \-u ", " \-\-upgrade +Upgrade the configuration to the latest syntax. +. +.SS "Data options" +.TP +.BR \-p ", " \-\-xml\-pipe +Retrieve XML from stdin. Currently \fB\-\-xml\-file\fR and \fB\-\-xml\-text\fR +override this. In a future release, the last one specified will be used. +.TP +.BR \-X ", " \-\-xml\-text =\fISTRING\fR +Retrieve XML from the supplied string. Currently this takes precedence over +\fB\-\-xml\-pipe\fR, but \fB\-\-xml\-file\fR overrides this. In a future +release, the last one specified will be used. +.TP +.BR \-x ", " \-\-xml\-file =\fIFILE\fR +Retrieve XML from the named file. Currently this takes precedence over +\fB\-\-xml\-text\fR and \fB\-\-xml\-pipe\fR. In a future release, the last one +specified will be used. +. +.SS "Additional options" +.TP +.BR \-A ", " \-\-xpath =\fISTRING\fR +Use the XPath \fISTRING\fR instead of \fB\-\-scope\fR/\fB\-o\fR. If both +\fB\-\-scope\fR/\fB\-o\fR and \fB\-\-xpath\fR/\fB\-A\fR are specified, the +last one to appear takes effect. +.TP +.BR \-c ", " \-\-allow\-create +(Advanced) Allow target of \fB\-\-modify\fR/\fB\-M\fR to be created if it +does not exist. +.TP +.BR \-f ", " \-\-force +Force the action to be performed. +.TP +.BR \-n ", " \-\-no\-children +(Advanced) When querying an object, do not include its children in the result. +.TP +.BR \-o ", " \-\-scope =\fISCOPE\fR +Limit scope of operation to specific section of CIB. \fISCOPE\fR may be one +of: \fIacls\fR, \fIalerts\fR, \fIconfiguration\fR, \fIconstraints\fR, +\fIcrm_config\fR, \fIfencing\-topology\fR, \fInodes\fR, \fIop_defaults\fR, +\fIresources\fR, \fIrsc_defaults\fR, \fIstatus\fR, or \fItags\fR. If both +\fB\-\-scope\fR/\fB\-o\fR and \fB\-\-xpath\fR/\fB\-A\fR are specified, the +last one to appear takes effect. +.TP +.BR \-S ", " \-\-show\-access =\fIVALUE\fR +How to use syntax highlighting for ACLs (with \fB\-\-query\fR/\fB\-Q\fR and +\fB\-\-user\fR/\fB\-U\fR). Values are: +.RS +.IP \fIcolor\fR +Use color to indicate readable, writeable, and denied sections of the CIB +(default for interactive terminals). +.IP \fItext\fR +Annotate readable, writeable, and denied sections of the CIB with plain text +markings (default for non\-interactive use). +.IP \fInamespace\fR +Annotate readable, writeable, and denied sections of the CIB with special +XML tags. +.IP \fIauto\fR +Determine the value to use based on the environment. +.RE +.TP +.BR \-t ", " \-\-timeout =\fISECONDS\fR +Time to wait before declaring the operation failed. +.TP +.BR \-U ", " \-\-user =\fIUSERNAME\fR +Run the command with permissions of the named user (valid only for the root and +@CRM_DAEMON_USER@ accounts). +.TP +.B \-\-score +.RS +Treat new attribute values as atomic score updates where possible (with +\fB\-\-modify\fR/\fB\-M\fR). This currently happens by default and cannot be +disabled, but this default behavior is deprecated and will be removed in a +future release. Set this flag if this behavior is desired. This option takes +effect when updating XML attributes. For an attribute named \fIname\fR, if the +new value is \fBname++\fR or \fBname+=X\fR for some score \fIX\fR, the new +value is set as follows: +.IP \(bu +If attribute \fBname\fR is not already set to some value in the element being +updated, the new value is set as a literal string. +.IP \(bu +If the new value is \fBname++\fR, then the attribute is set to its existing +value (parsed as a score) plus 1. +.IP \(bu +If the new value is \fBname+=X\fR for some score \fIX\fR, then the attribute +is set to its existing value plus \fIX\fR, where the existing value and +\fIX\fR are parsed and added as scores. +.P +Scores are integer values capped at \fBINFINITY\fR and \fB\-INFINITY\fR. See +the \fIHost-Local Configuration\fR chapter of \fIPacemaker Explained\fR for more +details on scores, including how they are parsed and added. +.RE +. +.SS "Output options" +. +.TP +.BI \-\-output\-as= FORMAT +Specify output format as one of: text (default), xml. +.TP +.BI \-\-output\-to= DEST +Specify file name for output (or "\-" for stdout). +. +.SS "Help options" +.TP +.BR \-h ", " \-\-help +Show basic help options. +.TP +.B \-\-help\-additional +Show additional options. +.TP +.B \-\-help\-all +Show all help options. +.TP +.B \-\-help\-command +Show program commands. +.TP +.B \-\-help\-data +Show data options. +.TP +.B \-\-help\-output +Show output-related help options. +. +.SS "Application options" +.TP +.BR \-$ ", " \-\-version +Display software version and exit. +.TP +.BR \-V ", " \-\-verbose +Increase debug output (may be specified multiple times). +. +.SH "EXIT STATUS" +This is not an exhaustive list of exit statuses for \fBcibadmin\fR. See +.MR crm_error 8 +for more information on converting between error codes and their names. +.TP +.B CRM_EX_CONFIG +The given XML is invalid, or results in an invalid CIB when applied. +.TP +.B CRM_EX_INSUFFICIENT_PRIV +The given command is not allowed by the ACLs for the given user. +.TP +.B CRM_EX_UNSAFE +The given command is unsafe and requires \fB\-\-force\fR to be used. +.TP +.B ENOTCONN, ECONNREFUSED +\fBcibadmin\fR had problems connecting to or communicating with +\fBpacemaker-based\fR. +. +.SH "ENVIRONMENT" +.TP +.BR CIB_shadow ", " CIB_shadow_dir +If \fBCIB_shadow\fR is set, use its value as the suffix of a CIB file named +\fBshadow.\fR. If this file does not already exist, create it as a +blank CIB. If \fBCIB_shadow_dir\fR is set, look for (or create the new CIB) +file in that directory. Otherwise, use a directory specific to the current +user instead. +.TP +.BR CIB_file +If set, use the given file as the CIB. +.TP +.BR CIB_encrypted ", " CIB_port ", " CIB_server ", " CIB_user ", " CIB_passwd +If set, use these values to access the CIB remotely. If a password is required +but \fBCIB_passwd\fR is not given, the user will be prompted for it. +. +.SH "EXAMPLES" +.EX +# \fBcibadmin \-\-query +.EE +.RS +Query the configuration. +.RE +.P +. +.EX +# \fBcibadmin \-\-query \-\-scope crm_config +.EE +.RS +Query just the cluster options configuration. +.RE +.P +.EX +# \fBcibadmin \-\-query \-\-xpath "//nvpair[@name='target\-role']" +.EE +.RS +Query all \fBtarget\-role\fR settings. +.RE +.P +.EX +# \fBcibadmin \-\-delete\-all \-\-xpath "//nvpair[@name='is\-managed']" +.EE +.RS +Remove all \fBis\-managed\fR settings. +.RE +.P +.EX +# \fBcibadmin \-\-delete \-\-xml\-text '' +.EE +.RS +Remove the resource named \fBold\fR. +.RE +.P +.EX +# \fBcibadmin \-\-replace \-\-scope resources \-\-xml\-text '' +.EE +.RS +Remove all resources from the configuration. +.RE +.P +.EX +# \fBcibadmin \-\-replace \-\-xml\-file $HOME/pacemaker.xml +.EE +.RS +Replace complete configuration with contents of \fB$HOME/pacemaker.xml\fR. +.RE +.P +.EX +# \fBcibadmin \-\-replace \-\-scope constraints \-\-xml\-file $HOME/constraints.xml +.EE +.RS +Replace constraints section of configuration with contents of +\fB$HOME/constraints.xml\fR. +.RE +.P +.EX +# \fBcibadmin \-\-modify \-\-score \-\-xml\-text '' +.EE +.RS +Increase configuration version to prevent old configurations from being loaded +accidentally. +.RE +.P +.EX +# \fBcibadmin \-\-query > $HOME/local.xml +# \fB$EDITOR $HOME/local.xml +# \fBcibadmin \-\-replace \-\-xml\-file $HOME/local.xml +.EE +.RS +Edit the configuration with your favorite \fB$EDITOR\fR. +.RE +.P +.EX +# \fBcibadmin \-\-show\-access=color \-\-query \-\-user tony | less \-r +.EE +.RS +Assuming terminal, render configuration in color (green for writable, blue for +readable, red for denied) to visualize permissions for user tony. +.RE +.SH "REPORTING BUGS" +Report bugs to https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker +. +.SH "COPYRIGHT" +Copyright © 2004-2026 the Pacemaker project contributors. +.P +This program is licensed under the GNU General Public License version 2 or +later (GPLv2+) WITHOUT ANY WARRANTY. +. +.SH "SEE ALSO" +.BR crm_diff (8), +.BR crm_shadow (8), +.BR pcs (8) diff --git a/mk/man.mk b/mk/man.mk index 5631353c270..7b54d86d79c 100644 --- a/mk/man.mk +++ b/mk/man.mk @@ -22,7 +22,7 @@ if BUILD_HELP manpages = $(sbin_PROGRAMS:%=%.8) $(sbin_SCRIPTS:%=%.8) -man8_MANS = $(filter-out attrd_updater.8,$(manpages)) +man8_MANS = $(filter-out attrd_updater.8 cibadmin.8,$(manpages)) HELP2MAN_ARGS = -N --section 8 --name "Part of the Pacemaker cluster resource manager" diff --git a/tools/cibadmin.8.inc b/tools/cibadmin.8.inc deleted file mode 100644 index 14ae85af0ed..00000000000 --- a/tools/cibadmin.8.inc +++ /dev/null @@ -1,5 +0,0 @@ -[=synopsis] -cibadmin [] [options] - -/query and edit the Pacemaker configuration/ -.SH OPTIONS From 74c35324e9f4cc5b3afdbae908f53abbd3c8d8de Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 24 Mar 2026 14:51:41 -0400 Subject: [PATCH 5/9] Refactor: tools: Remove the examples section from cibadmin help output. This can be better handled in the man page. Ref T638 --- tools/cibadmin.c | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/tools/cibadmin.c b/tools/cibadmin.c index fc20bdea950..c66b434275e 100644 --- a/tools/cibadmin.c +++ b/tools/cibadmin.c @@ -948,56 +948,10 @@ static const pcmk__message_entry_t fmt_functions[] = { static GOptionContext * build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { - const char *desc = NULL; GOptionContext *context = NULL; - desc = "Examples:\n\n" - "Query the configuration:\n\n" - "\t# cibadmin --query\n\n" - "or just:\n\n" - "\t# cibadmin\n\n" - "Query just the cluster options configuration:\n\n" - "\t# cibadmin --query --scope " PCMK_XE_CRM_CONFIG "\n\n" - "Query all '" PCMK_META_TARGET_ROLE "' settings:\n\n" - "\t# cibadmin --query --xpath " - "\"//" PCMK_XE_NVPAIR - "[@" PCMK_XA_NAME "='" PCMK_META_TARGET_ROLE"']\"\n\n" - "Remove all '" PCMK_META_IS_MANAGED "' settings:\n\n" - "\t# cibadmin --delete-all --xpath " - "\"//" PCMK_XE_NVPAIR - "[@" PCMK_XA_NAME "='" PCMK_META_IS_MANAGED "']\"\n\n" - "Remove the resource named 'old':\n\n" - "\t# cibadmin --delete --xml-text " - "'<" PCMK_XE_PRIMITIVE " " PCMK_XA_ID "=\"old\"/>'\n\n" - "Remove all resources from the configuration:\n\n" - "\t# cibadmin --replace --scope " PCMK_XE_RESOURCES - " --xml-text '<" PCMK_XE_RESOURCES "/>'\n\n" - "Replace complete configuration with contents of " - "$HOME/pacemaker.xml:\n\n" - "\t# cibadmin --replace --xml-file $HOME/pacemaker.xml\n\n" - "Replace " PCMK_XE_CONSTRAINTS " section of configuration with " - "contents of $HOME/constraints.xml:\n\n" - "\t# cibadmin --replace --scope " PCMK_XE_CONSTRAINTS - " --xml-file $HOME/constraints.xml\n\n" - "Increase configuration version to prevent old configurations from " - "being loaded accidentally:\n\n" - "\t# cibadmin --modify --score --xml-text " - "'<" PCMK_XE_CIB " " PCMK_XA_ADMIN_EPOCH - "=\"" PCMK_XA_ADMIN_EPOCH "++\"/>'\n\n" - "Edit the configuration with your favorite $EDITOR:\n\n" - "\t# cibadmin --query > $HOME/local.xml\n\n" - "\t# $EDITOR $HOME/local.xml\n\n" - "\t# cibadmin --replace --xml-file $HOME/local.xml\n\n" - "Assuming terminal, render configuration in color (green for " - "writable, blue for readable, red for\n" - "denied) to visualize permissions for user tony:\n\n" - "\t# cibadmin --show-access=color --query --user tony | less -r\n\n" - "SEE ALSO:\n" - " crm(8), pcs(8), crm_shadow(8), crm_diff(8)\n"; - context = pcmk__build_arg_context(args, "text (default), xml", group, "[]"); - g_option_context_set_description(context, desc); pcmk__add_arg_group(context, "commands", "Commands:", "Show command help", command_entries); From 968fae877a900b87bb1c9ee10ee41062117d3484 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 28 Apr 2026 16:07:09 -0400 Subject: [PATCH 6/9] Refactor: tools: Simplify cibadmin help output. Ref T638 --- tools/cibadmin.c | 112 ++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 80 deletions(-) diff --git a/tools/cibadmin.c b/tools/cibadmin.c index c66b434275e..a9166f51b7f 100644 --- a/tools/cibadmin.c +++ b/tools/cibadmin.c @@ -661,40 +661,35 @@ static GOptionEntry command_entries[] = { "Increase the CIB's epoch value by 1", NULL }, { "create", 'C', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Create an object in the CIB (will fail if object already exists)", + "Create an object in the CIB", NULL }, { "modify", 'M', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Find object somewhere in CIB's XML tree and update it (fails if object " - "does not exist unless -c is also specified)", + "Find object somewhere in CIB's XML tree and update it", NULL }, { "patch", 'P', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Supply an update in the form of an XML diff (see crm_diff(8))", NULL }, + "Supply an update in the form of an XML diff", NULL }, { "replace", 'R', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, "Recursively replace an object in the CIB", NULL }, { "delete", 'D', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Delete first object matching supplied criteria (for example, " - "<" PCMK_XE_OP " " PCMK_XA_ID "=\"rsc1_op1\" " - PCMK_XA_NAME "=\"monitor\"/>).\n" - INDENT "The XML element name and all attributes must match in order for " - "the element to be deleted.", + "Delete first object matching supplied criteria", NULL }, { "delete-all", 'd', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "When used with --xpath, remove all matching objects in the " - "configuration instead of just the first one", + "When used with --xpath, remove all matching objects\n" + INDENT "in the configuration instead of just the\n" + INDENT "first one", NULL }, { "empty", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, command_cb, - "Output an empty CIB. Accepts an optional schema name argument to use as " - "the " PCMK_XA_VALIDATE_WITH " value.\n" - INDENT "If no schema is given, the latest will be used.", - "[schema]" }, + "Output an empty CIB conforming to the optional schema\n" + INDENT "name", + "[SCHEMA]" }, { "md5-sum", '5', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, command_cb, "Calculate the on-disk CIB digest", NULL }, @@ -708,24 +703,13 @@ static GOptionEntry command_entries[] = { static GOptionEntry data_entries[] = { // @COMPAT These arguments should be last-one-wins { "xml-file", 'x', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, - &options.input_file, - "Retrieve XML from the named file. Currently this takes precedence\n" - INDENT "over --xml-text and --xml-pipe. In a future release, the last\n" - INDENT "one specified will be used.", - "FILE" }, + &options.input_file, "Retrieve XML from the named file", "FILE" }, { "xml-text", 'X', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &options.input_string, - "Retrieve XML from the supplied string. Currently this takes precedence\n" - INDENT "over --xml-pipe, but --xml-file overrides this. In a future\n" - INDENT "release, the last one specified will be used.", - "STRING" }, + &options.input_string, "Retrieve XML from the supplied string", "STRING" }, { "xml-pipe", 'p', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, - &options.input_stdin, - "Retrieve XML from stdin. Currently --xml-file and --xml-text override\n" - INDENT "this. In a future release, the last one specified will be used.", - NULL }, + &options.input_stdin, "Retrieve XML from stdin", NULL }, { NULL } }; @@ -736,76 +720,44 @@ static GOptionEntry addl_entries[] = { { "timeout", 't', G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &options.timeout_sec, - "Time (in seconds) to wait before declaring the operation failed", - "value" }, + "Time to wait before declaring the operation failed", + "SECONDS" }, { "user", 'U', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.cib_user, - "Run the command with permissions of the named user (valid only for the " - "root and " CRM_DAEMON_USER " accounts)", "value" }, + "Run the command with permissions of the named user", "USER" }, { "scope", 'o', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, section_cb, - "Limit scope of operation to specific section of CIB\n" - INDENT "Valid values: " PCMK_XE_CONFIGURATION ", " PCMK_XE_NODES - ", " PCMK_XE_RESOURCES ", " PCMK_XE_CONSTRAINTS - ", " PCMK_XE_CRM_CONFIG ", " PCMK_XE_RSC_DEFAULTS ",\n" - INDENT " " PCMK_XE_OP_DEFAULTS ", " PCMK_XE_ACLS - ", " PCMK_XE_FENCING_TOPOLOGY ", " PCMK_XE_TAGS ", " PCMK_XE_ALERTS - ", " PCMK_XE_STATUS "\n" - INDENT "If both --scope/-o and --xpath/-a are specified, the last one to " - "appear takes effect", - "value" }, + "Limit scope of operation to specific section of CIB", + "SCOPE" }, { "xpath", 'A', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, section_cb, - "A valid XPath to use instead of --scope/-o\n" - INDENT "If both --scope/-o and --xpath/-a are specified, the last one to " - "appear takes effect", - "value" }, + "A valid XPath to use instead of --scope/-o", + "STRING" }, { "show-access", 'S', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, show_access_cb, - "Whether to use syntax highlighting for ACLs (with -Q/--query and " - "-U/--user)\n" - INDENT "Allowed values: 'color' (default for terminal), 'text' (plain text, " - "default for non-terminal),\n" - INDENT " 'namespace', or 'auto' (use default value)\n" - INDENT "Default value: 'auto'", - "[value]" }, + "Whether to use syntax highlighting for ACLs\n" + INDENT "Values: 'color' (default), 'text', 'namespace',\n" + INDENT " 'auto'\n" + INDENT "(with -Q/--query and -U/--user)", + "[VALUE]" }, { "score", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.score_update, - "Treat new attribute values as atomic score updates where possible " - "(with --modify/-M).\n" - - INDENT "This currently happens by default and cannot be disabled, but\n" - INDENT "this default behavior is deprecated and will be removed in a\n" - INDENT "future release. Set this flag if this behavior is desired.\n" - - INDENT "This option takes effect when updating XML attributes. For an\n" - INDENT "attribute named \"name\", if the new value is \"name++\" or\n" - INDENT "\"name+=X\" for some score X, the new value is set as follows:\n" - INDENT "If attribute \"name\" is not already set to some value in\n" - INDENT "the element being updated, the new value is set as a literal\n" - INDENT "string.\n" - INDENT "If the new value is \"name++\", then the attribute is set to \n" - INDENT "its existing value (parsed as a score) plus 1.\n" - INDENT "If the new value is \"name+=X\" for some score X, then the\n" - INDENT "attribute is set to its existing value plus X, where the\n" - INDENT "existing value and X are parsed and added as scores.\n" - - INDENT "Scores are integer values capped at INFINITY and -INFINITY.\n" - INDENT "Refer to Pacemaker Explained for more details on scores,\n" - INDENT "including how they are parsed and added.", + "Treat new attribute values as atomic score updates\n" + INDENT "where possible\n" + INDENT "(with --modify/-M)", NULL }, { "allow-create", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.allow_create, - "(Advanced) Allow target of --modify/-M to be created if it does not " - "exist", + "(Advanced) Allow target of --modify/-M to be created\n" + INDENT "if it does not exist", NULL }, { "no-children", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.no_children, - "(Advanced) When querying an object, do not include its children in the " - "result", + "(Advanced) When querying an object, do not include\n" + INDENT "its children in the result", NULL }, // @COMPAT Deprecated since 3.0.0 From 32edca2595f8ca50a25fa01e942b887519e76632 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 28 Apr 2026 14:52:16 -0400 Subject: [PATCH 7/9] Doc: man: Add a hand-written man page for crm_attribute. Ref T638 --- configure.ac | 1 + doc/man/Makefile.am | 1 + doc/man/crm_attribute.8.in | 268 +++++++++++++++++++++++++++++++++++++ mk/man.mk | 2 +- tools/crm_attribute.8.inc | 5 - 5 files changed, 271 insertions(+), 6 deletions(-) create mode 100644 doc/man/crm_attribute.8.in delete mode 100644 tools/crm_attribute.8.inc diff --git a/configure.ac b/configure.ac index 0c3e7038234..ae086324729 100644 --- a/configure.ac +++ b/configure.ac @@ -2033,6 +2033,7 @@ AC_CONFIG_FILES(Makefile \ doc/man/Makefile \ doc/man/attrd_updater.8 \ doc/man/cibadmin.8 \ + doc/man/crm_attribute.8 \ doc/sphinx/Makefile \ etc/Makefile \ etc/init.d/pacemaker \ diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index ac89008c74b..cbc7e50d0b9 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -10,3 +10,4 @@ include $(top_srcdir)/mk/common.mk man8_MANS = attrd_updater.8 man8_MANS += cibadmin.8 +man8_MANS += crm_attribute.8 diff --git a/doc/man/crm_attribute.8.in b/doc/man/crm_attribute.8.in new file mode 100644 index 00000000000..740745923ea --- /dev/null +++ b/doc/man/crm_attribute.8.in @@ -0,0 +1,268 @@ +.TH CRM_ATTRIBUTE "8" "@BUILD_DATE@" "@PACKAGE@ @VERSION@" "Pacemaker Manual" +.SH "NAME" +crm_attribute \- query and update Pacemaker cluster options and node attributes +. +.SH "SYNOPSIS" +.SY crm_attribute +.B \-n \fIattribute\fB +.RI [ option\~ ...] +.YS +. +.SH "DESCRIPTION" +.B crm_attribute +manages permanent and transient node attributes, as well as cluster options, +resource defaults, and operation defaults. Permanent node attributes are stored +in the CIB directly, while transient node attributes go through the attribute +manager to be recorded in the CIB. Transient node attributes will be erased +when the cluster is restarted. +.P +.B crm_attribute +can also use shadow CIBs and saved CIB files in addition to the live CIB. +. +.SH "OPTIONS" +.SS "Commands" +One of the following commands must be provided. These options are mutually +exclusive. +.TP +.BR \-D ", " \-\-delete +Delete the attribute/option (with \fB\-n\fR or \fB\-P\fR) +.TP +.BR \-G ", " \-\-query +Query the current value of the attribute/option. See also: \fB\-n\fR, \fB\-P\fR +.TP +.BR \-L ", " \-\-list\-options =\fITYPE\fR +List all available options of the given type. \fITYPE\fR may be one of: +\fIcluster\fR. +.TP +.BR \-v ", " \-\-update =\fIVALUE\fR +Update the value of the attribute/option (with \fB\-n\fR or \fB\-P\fR) +. +.SS "Selecting attributes:" +.TP +.BR \-P ", " \-\-pattern =\fIPATTERN\fR +Operate on all attributes matching \fIPATTERN\fR (with \fB\-v\fR, \fB\-D\fR, +or \fB\-G\fR). +.TP +.BR \-a ", " \-\-all +With \fB\-L\fR/\fB\-\-list\-options\fR, include advanced and deprecated options +in the output. This is always treated as true when \fB\-\-output\-as\fR=\fIxml\fR +is specified. +.TP +.BR \-i ", " \-\-id =\fIXML_ID\fR +(Advanced) Operate on instance of specified attribute with this \fIXML_ID\fR +.TP +.BR \-n ", " \-\-name =\fINAME\fR +Operate on attribute or option with \fINAME\fR. For queries, this is optional, +in which case all matching attributes will be returned. +.TP +.BR \-p ", " \-\-promotion =\fIRESOURCE\fR +Operate on node attribute used as promotion score for specified resource, or +resource given in \fIOCF_RESOURCE_INSTANCE\fR environment variable if none is +specified; this also defaults \fB\-l\fR/\fB\-\-lifetime\fR to reboot (normally +invoked from an OCF resource agent) +.TP +.BR \-s ", " \-\-set\-name =\fINAME\fR +(Advanced) Operate on instance of specified attribute that is within set with +this XML ID +. +.SS "Additional options" +.TP +.BR \-N ", " \-\-node =\fINODE\fR +Set a node attribute for named node (instead of a cluster option). See +also: \fB\-l\fR +.TP +.BR \-d ", " \-\-default =\fIVALUE\fR +(Advanced) Default value to display if none is found in configuration +.TP +.BR \-l ", " \-\-lifetime =\fILIFETIME\fR +Lifetime of the node attribute. \fILIFETIME\fR may be one of: \fIforever\fR, +\fIreboot\fR. +.TP +.BR \-t ", " \-\-type =\fISECTION\fR +Which part of the configuration to update, delete, or query the option in. +\fISECTION\fR may be one of: \fIcrm_config\fR, \fIrsc_defaults\fR, +\fIop_defaults\fR, \fItickets\fR. +.TP +.BR \-w ", " \-\-wait =\fIUNTIL\fR +Wait for some event to occur before returning to the shell (with \fB\-N\fR +and one of \fB\-D\fR or \fB\-v\fR). Values are: +.RS +.IP \fIno\fR (default) +Wait only for the attribute manager to acknowledge the request. +.IP \fIlocal\fR +Wait until the change has propagated to where a local query will return the +request value, or the value set by a later request. +.IP \fIcluster\fR +Wait until the change has propagated to where a query anywhere on the cluster +will return the requested value, or the value set by a later request. +.RE +.TP +.BR \-z ", " \-\-utilization +Set an utilization attribute for the node. +.TP +.BR \-\-score +Treat new attribute values as atomic score updates where possible (with +\fB\-\-update\fR/\fB\-v\fR, when running against a CIB file or updating an +attribute outside the status section; enabled by default if +\fB\-\-promotion\fR/\fB\-p\fR is specified) +.IP +This currently happens by default and cannot be disabled, but this default +behavior is deprecated and will be removed in a future release (exception: +this will remain the default with \fB\-\-promotion\fR/\fB\-p\fR). Set this +flag if this behavior is desired. +.IP +This option takes effect when updating XML attributes. For an attribute named +\fBname\fR, if the new value is \fBname++\fR or \fBname+=X\fR for some score +\fBX\fR, the new value is set as follows: +.RS +.IP \(bu +If attribute \fBname\fR is not already set to some value in the element being +updated, the new value is set as a literal string. +.IP \(bu +If the new value is \fBname++\fR, then the attribute is set to its existing +value (parsed as a score) plus 1. +.IP \(bu +If the new value is \fBname+=X\fR for some score \fBX\fR, then the attribute +is set to its existing value plus \fBX\fR, where the existing value and +\fBX\fR are parsed and added as scores. +.RE +.IP +Scores are integer values capped at \fBINFINITY\fR and \fB\-INFINITY\fR. +Refer to \fIPacemaker Explained\fR for more details on scores, including how +they are parsed and added. +. +.SS "Output options" +.TP +.BI \-\-output\-as= FORMAT +Specify output format as one of: text (default), xml. +.TP +.BI \-\-output\-to= DEST +Specify file name for output (or "\-" for stdout). +. +.SS "Help options" +.TP +.BR \-h ", " \-\-help +Show basic help options. +.TP +.B \-\-help\-additional +Show additional options. +.TP +.B \-\-help\-all +Show all help options. +.TP +.B \-\-help\-command +Show program commands. +.TP +.B \-\-help\-output +Show output-related help options. +.TP +.B \-\-help\-selections +Show selecting options. +. +.SS "Application options" +.TP +.BR \-$ ", " \-\-version +Display software version and exit. +.TP +.BR \-V ", " \-\-verbose +Increase debug output (may be specified multiple times). +.TP +.BR \-q ", " \-\-quiet +Print only the value on stdout. +. +.SH "EXIT STATUS" +This is not an exhaustive list of exit statuses for \fBcrm_attribute\fR. See +.MR crm_error 8 +for more information on converting between error codes and their names. +.TP +.B CRM_EX_CONFIG +The given XML is invalid, or results in an invalid CIB when applied. +.TP +.B CRM_EX_INSUFFICIENT_PRIV +The given command is not allowed by the ACLs for the given user. +.TP +.B CRM_EX_MULTIPLE +Multiple attributes exist with the same name. +.TP +.B CRM_EX_NOSUCH +The given attribute does not exist. +.TP +.B ENOTCONN, ECONNREFUSED +\fBcrm_attribute\fR had problems connecting to or communicating with +\fBpacemaker-based\fR. +. +.SH "ENVIRONMENT" +.TP +.BR CIB_shadow ", " CIB_shadow_dir +If \fBCIB_shadow\fR is set, use its value as the suffix of a CIB file named +\fBshadow.\fR. If this file does not already exist, create it as a +blank CIB. If \fBCIB_shadow_dir\fR is set, look for (or create the new CIB) +file in that directory. Otherwise, use a directory specific to the current +user instead. +.TP +.BR CIB_file +If set, use the given file as the CIB. +.TP +.BR CIB_encrypted ", " CIB_port ", " CIB_server ", " CIB_user ", " CIB_passwd +If set, use these values to access the CIB remotely. If a password is required +but \fBCIB_passwd\fR is not given, the user will be prompted for it. +.TP +.BR OCF_RESOURCE_INSTANCE +Resource to be used when managing promotion scores. +. +.SH "EXAMPLES" +.EX +# \fBcrm_attribute \-\-node myhost \-\-name location \-\-update office +.EE +.RS +Add new node attribute called \fBlocation\fR with the value of \fBoffice\fR +for host \fBmyhost\fR +.RE +.P +.EX +# \fBcrm_attribute \-\-node myhost \-\-name location \-\-query +.EE +.RS +Query the value of the \fBlocation\fR node attribute for host \fBmyhost\fR +.RE +.P +.EX +# \fBcrm_attribute \-\-node myhost \-\-name location \-\-update backoffice +.EE +.RS +Change the value of the \fBlocation\fR node attribute for host \fBmyhost\fR +.RE +.P +.EX +# \fBcrm_attribute \-\-node myhost \-\-name location \-\-delete +.EE +.RS +Delete the \fBlocation\fR node attribute for host \fBmyhost\fR +.RE +.P +.EX +# \fBcrm_attribute \-\-type crm_config \-\-name cluster\-delay \-\-query +.EE +.RS +Query the value of the \fBcluster\-delay\fR cluster option +.RE +.P +.EX +# \fBcrm_attribute \-\-type crm_config \-\-name cluster\-delay \-\-query \-\-quiet +.EE +.RS +Query value of the \fBcluster\-delay\fR cluster option and print only the value +.RE +. +.SH "REPORTING BUGS" +Report bugs to https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker +. +.SH "COPYRIGHT" +Copyright © 2004-2026 the Pacemaker project contributors. +.P +This program is licensed under the GNU General Public License version 2 or +later (GPLv2+) WITHOUT ANY WARRANTY. +. +.SH "SEE ALSO" +.BR attrd_updater (8), +.BR crm_error (8) diff --git a/mk/man.mk b/mk/man.mk index 7b54d86d79c..01fffd6d067 100644 --- a/mk/man.mk +++ b/mk/man.mk @@ -22,7 +22,7 @@ if BUILD_HELP manpages = $(sbin_PROGRAMS:%=%.8) $(sbin_SCRIPTS:%=%.8) -man8_MANS = $(filter-out attrd_updater.8 cibadmin.8,$(manpages)) +man8_MANS = $(filter-out attrd_updater.8 cibadmin.8 crm_attribute.8,$(manpages)) HELP2MAN_ARGS = -N --section 8 --name "Part of the Pacemaker cluster resource manager" diff --git a/tools/crm_attribute.8.inc b/tools/crm_attribute.8.inc deleted file mode 100644 index 2be825315c6..00000000000 --- a/tools/crm_attribute.8.inc +++ /dev/null @@ -1,5 +0,0 @@ -[synopsis] -crm_attribute -n [options] - -/and node attributes/ -.SH OPTIONS From c3a3ef5de69e7d498879752a46cb2d192aacc69a Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 28 Apr 2026 14:52:31 -0400 Subject: [PATCH 8/9] Refactor: tools: Remove the examples section from crm_attribute help output. This can be better handled in the man page. Ref T638 --- tools/crm_attribute.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tools/crm_attribute.c b/tools/crm_attribute.c index c7de7b71376..77f06bb20c1 100644 --- a/tools/crm_attribute.c +++ b/tools/crm_attribute.c @@ -708,27 +708,8 @@ build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { { NULL } }; - const char *description = "Examples:\n\n" - "Add new node attribute called 'location' with the value of 'office' for host 'myhost':\n\n" - "\tcrm_attribute --node myhost --name location --update office\n\n" - "Query the value of the 'location' node attribute for host 'myhost':\n\n" - "\tcrm_attribute --node myhost --name location --query\n\n" - "Change the value of the 'location' node attribute for host 'myhost':\n\n" - "\tcrm_attribute --node myhost --name location --update backoffice\n\n" - "Delete the 'location' node attribute for host 'myhost':\n\n" - "\tcrm_attribute --node myhost --name location --delete\n\n" - "Query the value of the '" PCMK_OPT_CLUSTER_DELAY - "' cluster option:\n\n" - "\tcrm_attribute --type crm_config --name " - PCMK_OPT_CLUSTER_DELAY " --query\n\n" - "Query value of the '" PCMK_OPT_CLUSTER_DELAY - "' cluster option and print only the value:\n\n" - "\tcrm_attribute --type crm_config --name " - PCMK_OPT_CLUSTER_DELAY " --query --quiet\n\n"; - context = pcmk__build_arg_context(args, "text (default), xml", group, NULL); pcmk__add_main_args(context, extra_prog_entries); - g_option_context_set_description(context, description); pcmk__add_arg_group(context, "selections", "Selecting attributes:", "Show selecting options", selecting_entries); From 046613ed2b436e7d5e8959a8e924b4f9cfe7fc6e Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Tue, 28 Apr 2026 16:38:00 -0400 Subject: [PATCH 9/9] Refactor: tools: Simplify crm_attribute help output. Ref T638 --- tools/crm_attribute.c | 93 ++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 59 deletions(-) diff --git a/tools/crm_attribute.c b/tools/crm_attribute.c index 77f06bb20c1..3a4b3ad5ed8 100644 --- a/tools/crm_attribute.c +++ b/tools/crm_attribute.c @@ -175,22 +175,20 @@ wait_cb (const gchar *option_name, const gchar *optarg, gpointer data, GError ** static GOptionEntry selecting_entries[] = { { "all", 'a', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.all, - "With -L/--list-options, include advanced and deprecated options in the\n" - INDENT "output. This is always treated as true when --output-as=xml is\n" - INDENT "specified.", + "Include advanced and deprecated options in the\n" + INDENT "output\n" + INDENT "(with -L/--list-options)", NULL, }, { "id", 'i', 0, G_OPTION_ARG_STRING, &options.attr_id, - "(Advanced) Operate on instance of specified attribute with this\n" - INDENT "XML ID", + "(Advanced) Operate on instance of specified\n" + INDENT "attribute with this XML ID", "XML_ID" }, { "name", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, attr_name_cb, - "Operate on attribute or option with this name. For queries, this\n" - INDENT "is optional, in which case all matching attributes will be\n" - INDENT "returned.", + "Operate on attribute or option with this name", "NAME" }, @@ -201,16 +199,15 @@ static GOptionEntry selecting_entries[] = { }, { "promotion", 'p', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, promotion_cb, - "Operate on node attribute used as promotion score for specified\n" - INDENT "resource, or resource given in OCF_RESOURCE_INSTANCE environment\n" - INDENT "variable if none is specified; this also defaults -l/--lifetime\n" - INDENT "to reboot (normally invoked from an OCF resource agent)", + "Operate on node attribute used as promotion score\n" + INDENT "for specified resource", "RESOURCE" }, { "set-name", 's', 0, G_OPTION_ARG_STRING, &options.set_name, - "(Advanced) Operate on instance of specified attribute that is\n" - INDENT "within set with this XML ID", + "(Advanced) Operate on instance of specified\n" + INDENT "attribute that is within set with this\n" + INDENT "XML ID", "NAME" }, @@ -219,24 +216,26 @@ static GOptionEntry selecting_entries[] = { static GOptionEntry command_entries[] = { { "list-options", 'L', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, list_cb, - "List all available options of the given type.\n" - INDENT "Allowed values: " PCMK__VALUE_CLUSTER, + "List all available options of the given type\n" + INDENT "Values: '" PCMK__VALUE_CLUSTER "'", "TYPE" }, { "delete", 'D', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, delete_cb, - "Delete the attribute/option (with -n or -P)", + "Delete the attribute/option\n" + INDENT "(with -n or -P)", NULL }, { "query", 'G', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, value_cb, - "Query the current value of the attribute/option.\n" + "Query the current value of the attribute/option\n" INDENT "See also: -n, -P", NULL }, { "update", 'v', 0, G_OPTION_ARG_CALLBACK, update_cb, - "Update the value of the attribute/option (with -n or -P)", + "Update the value of the attribute/option\n" + INDENT "(with -n or -P)", "VALUE" }, @@ -245,69 +244,45 @@ static GOptionEntry command_entries[] = { static GOptionEntry addl_entries[] = { { "default", 'd', 0, G_OPTION_ARG_STRING, &options.attr_default, - "(Advanced) Default value to display if none is found in configuration", + "(Advanced) Default value to display if none is\n" + INDENT "found in configuration", "VALUE" }, { "lifetime", 'l', 0, G_OPTION_ARG_STRING, &options.type, - "Lifetime of the node attribute.\n" - INDENT "Valid values: reboot, forever", + "Lifetime of the node attribute\n" + INDENT "Values: 'forever', 'reboot'", "LIFETIME" }, { "node", 'N', 0, G_OPTION_ARG_STRING, &options.dest_uname, - "Set a node attribute for named node (instead of a cluster option).\n" + "Set a node attribute for named node (instead of\n" + INDENT "a cluster option)\n" INDENT "See also: -l", "NODE" }, { "type", 't', 0, G_OPTION_ARG_STRING, &options.type, - "Which part of the configuration to update/delete/query the option in.\n" - INDENT "Valid values: crm_config, rsc_defaults, op_defaults, tickets", + "Which part of the configuration to update, delete,\n" + INDENT "or query the option in\n" + INDENT "Values: 'crm_config', 'rsc_defaults',\n" + INDENT " 'op_defaults', 'tickets'", "SECTION" }, { "score", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.score_update, - "Treat new attribute values as atomic score updates where possible\n" - INDENT "(with --update/-v, when running against a CIB file or updating\n" - INDENT "an attribute outside the " PCMK_XE_STATUS " section; enabled\n" - INDENT "by default if --promotion/-p is specified)\n\n" - - INDENT "This currently happens by default and cannot be disabled, but\n" - INDENT "this default behavior is deprecated and will be removed in a\n" - INDENT "future release (exception: this will remain the default with\n" - INDENT "--promotion/-p). Set this flag if this behavior is desired.\n\n" - - INDENT "This option takes effect when updating XML attributes. For an\n" - INDENT "attribute named \"name\", if the new value is \"name++\" or\n" - INDENT "\"name+=X\" for some score X, the new value is set as follows:\n" - INDENT " * If attribute \"name\" is not already set to some value in\n" - INDENT " the element being updated, the new value is set as a literal\n" - INDENT " string.\n" - INDENT " * If the new value is \"name++\", then the attribute is set to\n" - INDENT " its existing value (parsed as a score) plus 1.\n" - INDENT " * If the new value is \"name+=X\" for some score X, then the\n" - INDENT " attribute is set to its existing value plus X, where the\n" - INDENT " existing value and X are parsed and added as scores.\n\n" - - INDENT "Scores are integer values capped at INFINITY and -INFINITY.\n" - INDENT "Refer to Pacemaker Explained for more details on scores,\n" - INDENT "including how they are parsed and added.", + "Treat new attribute values as atomic score updates\n" + INDENT "where possible", NULL }, { "wait", 'W', 0, G_OPTION_ARG_CALLBACK, wait_cb, - "Wait for some event to occur before returning. Values are 'no' (wait\n" - INDENT "only for the attribute daemon to acknowledge the request),\n" - INDENT "'local' (wait until the change has propagated to where a local\n" - INDENT "query will return the request value, or the value set by a\n" - INDENT "later request), or 'cluster' (wait until the change has propagated\n" - INDENT "to where a query anywhere on the cluster will return the requested\n" - INDENT "value, or the value set by a later request). Default is 'no'.\n" - INDENT "(with -N, and one of -D or -u)", + "Wait for some event to occur before returning\n" + INDENT "Values: 'no' (default), 'local', 'cluster'\n" + INDENT "(with -N, and one of -D or -v)", "UNTIL" }, { "utilization", 'z', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, utilization_cb, - "Set an utilization attribute for the node.", + "Set an utilization attribute for the node", NULL },