Blob Blame History Raw
From a5a507d4e1abf242903472719a19977811e6f164 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 20 May 2021 11:59:36 -0400
Subject: [PATCH 01/10] Feature: libcrmcommon: Add OCF_OUTPUT_FORMAT to
 crm_resource environment.

See: rhbz#1644628
---
 lib/common/output.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/common/output.c b/lib/common/output.c
index 6cb49b5..58872e0 100644
--- a/lib/common/output.c
+++ b/lib/common/output.c
@@ -71,6 +71,8 @@ pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filenam
         return ENOMEM;
     }
 
+    setenv("OCF_OUTPUT_FORMAT", (*out)->fmt_name, 1);
+
     return pcmk_rc_ok;
 }
 
-- 
1.8.3.1


From acc6ecdbfb797d69794e68f75a734d6252434e01 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 21 May 2021 14:20:30 -0400
Subject: [PATCH 02/10] Feature: schemas: Copy crm_resource schema in
 preparation for changes.

See: rhbz#1644628
---
 xml/api/crm_resource-2.11.rng | 238 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 238 insertions(+)
 create mode 100644 xml/api/crm_resource-2.11.rng

diff --git a/xml/api/crm_resource-2.11.rng b/xml/api/crm_resource-2.11.rng
new file mode 100644
index 0000000..8e386db
--- /dev/null
+++ b/xml/api/crm_resource-2.11.rng
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+    <start>
+        <ref name="element-crm-resource"/>
+    </start>
+
+    <define name="element-crm-resource">
+        <choice>
+            <ref name="agents-list" />
+            <ref name="alternatives-list" />
+            <ref name="constraints-list" />
+            <externalRef href="generic-list-2.4.rng"/>
+            <element name="metadata"> <text/> </element>
+            <ref name="locate-list" />
+            <ref name="operations-list" />
+            <ref name="providers-list" />
+            <ref name="reasons-list" />
+            <ref name="resource-check" />
+            <ref name="resource-config" />
+            <ref name="resources-list" />
+        </choice>
+    </define>
+
+    <define name="agents-list">
+        <element name="agents">
+            <attribute name="standard"> <text/> </attribute>
+            <optional>
+                <attribute name="provider"> <text/> </attribute>
+            </optional>
+            <zeroOrMore>
+                <element name="agent"> <text/> </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="alternatives-list">
+        <element name="providers">
+            <attribute name="for"> <text/> </attribute>
+            <zeroOrMore>
+                <element name="provider"> <text/> </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="constraints-list">
+        <element name="constraints">
+            <interleave>
+                <zeroOrMore>
+                    <ref name="rsc-location" />
+                </zeroOrMore>
+                <zeroOrMore>
+                    <ref name="rsc-colocation" />
+                </zeroOrMore>
+            </interleave>
+        </element>
+    </define>
+
+    <define name="locate-list">
+        <element name="nodes">
+            <attribute name="resource"> <text/> </attribute>
+            <zeroOrMore>
+                <element name="node">
+                    <optional>
+                        <attribute name="state"><value>promoted</value></attribute>
+                    </optional>
+                    <text/>
+                </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="rsc-location">
+        <element name="rsc_location">
+            <attribute name="node"> <text/> </attribute>
+            <attribute name="rsc"> <text/> </attribute>
+            <attribute name="id"> <text/> </attribute>
+            <externalRef href="../score.rng"/>
+        </element>
+    </define>
+
+    <define name="operations-list">
+        <element name="operations">
+            <oneOrMore>
+                <ref name="element-operation-list" />
+            </oneOrMore>
+        </element>
+    </define>
+
+    <define name="providers-list">
+        <element name="providers">
+            <attribute name="standard"> <value>ocf</value> </attribute>
+            <optional>
+                <attribute name="agent"> <text/> </attribute>
+            </optional>
+            <zeroOrMore>
+                <element name="provider"> <text/> </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="reasons-list">
+        <choice>
+            <ref name="no-resource-or-uname"/>
+            <ref name="resource-and-uname"/>
+            <ref name="no-resource-but-uname"/>
+            <ref name="resource-but-no-uname"/>
+        </choice>
+    </define>
+
+    <define name="no-resource-or-uname">
+        <element name="reason">
+            <element name="resources">
+                <zeroOrMore>
+                    <element name="resource">
+                        <attribute name="id"> <text/> </attribute>
+                        <attribute name="running"> <data type="boolean"/> </attribute>
+                        <ref name="resource-check"/>
+                    </element>
+                </zeroOrMore>
+            </element>
+        </element>
+    </define>
+
+    <define name="resource-and-uname">
+        <element name="reason">
+            <attribute name="running_on"> <text/> </attribute>
+            <ref name="resource-check"/>
+        </element>
+    </define>
+
+    <define name="no-resource-but-uname">
+        <element name="reason">
+            <element name="resources">
+                <zeroOrMore>
+                    <element name="resource">
+                        <attribute name="id"> <text/> </attribute>
+                        <attribute name="running"> <data type="boolean"/> </attribute>
+                        <attribute name="host"> <text/> </attribute>
+                        <ref name="resource-check"/>
+                    </element>
+                </zeroOrMore>
+            </element>
+        </element>
+    </define>
+
+    <define name="resource-but-no-uname">
+        <element name="reason">
+            <attribute name="running"> <data type="boolean"/> </attribute>
+            <ref name="resource-check"/>
+        </element>
+    </define>
+
+    <define name="resource-config">
+        <element name="resource_config">
+            <externalRef href="resources-2.4.rng" />
+            <element name="xml"> <text/> </element>
+        </element>
+    </define>
+
+    <define name="resource-check">
+        <element name="check">
+            <attribute name="id"> <text/> </attribute>
+            <optional>
+                <choice>
+                    <attribute name="remain_stopped"><value>true</value></attribute>
+                    <attribute name="promotable"><value>false</value></attribute>
+                </choice>
+            </optional>
+            <optional>
+                <attribute name="unmanaged"><value>true</value></attribute>
+            </optional>
+            <optional>
+                <attribute name="locked-to"> <text/> </attribute>
+            </optional>
+        </element>
+    </define>
+
+    <define name="resources-list">
+        <element name="resources">
+            <zeroOrMore>
+                <externalRef href="resources-2.4.rng" />
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="rsc-colocation">
+        <element name="rsc_colocation">
+            <attribute name="id"> <text/> </attribute>
+            <attribute name="rsc"> <text/> </attribute>
+            <attribute name="with-rsc"> <text/> </attribute>
+            <externalRef href="../score.rng"/>
+            <optional>
+                <attribute name="node-attribute"> <text/> </attribute>
+            </optional>
+            <optional>
+                <attribute name="rsc-role">
+                    <ref name="attribute-roles"/>
+                </attribute>
+            </optional>
+            <optional>
+                <attribute name="with-rsc-role">
+                    <ref name="attribute-roles"/>
+                </attribute>
+            </optional>
+        </element>
+    </define>
+
+    <define name="element-operation-list">
+        <element name="operation">
+            <optional>
+                <group>
+                    <attribute name="rsc"> <text/> </attribute>
+                    <attribute name="agent"> <text/> </attribute>
+                </group>
+            </optional>
+            <attribute name="op"> <text/> </attribute>
+            <attribute name="node"> <text/> </attribute>
+            <attribute name="call"> <data type="integer" /> </attribute>
+            <attribute name="rc"> <data type="nonNegativeInteger" /> </attribute>
+            <optional>
+                <attribute name="last-rc-change"> <text/> </attribute>
+                <attribute name="exec-time"> <data type="nonNegativeInteger" /> </attribute>
+            </optional>
+            <attribute name="status"> <text/> </attribute>
+        </element>
+    </define>
+
+    <define name="attribute-roles">
+        <choice>
+            <value>Stopped</value>
+            <value>Started</value>
+            <value>Master</value>
+            <value>Slave</value>
+        </choice>
+    </define>
+</grammar>
-- 
1.8.3.1


From 1bbdf2149a111e9e19c388834f82001e0d31c427 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 24 May 2021 12:23:55 -0400
Subject: [PATCH 03/10] Feature: xml: Update the crm_resource schema for XML
 output.

See: rhbz#1644628
---
 xml/api/crm_resource-2.11.rng | 50 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/xml/api/crm_resource-2.11.rng b/xml/api/crm_resource-2.11.rng
index 8e386db..aaa54d6 100644
--- a/xml/api/crm_resource-2.11.rng
+++ b/xml/api/crm_resource-2.11.rng
@@ -20,6 +20,7 @@
             <ref name="resource-check" />
             <ref name="resource-config" />
             <ref name="resources-list" />
+            <ref name="resource-agent-action" />
         </choice>
     </define>
 
@@ -227,6 +228,55 @@
         </element>
     </define>
 
+    <define name="resource-agent-action">
+        <element name="resource-agent-action">
+            <attribute name="action"> <text/> </attribute>
+            <optional>
+                <attribute name="rsc"> <text/> </attribute>
+            </optional>
+            <attribute name="class"> <text/> </attribute>
+            <attribute name="type"> <text/> </attribute>
+            <optional>
+                <attribute name="provider"> <text/> </attribute>
+            </optional>
+            <optional>
+                <ref name="overrides-list"/>
+            </optional>
+            <ref name="agent-status"/>
+            <optional>
+                <choice>
+                    <element name="command">
+                        <text />
+                    </element>
+                    <externalRef href="command-output-1.0.rng"/>
+                </choice>
+            </optional>
+        </element>
+    </define>
+
+    <define name="overrides-list">
+        <element name="overrides">
+            <zeroOrMore>
+                <element name="override">
+                    <optional>
+                        <attribute name="rsc"> <text/> </attribute>
+                    </optional>
+                    <attribute name="name"> <text/> </attribute>
+                    <attribute name="value"> <text/> </attribute>
+                </element>
+            </zeroOrMore>
+        </element>
+    </define>
+
+    <define name="agent-status">
+        <element name="agent-status">
+            <attribute name="code"> <data type="integer" /> </attribute>
+            <optional>
+                <attribute name="message"> <text/> </attribute>
+            </optional>
+        </element>
+    </define>
+
     <define name="attribute-roles">
         <choice>
             <value>Stopped</value>
-- 
1.8.3.1


From d89f5bc7fec856fdcd32fa14edbd0019507d5d15 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 1 Jun 2021 15:26:58 -0400
Subject: [PATCH 04/10] Low: libcrmcommon: Increase PCMK__API_VERSION for new
 crm_resource output.

See: rhbz#1644628
---
 include/crm/common/output_internal.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/crm/common/output_internal.h b/include/crm/common/output_internal.h
index 10b315b..0436cde 100644
--- a/include/crm/common/output_internal.h
+++ b/include/crm/common/output_internal.h
@@ -27,7 +27,7 @@ extern "C" {
 #  include <glib.h>
 #  include <crm/common/results.h>
 
-#  define PCMK__API_VERSION "2.9"
+#  define PCMK__API_VERSION "2.11"
 
 #if defined(PCMK__WITH_ATTRIBUTE_OUTPUT_ARGS)
 #  define PCMK__OUTPUT_ARGS(ARGS...) __attribute__((output_args(ARGS)))
-- 
1.8.3.1


From 30bd2ddf43ee2a911681e51f40ed9ba20ec250b0 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Thu, 27 May 2021 13:57:12 -0400
Subject: [PATCH 05/10] Low: tools: Pass NULL to
 cli_resource_execute_from_params...

if no resource name is given.  This happens if we are validating based
on the --class/--agent/--provider command line options instead.
---
 tools/crm_resource.c         | 2 +-
 tools/crm_resource_runtime.c | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 24f1121..37a0bb0 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1840,7 +1840,7 @@ main(int argc, char **argv)
 
         case cmd_execute_agent:
             if (options.cmdline_config) {
-                exit_code = cli_resource_execute_from_params(out, "test",
+                exit_code = cli_resource_execute_from_params(out, NULL,
                     options.v_class, options.v_provider, options.v_agent,
                     "validate-all", options.cmdline_params,
                     options.override_params, options.timeout_ms,
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 48a4b40..ebf48bb 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -1717,14 +1717,14 @@ cli_resource_execute_from_params(pcmk__output_t *out, const char *rsc_name,
      */
     params_copy = pcmk__str_table_dup(params);
 
-    op = resources_action_create(rsc_name, rsc_class, rsc_prov, rsc_type, action, 0,
-                                 timeout_ms, params_copy, 0);
+    op = resources_action_create(rsc_name ? rsc_name : "test", rsc_class, rsc_prov,
+                                 rsc_type, action, 0, timeout_ms, params_copy, 0);
     if (op == NULL) {
         /* Re-run with stderr enabled so we can display a sane error message */
         crm_enable_stderr(TRUE);
         params_copy = pcmk__str_table_dup(params);
-        op = resources_action_create(rsc_name, rsc_class, rsc_prov, rsc_type, action, 0,
-                                     timeout_ms, params_copy, 0);
+        op = resources_action_create(rsc_name ? rsc_name : "test", rsc_class, rsc_prov,
+                                     rsc_type, action, 0, timeout_ms, params_copy, 0);
 
         /* Callers of cli_resource_execute expect that the params hash table will
          * be freed.  That function uses this one, so for that reason and for
-- 
1.8.3.1


From ee56efd53d14cfc4f902769540b72b3bb6096a73 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 24 May 2021 12:08:52 -0400
Subject: [PATCH 06/10] Feature: tools: Add an agent-status message for
 crm_resource.

This moves what was previously only done in an out->info call to its own
output message, which means it will appear in XML output as well.  Also,
note that if --class/--agent/--provider are given, the resource name
will be set to "test".  In that case, do not display the resource name
in the output.

This message will be used for --validate and the --force-* command line
options to crm_resource.

See: rhbz#1644628
---
 tools/crm_resource_print.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index 9d82cf8..88d5878 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -152,6 +152,57 @@ attribute_list_default(pcmk__output_t *out, va_list args) {
     return pcmk_rc_ok;
 }
 
+PCMK__OUTPUT_ARGS("agent-status", "int", "const char *", "const char *", "const char *",
+                  "const char *", "const char *", "int")
+static int
+agent_status_default(pcmk__output_t *out, va_list args) {
+    int status = va_arg(args, int);
+    const char *action = va_arg(args, const char *);
+    const char *name = va_arg(args, const char *);
+    const char *class = va_arg(args, const char *);
+    const char *provider = va_arg(args, const char *);
+    const char *type = va_arg(args, const char *);
+    int rc = va_arg(args, int);
+
+    if (status == PCMK_LRM_OP_DONE) {
+        out->info(out, "Operation %s%s%s (%s%s%s:%s) returned: '%s' (%d)",
+                  action, name ? " for " : "", name ? name : "",
+                  class, provider ? ":" : "", provider ? provider : "", type,
+                  services_ocf_exitcode_str(rc), rc);
+    } else {
+        out->err(out, "Operation %s%s%s (%s%s%s:%s) failed: '%s' (%d)",
+                 action, name ? " for " : "", name ? name : "",
+                 class, provider ? ":" : "", provider ? provider : "", type,
+                 services_lrm_status_str(status), status);
+    }
+
+    return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("agent-status", "int", "const char *", "const char *", "const char *",
+                  "const char *", "const char *", "int")
+static int
+agent_status_xml(pcmk__output_t *out, va_list args) {
+    int status G_GNUC_UNUSED = va_arg(args, int);
+    const char *action G_GNUC_UNUSED = va_arg(args, const char *);
+    const char *name G_GNUC_UNUSED = va_arg(args, const char *);
+    const char *class G_GNUC_UNUSED = va_arg(args, const char *);
+    const char *provider G_GNUC_UNUSED = va_arg(args, const char *);
+    const char *type G_GNUC_UNUSED = va_arg(args, const char *);
+    int rc = va_arg(args, int);
+
+    char *status_str = pcmk__itoa(rc);
+
+    pcmk__output_create_xml_node(out, "agent-status",
+                                 "code", status_str,
+                                 "message", services_ocf_exitcode_str(rc),
+                                 NULL);
+
+    free(status_str);
+
+    return pcmk_rc_ok;
+}
+
 PCMK__OUTPUT_ARGS("attribute-list", "pe_resource_t *", "char *", "GHashTable *")
 static int
 attribute_list_text(pcmk__output_t *out, va_list args) {
@@ -562,6 +613,8 @@ resource_names(pcmk__output_t *out, va_list args) {
 }
 
 static pcmk__message_entry_t fmt_functions[] = {
+    { "agent-status", "default", agent_status_default },
+    { "agent-status", "xml", agent_status_xml },
     { "attribute-list", "default", attribute_list_default },
     { "attribute-list", "text", attribute_list_text },
     { "property-list", "default", property_list_default },
-- 
1.8.3.1


From 85cb6b6bff96b18c5174d11e4de4d49cbfb20bb7 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Tue, 1 Jun 2021 14:47:30 -0400
Subject: [PATCH 07/10] Feature: tools: Add an overridden params output
 message.

This also replaces what was previously being done in an out->info call
with an output message.  This means it shows up in XML output as well.
Also, note that if --class/--agent/--provider are given, the resource
name will be set to "test".  In that case, do not display the resource
name in the output.

See: rhbz#1644628
---
 tools/crm_resource_print.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index 88d5878..119d83f 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -224,6 +224,43 @@ attribute_list_text(pcmk__output_t *out, va_list args) {
     return pcmk_rc_ok;
 }
 
+PCMK__OUTPUT_ARGS("override", "const char *", "const char *", "const char *")
+static int
+override_default(pcmk__output_t *out, va_list args) {
+    const char *rsc_name = va_arg(args, const char *);
+    const char *name = va_arg(args, const char *);
+    const char *value = va_arg(args, const char *);
+
+    if (rsc_name == NULL) {
+        out->list_item(out, NULL, "Overriding the cluster configuration with '%s' = '%s'",
+                       name, value);
+    } else {
+        out->list_item(out, NULL, "Overriding the cluster configuration for '%s' with '%s' = '%s'",
+                       rsc_name, name, value);
+    }
+
+    return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("override", "const char *", "const char *", "const char *")
+static int
+override_xml(pcmk__output_t *out, va_list args) {
+    const char *rsc_name = va_arg(args, const char *);
+    const char *name = va_arg(args, const char *);
+    const char *value = va_arg(args, const char *);
+
+    xmlNodePtr node = pcmk__output_create_xml_node(out, "override",
+                                                   "name", name,
+                                                   "value", value,
+                                                   NULL);
+
+    if (rsc_name != NULL) {
+        crm_xml_add(node, "rsc", rsc_name);
+    }
+
+    return pcmk_rc_ok;
+}
+
 PCMK__OUTPUT_ARGS("property-list", "pe_resource_t *", "char *")
 static int
 property_list_default(pcmk__output_t *out, va_list args) {
@@ -617,6 +654,8 @@ static pcmk__message_entry_t fmt_functions[] = {
     { "agent-status", "xml", agent_status_xml },
     { "attribute-list", "default", attribute_list_default },
     { "attribute-list", "text", attribute_list_text },
+    { "override", "default", override_default },
+    { "override", "xml", override_xml },
     { "property-list", "default", property_list_default },
     { "property-list", "text", property_list_text },
     { "resource-check-list", "default", resource_check_list_default },
-- 
1.8.3.1


From e5e24592c7c3231c619fb5253e7925ffbc634a99 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 4 Jun 2021 10:24:51 -0400
Subject: [PATCH 08/10] Low: tools: Use simple XML lists for resource actions
 as well.

See: rhbz#1644628
---
 tools/crm_resource.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 37a0bb0..e957011 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1643,6 +1643,7 @@ main(int argc, char **argv)
          * saves from having to write custom messages to build the lists around all these things
          */
         switch (options.rsc_cmd) {
+            case cmd_execute_agent:
             case cmd_list_resources:
             case cmd_query_xml:
             case cmd_query_raw_xml:
-- 
1.8.3.1


From 3e75174d0bc31b261adb1994214a5878b79da85b Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 4 Jun 2021 10:30:10 -0400
Subject: [PATCH 09/10] Feature: tools: Add an output message for resource
 actions.

This wraps up the override and agent-status messages into a single
message, along with any stdout/stderr from the resource action.  This
message should be called after taking the action.

This also implements handling XML output from resource actions.  Check
to see if the validate-all action returns XML.  If so, output it as a
CDATA block under a "command" element.  If not, treat it as plain text
and output it as stdout/stderr from a command.

See: rhbz#1644628
---
 tools/crm_resource_print.c | 122 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index 119d83f..19a366d 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -293,6 +293,126 @@ property_list_text(pcmk__output_t *out, va_list args) {
     return pcmk_rc_ok;
 }
 
+PCMK__OUTPUT_ARGS("resource-agent-action", "int", "const char *", "const char *",
+                  "const char *", "const char *", "const char *", "GHashTable *",
+                  "int", "int", "char *", "char *")
+static int
+resource_agent_action_default(pcmk__output_t *out, va_list args) {
+    int verbose = va_arg(args, int);
+
+    const char *class = va_arg(args, const char *);
+    const char *provider = va_arg(args, const char *);
+    const char *type = va_arg(args, const char *);
+    const char *rsc_name = va_arg(args, const char *);
+    const char *action = va_arg(args, const char *);
+    GHashTable *overrides = va_arg(args, GHashTable *);
+    int rc = va_arg(args, int);
+    int status = va_arg(args, int);
+    char *stdout_data = va_arg(args, char *);
+    char *stderr_data = va_arg(args, char *);
+
+    if (overrides) {
+        GHashTableIter iter;
+        char *name = NULL;
+        char *value = NULL;
+
+        out->begin_list(out, NULL, NULL, "overrides");
+
+        g_hash_table_iter_init(&iter, overrides);
+        while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &value)) {
+            out->message(out, "override", rsc_name, name, value);
+        }
+
+        out->end_list(out);
+    }
+
+    out->message(out, "agent-status", status, action, rsc_name, class, provider,
+                 type, rc);
+
+    /* hide output for validate-all if not in verbose */
+    if (verbose == 0 && pcmk__str_eq(action, "validate-all", pcmk__str_casei)) {
+        return pcmk_rc_ok;
+    }
+
+    if (stdout_data || stderr_data) {
+        xmlNodePtr doc = string2xml(stdout_data);
+
+        if (doc != NULL) {
+            out->output_xml(out, "command", stdout_data);
+            xmlFreeNode(doc);
+        } else {
+            out->subprocess_output(out, rc, stdout_data, stderr_data);
+        }
+    }
+
+    return pcmk_rc_ok;
+}
+
+PCMK__OUTPUT_ARGS("resource-agent-action", "int", "const char *", "const char *",
+                  "const char *", "const char *", "const char *", "GHashTable *",
+                  "int", "int", "char *", "char *")
+static int
+resource_agent_action_xml(pcmk__output_t *out, va_list args) {
+    int verbose G_GNUC_UNUSED = va_arg(args, int);
+
+    const char *class = va_arg(args, const char *);
+    const char *provider = va_arg(args, const char *);
+    const char *type = va_arg(args, const char *);
+    const char *rsc_name = va_arg(args, const char *);
+    const char *action = va_arg(args, const char *);
+    GHashTable *overrides = va_arg(args, GHashTable *);
+    int rc = va_arg(args, int);
+    int status = va_arg(args, int);
+    char *stdout_data = va_arg(args, char *);
+    char *stderr_data = va_arg(args, char *);
+
+    xmlNodePtr node = pcmk__output_xml_create_parent(out, "resource-agent-action",
+                                                     "action", action,
+                                                     "class", class,
+                                                     "type", type,
+                                                     NULL);
+
+    if (rsc_name) {
+        crm_xml_add(node, "rsc", rsc_name);
+    }
+
+    if (provider) {
+        crm_xml_add(node, "provider", provider);
+    }
+
+    if (overrides) {
+        GHashTableIter iter;
+        char *name = NULL;
+        char *value = NULL;
+
+        out->begin_list(out, NULL, NULL, "overrides");
+
+        g_hash_table_iter_init(&iter, overrides);
+        while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &value)) {
+            out->message(out, "override", rsc_name, name, value);
+        }
+
+        out->end_list(out);
+    }
+
+    out->message(out, "agent-status", status, action, rsc_name, class, provider,
+                 type, rc);
+
+    if (stdout_data || stderr_data) {
+        xmlNodePtr doc = string2xml(stdout_data);
+
+        if (doc != NULL) {
+            out->output_xml(out, "command", stdout_data);
+            xmlFreeNode(doc);
+        } else {
+            out->subprocess_output(out, rc, stdout_data, stderr_data);
+        }
+    }
+
+    pcmk__output_xml_pop_parent(out);
+    return pcmk_rc_ok;
+}
+
 PCMK__OUTPUT_ARGS("resource-check-list", "resource_checks_t *")
 static int
 resource_check_list_default(pcmk__output_t *out, va_list args) {
@@ -658,6 +778,8 @@ static pcmk__message_entry_t fmt_functions[] = {
     { "override", "xml", override_xml },
     { "property-list", "default", property_list_default },
     { "property-list", "text", property_list_text },
+    { "resource-agent-action", "default", resource_agent_action_default },
+    { "resource-agent-action", "xml", resource_agent_action_xml },
     { "resource-check-list", "default", resource_check_list_default },
     { "resource-check-list", "xml", resource_check_list_xml },
     { "resource-search-list", "default", resource_search_list_default },
-- 
1.8.3.1


From b50b2418e1e997b42f5370b4672a3f105d74634f Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Fri, 4 Jun 2021 10:40:16 -0400
Subject: [PATCH 10/10] Feature: tools: Use the new resource-agent-action
 message.

See: rhbz#1644628
---
 tools/crm_resource_runtime.c | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index ebf48bb..755be9f 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -1765,28 +1765,13 @@ cli_resource_execute_from_params(pcmk__output_t *out, const char *rsc_name,
     if (services_action_sync(op)) {
         exit_code = op->rc;
 
-        if (op->status == PCMK_LRM_OP_DONE) {
-            out->info(out, "Operation %s for %s (%s:%s:%s) returned: '%s' (%d)",
-                      action, rsc_name, rsc_class, rsc_prov ? rsc_prov : "", rsc_type,
-                      services_ocf_exitcode_str(op->rc), op->rc);
-        } else {
-            out->err(out, "Operation %s for %s (%s:%s:%s) failed: '%s' (%d)",
-                     action, rsc_name, rsc_class, rsc_prov ? rsc_prov : "", rsc_type,
-                     services_lrm_status_str(op->status), op->status);
-        }
-
-        /* hide output for validate-all if not in verbose */
-        if (resource_verbose == 0 && pcmk__str_eq(action, "validate-all", pcmk__str_casei))
-            goto done;
-
-        if (op->stdout_data || op->stderr_data) {
-            out->subprocess_output(out, op->rc, op->stdout_data, op->stderr_data);
-        }
+        out->message(out, "resource-agent-action", resource_verbose, rsc_class,
+                     rsc_prov, rsc_type, rsc_name, action, override_hash, op->rc,
+                     op->status, op->stdout_data, op->stderr_data);
     } else {
         exit_code = op->rc == 0 ? CRM_EX_ERROR : op->rc;
     }
 
-done:
     services_action_free(op);
     /* See comment above about why we free params here. */
     g_hash_table_destroy(params);
-- 
1.8.3.1