From a467f0953c61bd56a9b34a98c71855d3cfbf6ba4 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 5 Apr 2022 16:26:30 -0500
Subject: [PATCH 01/14] Refactor: tools: use a flag to indicate locked
resources in crm_resource
... to make the handling consistent with other checks. This also allows some of
the code to be simplified.
---
tools/crm_resource.h | 13 +++++++++----
tools/crm_resource_print.c | 21 ++++++++-------------
tools/crm_resource_runtime.c | 7 +++----
3 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/tools/crm_resource.h b/tools/crm_resource.h
index 71a978893..b5fdd1bb5 100644
--- a/tools/crm_resource.h
+++ b/tools/crm_resource.h
@@ -8,6 +8,10 @@
*/
#include <crm_internal.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+
#include <crm/crm.h>
#include <crm/msg_xml.h>
@@ -31,13 +35,14 @@ typedef struct node_info_s {
enum resource_check_flags {
rsc_remain_stopped = (1 << 0),
rsc_unpromotable = (1 << 1),
- rsc_unmanaged = (1 << 2)
+ rsc_unmanaged = (1 << 2),
+ rsc_locked = (1 << 3),
};
typedef struct resource_checks_s {
- pe_resource_t *rsc;
- unsigned int flags;
- const char *lock_node;
+ pe_resource_t *rsc; // Resource being checked
+ uint32_t flags; // Group of enum resource_check_flags
+ const char *lock_node; // Node that resource is shutdown-locked to, if any
} resource_checks_t;
resource_checks_t *cli_check_resource(pe_resource_t *rsc, char *role_s, char *managed);
diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index 5abf3df0c..f63fc952d 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -450,14 +450,13 @@ resource_check_list_default(pcmk__output_t *out, va_list args) {
resource_checks_t *checks = va_arg(args, resource_checks_t *);
pe_resource_t *parent = uber_parent(checks->rsc);
- int rc = pcmk_rc_no_output;
- bool printed = false;
- if (checks->flags != 0 || checks->lock_node != NULL) {
- printed = true;
- out->begin_list(out, NULL, NULL, "Resource Checks");
+ if (checks->flags == 0) {
+ return pcmk_rc_no_output;
}
+ out->begin_list(out, NULL, NULL, "Resource Checks");
+
if (pcmk_is_set(checks->flags, rsc_remain_stopped)) {
out->list_item(out, "check", "Configuration specifies '%s' should remain stopped",
parent->id);
@@ -473,17 +472,13 @@ resource_check_list_default(pcmk__output_t *out, va_list args) {
parent->id);
}
- if (checks->lock_node) {
+ if (pcmk_is_set(checks->flags, rsc_locked)) {
out->list_item(out, "check", "'%s' is locked to node %s due to shutdown",
parent->id, checks->lock_node);
}
- if (printed) {
- out->end_list(out);
- rc = pcmk_rc_ok;
- }
-
- return rc;
+ out->end_list(out);
+ return pcmk_rc_ok;
}
PCMK__OUTPUT_ARGS("resource-check-list", "resource_checks_t *")
@@ -509,7 +504,7 @@ resource_check_list_xml(pcmk__output_t *out, va_list args) {
pcmk__xe_set_bool_attr(node, "unmanaged", true);
}
- if (checks->lock_node) {
+ if (pcmk_is_set(checks->flags, rsc_locked)) {
crm_xml_add(node, "locked-to", checks->lock_node);
}
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 9e7e1fe74..b5bccadaf 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -36,7 +36,8 @@ cli_check_resource(pe_resource_t *rsc, char *role_s, char *managed)
rc->flags |= rsc_unmanaged;
}
- if (rsc->lock_node) {
+ if (rsc->lock_node != NULL) {
+ rc->flags |= rsc_locked;
rc->lock_node = rsc->lock_node->details->uname;
}
@@ -914,9 +915,7 @@ cli_resource_check(pcmk__output_t *out, cib_t * cib_conn, pe_resource_t *rsc)
checks = cli_check_resource(rsc, role_s, managed);
- if (checks->flags != 0 || checks->lock_node != NULL) {
- rc = out->message(out, "resource-check-list", checks);
- }
+ rc = out->message(out, "resource-check-list", checks);
free(role_s);
free(managed);
--
2.31.1
From 7f8f94d0a1086e592e39f3a1a812b1a65225c09b Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 5 Apr 2022 16:48:03 -0500
Subject: [PATCH 02/14] Refactor: tools: functionize individual resource checks
in crm_resource
... rather than have one check-everything function, to make the code simpler
and more readable.
---
tools/crm_resource_runtime.c | 101 ++++++++++++++++++++---------------
1 file changed, 57 insertions(+), 44 deletions(-)
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index b5bccadaf..d47f959f5 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -15,36 +15,6 @@
#include <crm/common/lists_internal.h>
#include <crm/services_internal.h>
-resource_checks_t *
-cli_check_resource(pe_resource_t *rsc, char *role_s, char *managed)
-{
- pe_resource_t *parent = uber_parent(rsc);
- resource_checks_t *rc = calloc(1, sizeof(resource_checks_t));
-
- if (role_s) {
- enum rsc_role_e role = text2role(role_s);
-
- if (role == RSC_ROLE_STOPPED) {
- rc->flags |= rsc_remain_stopped;
- } else if (pcmk_is_set(parent->flags, pe_rsc_promotable) &&
- (role == RSC_ROLE_UNPROMOTED)) {
- rc->flags |= rsc_unpromotable;
- }
- }
-
- if (managed && !crm_is_true(managed)) {
- rc->flags |= rsc_unmanaged;
- }
-
- if (rsc->lock_node != NULL) {
- rc->flags |= rsc_locked;
- rc->lock_node = rsc->lock_node->details->uname;
- }
-
- rc->rsc = rsc;
- return rc;
-}
-
static GList *
build_node_info_list(pe_resource_t *rsc)
{
@@ -898,29 +868,72 @@ cli_cleanup_all(pcmk_ipc_api_t *controld_api, const char *node_name,
return rc;
}
-int
-cli_resource_check(pcmk__output_t *out, cib_t * cib_conn, pe_resource_t *rsc)
+static void
+check_role(pcmk__output_t *out, cib_t *cib_conn, resource_checks_t *checks)
{
char *role_s = NULL;
- char *managed = NULL;
- pe_resource_t *parent = uber_parent(rsc);
- int rc = pcmk_rc_no_output;
- resource_checks_t *checks = NULL;
-
- find_resource_attr(out, cib_conn, XML_NVPAIR_ATTR_VALUE, parent->id,
- NULL, NULL, NULL, XML_RSC_ATTR_MANAGED, &managed);
+ pe_resource_t *parent = uber_parent(checks->rsc);
find_resource_attr(out, cib_conn, XML_NVPAIR_ATTR_VALUE, parent->id,
NULL, NULL, NULL, XML_RSC_ATTR_TARGET_ROLE, &role_s);
+ if (role_s == NULL) {
+ return;
+ }
- checks = cli_check_resource(rsc, role_s, managed);
+ switch (text2role(role_s)) {
+ case RSC_ROLE_STOPPED:
+ checks->flags |= rsc_remain_stopped;
+ break;
- rc = out->message(out, "resource-check-list", checks);
+ case RSC_ROLE_UNPROMOTED:
+ if (pcmk_is_set(parent->flags, pe_rsc_promotable)) {
+ checks->flags |= rsc_unpromotable;
+ }
+ break;
+ default:
+ break;
+ }
free(role_s);
- free(managed);
- free(checks);
- return rc;
+}
+
+static void
+check_managed(pcmk__output_t *out, cib_t *cib_conn, resource_checks_t *checks)
+{
+ char *managed_s = NULL;
+ pe_resource_t *parent = uber_parent(checks->rsc);
+
+ find_resource_attr(out, cib_conn, XML_NVPAIR_ATTR_VALUE, parent->id,
+ NULL, NULL, NULL, XML_RSC_ATTR_MANAGED, &managed_s);
+ if (managed_s == NULL) {
+ return;
+ }
+
+ if (!crm_is_true(managed_s)) {
+ checks->flags |= rsc_unmanaged;
+ }
+ free(managed_s);
+}
+
+static void
+check_locked(resource_checks_t *checks)
+{
+ if (checks->rsc->lock_node != NULL) {
+ checks->flags |= rsc_locked;
+ checks->lock_node = checks->rsc->lock_node->details->uname;
+ }
+}
+
+int
+cli_resource_check(pcmk__output_t *out, cib_t * cib_conn, pe_resource_t *rsc)
+{
+ resource_checks_t checks = { .rsc = rsc };
+
+ check_role(out, cib_conn, &checks);
+ check_managed(out, cib_conn, &checks);
+ check_locked(&checks);
+
+ return out->message(out, "resource-check-list", &checks);
}
// \return Standard Pacemaker return code
--
2.31.1
From 32414475281d909cd808f723a41d88a5e0d2b254 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 5 Apr 2022 17:11:07 -0500
Subject: [PATCH 03/14] Fix: tools: crm_resource target-role check should use
meta-attribute table
Previously, check_role() searched the CIB for the uber-parent's target-role
attribute. That could give incorrect results if target-role was set on a
different resource in the ancestry chain (e.g. the resource itself for a group
member, or the group for a cloned group), or if there were multiple target-role
settings (e.g. using rules).
Now, target-role is checked in rsc->meta, which should be fully evaluated for
inheritance and rules.
---
tools/crm_resource_runtime.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index d47f959f5..e9d05cb77 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -869,24 +869,22 @@ cli_cleanup_all(pcmk_ipc_api_t *controld_api, const char *node_name,
}
static void
-check_role(pcmk__output_t *out, cib_t *cib_conn, resource_checks_t *checks)
+check_role(resource_checks_t *checks)
{
- char *role_s = NULL;
- pe_resource_t *parent = uber_parent(checks->rsc);
+ const char *role_s = g_hash_table_lookup(checks->rsc->meta,
+ XML_RSC_ATTR_TARGET_ROLE);
- find_resource_attr(out, cib_conn, XML_NVPAIR_ATTR_VALUE, parent->id,
- NULL, NULL, NULL, XML_RSC_ATTR_TARGET_ROLE, &role_s);
if (role_s == NULL) {
return;
}
-
switch (text2role(role_s)) {
case RSC_ROLE_STOPPED:
checks->flags |= rsc_remain_stopped;
break;
case RSC_ROLE_UNPROMOTED:
- if (pcmk_is_set(parent->flags, pe_rsc_promotable)) {
+ if (pcmk_is_set(uber_parent(checks->rsc)->flags,
+ pe_rsc_promotable)) {
checks->flags |= rsc_unpromotable;
}
break;
@@ -894,7 +892,6 @@ check_role(pcmk__output_t *out, cib_t *cib_conn, resource_checks_t *checks)
default:
break;
}
- free(role_s);
}
static void
@@ -929,7 +926,7 @@ cli_resource_check(pcmk__output_t *out, cib_t * cib_conn, pe_resource_t *rsc)
{
resource_checks_t checks = { .rsc = rsc };
- check_role(out, cib_conn, &checks);
+ check_role(&checks);
check_managed(out, cib_conn, &checks);
check_locked(&checks);
--
2.31.1
From 0fd133680f7b2c25a946cf3fb25f4ee9ffeeaf93 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 5 Apr 2022 17:15:43 -0500
Subject: [PATCH 04/14] Fix: tools: crm_resource is-managed check should use
meta-attribute table
Previously, check_managed() searched the CIB for the uber-parent's is-managed
attribute. That could give incorrect results if is-managed was set on a
different resource in the ancestry chain (e.g. the resource itself for a group
member, or the group for a cloned group), or if there were multiple is-managed
settings (e.g. using rules).
Now, is-managed is checked in rsc->meta, which should be fully evaluated for
inheritance and rules.
---
tools/crm_resource_runtime.c | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index e9d05cb77..4f62b4b2e 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -895,21 +895,14 @@ check_role(resource_checks_t *checks)
}
static void
-check_managed(pcmk__output_t *out, cib_t *cib_conn, resource_checks_t *checks)
+check_managed(resource_checks_t *checks)
{
- char *managed_s = NULL;
- pe_resource_t *parent = uber_parent(checks->rsc);
+ const char *managed_s = g_hash_table_lookup(checks->rsc->meta,
+ XML_RSC_ATTR_MANAGED);
- find_resource_attr(out, cib_conn, XML_NVPAIR_ATTR_VALUE, parent->id,
- NULL, NULL, NULL, XML_RSC_ATTR_MANAGED, &managed_s);
- if (managed_s == NULL) {
- return;
- }
-
- if (!crm_is_true(managed_s)) {
+ if ((managed_s != NULL) && !crm_is_true(managed_s)) {
checks->flags |= rsc_unmanaged;
}
- free(managed_s);
}
static void
@@ -927,7 +920,7 @@ cli_resource_check(pcmk__output_t *out, cib_t * cib_conn, pe_resource_t *rsc)
resource_checks_t checks = { .rsc = rsc };
check_role(&checks);
- check_managed(out, cib_conn, &checks);
+ check_managed(&checks);
check_locked(&checks);
return out->message(out, "resource-check-list", &checks);
--
2.31.1
From e9523c1b238492c8cf8b453ba6710f13bf81cd28 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 5 Apr 2022 17:18:44 -0500
Subject: [PATCH 05/14] Refactor: tools: drop unused argument from
cli_resource_check()
---
tools/crm_resource.c | 4 ++--
tools/crm_resource.h | 2 +-
tools/crm_resource_print.c | 24 ++++++++++++------------
tools/crm_resource_runtime.c | 2 +-
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 883563df9..bf5326b40 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1019,7 +1019,7 @@ cleanup(pcmk__output_t *out, pe_resource_t *rsc)
if ((rc == pcmk_rc_ok) && !out->is_quiet(out)) {
// Show any reasons why resource might stay stopped
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
}
if (rc == pcmk_rc_ok) {
@@ -1326,7 +1326,7 @@ refresh_resource(pcmk__output_t *out, pe_resource_t *rsc)
if ((rc == pcmk_rc_ok) && !out->is_quiet(out)) {
// Show any reasons why resource might stay stopped
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
}
if (rc == pcmk_rc_ok) {
diff --git a/tools/crm_resource.h b/tools/crm_resource.h
index b5fdd1bb5..bcff2b5f6 100644
--- a/tools/crm_resource.h
+++ b/tools/crm_resource.h
@@ -68,7 +68,7 @@ int cli_resource_print_operations(const char *rsc_id, const char *host_uname,
bool active, pe_working_set_t * data_set);
/* runtime */
-int cli_resource_check(pcmk__output_t *out, cib_t * cib, pe_resource_t *rsc);
+int cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc);
int cli_resource_fail(pcmk_ipc_api_t *controld_api, const char *host_uname,
const char *rsc_id, pe_working_set_t *data_set);
GList *cli_resource_search(pe_resource_t *rsc, const char *requested_name,
diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index f63fc952d..f025cbddd 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -587,7 +587,7 @@ PCMK__OUTPUT_ARGS("resource-reasons-list", "cib_t *", "GList *", "pe_resource_t
static int
resource_reasons_list_default(pcmk__output_t *out, va_list args)
{
- cib_t *cib_conn = va_arg(args, cib_t *);
+ cib_t *cib_conn G_GNUC_UNUSED = va_arg(args, cib_t *);
GList *resources = va_arg(args, GList *);
pe_resource_t *rsc = va_arg(args, pe_resource_t *);
pe_node_t *node = va_arg(args, pe_node_t *);
@@ -610,7 +610,7 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
out->list_item(out, "reason", "Resource %s is running", rsc->id);
}
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
g_list_free(hosts);
hosts = NULL;
}
@@ -624,7 +624,7 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
rsc->id, host_uname);
}
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
} else if ((rsc == NULL) && (host_uname != NULL)) {
const char* host_uname = node->details->uname;
@@ -637,14 +637,14 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
pe_resource_t *rsc = (pe_resource_t *) lpc->data;
out->list_item(out, "reason", "Resource %s is running on host %s",
rsc->id, host_uname);
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
}
for(lpc = unactiveResources; lpc != NULL; lpc = lpc->next) {
pe_resource_t *rsc = (pe_resource_t *) lpc->data;
out->list_item(out, "reason", "Resource %s is assigned to host %s but not running",
rsc->id, host_uname);
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
}
g_list_free(allResources);
@@ -657,7 +657,7 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
rsc->fns->location(rsc, &hosts, TRUE);
out->list_item(out, "reason", "Resource %s is %srunning",
rsc->id, (hosts? "" : "not "));
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
g_list_free(hosts);
}
@@ -670,7 +670,7 @@ PCMK__OUTPUT_ARGS("resource-reasons-list", "cib_t *", "GList *", "pe_resource_t
static int
resource_reasons_list_xml(pcmk__output_t *out, va_list args)
{
- cib_t *cib_conn = va_arg(args, cib_t *);
+ cib_t *cib_conn G_GNUC_UNUSED = va_arg(args, cib_t *);
GList *resources = va_arg(args, GList *);
pe_resource_t *rsc = va_arg(args, pe_resource_t *);
pe_node_t *node = va_arg(args, pe_node_t *);
@@ -695,7 +695,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
"running", pcmk__btoa(hosts != NULL),
NULL);
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
pcmk__output_xml_pop_parent(out);
g_list_free(hosts);
hosts = NULL;
@@ -708,7 +708,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
crm_xml_add(xml_node, "running_on", host_uname);
}
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
} else if ((rsc == NULL) && (host_uname != NULL)) {
const char* host_uname = node->details->uname;
@@ -728,7 +728,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
"host", host_uname,
NULL);
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
pcmk__output_xml_pop_parent(out);
}
@@ -741,7 +741,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
"host", host_uname,
NULL);
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
pcmk__output_xml_pop_parent(out);
}
@@ -755,7 +755,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
rsc->fns->location(rsc, &hosts, TRUE);
crm_xml_add(xml_node, "running", pcmk__btoa(hosts != NULL));
- cli_resource_check(out, cib_conn, rsc);
+ cli_resource_check(out, rsc);
g_list_free(hosts);
}
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 4f62b4b2e..47653a060 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -915,7 +915,7 @@ check_locked(resource_checks_t *checks)
}
int
-cli_resource_check(pcmk__output_t *out, cib_t * cib_conn, pe_resource_t *rsc)
+cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc)
{
resource_checks_t checks = { .rsc = rsc };
--
2.31.1
From b1a1a07f3e44bc74575eab325277ea8c1f3391b2 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 5 Apr 2022 17:20:06 -0500
Subject: [PATCH 06/14] Refactor: tools: drop unused argument from
resource-reasons-list message
---
tools/crm_resource.c | 2 +-
tools/crm_resource_print.c | 6 ++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index bf5326b40..7f656a20d 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1941,7 +1941,7 @@ main(int argc, char **argv)
if ((options.host_uname != NULL) && (node == NULL)) {
rc = pcmk_rc_node_unknown;
} else {
- rc = out->message(out, "resource-reasons-list", cib_conn,
+ rc = out->message(out, "resource-reasons-list",
data_set->resources, rsc, node);
}
break;
diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index f025cbddd..580f9c71a 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -582,12 +582,11 @@ resource_search_list_xml(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("resource-reasons-list", "cib_t *", "GList *", "pe_resource_t *",
+PCMK__OUTPUT_ARGS("resource-reasons-list", "GList *", "pe_resource_t *",
"pe_node_t *")
static int
resource_reasons_list_default(pcmk__output_t *out, va_list args)
{
- cib_t *cib_conn G_GNUC_UNUSED = va_arg(args, cib_t *);
GList *resources = va_arg(args, GList *);
pe_resource_t *rsc = va_arg(args, pe_resource_t *);
pe_node_t *node = va_arg(args, pe_node_t *);
@@ -665,12 +664,11 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
return pcmk_rc_ok;
}
-PCMK__OUTPUT_ARGS("resource-reasons-list", "cib_t *", "GList *", "pe_resource_t *",
+PCMK__OUTPUT_ARGS("resource-reasons-list", "GList *", "pe_resource_t *",
"pe_node_t *")
static int
resource_reasons_list_xml(pcmk__output_t *out, va_list args)
{
- cib_t *cib_conn G_GNUC_UNUSED = va_arg(args, cib_t *);
GList *resources = va_arg(args, GList *);
pe_resource_t *rsc = va_arg(args, pe_resource_t *);
pe_node_t *node = va_arg(args, pe_node_t *);
--
2.31.1
From 973eb2694b334b4e9e6967f6c7ceaebec10693db Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 10:08:37 -0500
Subject: [PATCH 07/14] Refactor: tools: pass node to cli_resource_check()
The node is not used yet
---
tools/crm_resource.c | 12 ++++++------
tools/crm_resource.h | 3 ++-
tools/crm_resource_print.c | 20 ++++++++++----------
tools/crm_resource_runtime.c | 2 +-
4 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 7f656a20d..756a06268 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1004,7 +1004,7 @@ ban_or_move(pcmk__output_t *out, pe_resource_t *rsc, const char *move_lifetime)
}
static void
-cleanup(pcmk__output_t *out, pe_resource_t *rsc)
+cleanup(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
{
int rc = pcmk_rc_ok;
@@ -1019,7 +1019,7 @@ cleanup(pcmk__output_t *out, pe_resource_t *rsc)
if ((rc == pcmk_rc_ok) && !out->is_quiet(out)) {
// Show any reasons why resource might stay stopped
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
}
if (rc == pcmk_rc_ok) {
@@ -1311,7 +1311,7 @@ refresh(pcmk__output_t *out)
}
static void
-refresh_resource(pcmk__output_t *out, pe_resource_t *rsc)
+refresh_resource(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
{
int rc = pcmk_rc_ok;
@@ -1326,7 +1326,7 @@ refresh_resource(pcmk__output_t *out, pe_resource_t *rsc)
if ((rc == pcmk_rc_ok) && !out->is_quiet(out)) {
// Show any reasons why resource might stay stopped
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
}
if (rc == pcmk_rc_ok) {
@@ -2075,7 +2075,7 @@ main(int argc, char **argv)
start_mainloop(controld_api);
}
} else {
- cleanup(out, rsc);
+ cleanup(out, rsc, node);
}
break;
@@ -2083,7 +2083,7 @@ main(int argc, char **argv)
if (rsc == NULL) {
rc = refresh(out);
} else {
- refresh_resource(out, rsc);
+ refresh_resource(out, rsc, node);
}
break;
diff --git a/tools/crm_resource.h b/tools/crm_resource.h
index bcff2b5f6..f7e44476d 100644
--- a/tools/crm_resource.h
+++ b/tools/crm_resource.h
@@ -68,7 +68,8 @@ int cli_resource_print_operations(const char *rsc_id, const char *host_uname,
bool active, pe_working_set_t * data_set);
/* runtime */
-int cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc);
+int cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc,
+ pe_node_t *node);
int cli_resource_fail(pcmk_ipc_api_t *controld_api, const char *host_uname,
const char *rsc_id, pe_working_set_t *data_set);
GList *cli_resource_search(pe_resource_t *rsc, const char *requested_name,
diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index 580f9c71a..087819601 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -609,7 +609,7 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
out->list_item(out, "reason", "Resource %s is running", rsc->id);
}
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, NULL);
g_list_free(hosts);
hosts = NULL;
}
@@ -623,7 +623,7 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
rsc->id, host_uname);
}
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
} else if ((rsc == NULL) && (host_uname != NULL)) {
const char* host_uname = node->details->uname;
@@ -636,14 +636,14 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
pe_resource_t *rsc = (pe_resource_t *) lpc->data;
out->list_item(out, "reason", "Resource %s is running on host %s",
rsc->id, host_uname);
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
}
for(lpc = unactiveResources; lpc != NULL; lpc = lpc->next) {
pe_resource_t *rsc = (pe_resource_t *) lpc->data;
out->list_item(out, "reason", "Resource %s is assigned to host %s but not running",
rsc->id, host_uname);
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
}
g_list_free(allResources);
@@ -656,7 +656,7 @@ resource_reasons_list_default(pcmk__output_t *out, va_list args)
rsc->fns->location(rsc, &hosts, TRUE);
out->list_item(out, "reason", "Resource %s is %srunning",
rsc->id, (hosts? "" : "not "));
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, NULL);
g_list_free(hosts);
}
@@ -693,7 +693,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
"running", pcmk__btoa(hosts != NULL),
NULL);
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, NULL);
pcmk__output_xml_pop_parent(out);
g_list_free(hosts);
hosts = NULL;
@@ -706,7 +706,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
crm_xml_add(xml_node, "running_on", host_uname);
}
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
} else if ((rsc == NULL) && (host_uname != NULL)) {
const char* host_uname = node->details->uname;
@@ -726,7 +726,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
"host", host_uname,
NULL);
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
pcmk__output_xml_pop_parent(out);
}
@@ -739,7 +739,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
"host", host_uname,
NULL);
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, node);
pcmk__output_xml_pop_parent(out);
}
@@ -753,7 +753,7 @@ resource_reasons_list_xml(pcmk__output_t *out, va_list args)
rsc->fns->location(rsc, &hosts, TRUE);
crm_xml_add(xml_node, "running", pcmk__btoa(hosts != NULL));
- cli_resource_check(out, rsc);
+ cli_resource_check(out, rsc, NULL);
g_list_free(hosts);
}
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 47653a060..68e899c45 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -915,7 +915,7 @@ check_locked(resource_checks_t *checks)
}
int
-cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc)
+cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
{
resource_checks_t checks = { .rsc = rsc };
--
2.31.1
From c3bfde0536f2eb51c81bf34fa957c38dc88f9cc3 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 09:49:03 -0500
Subject: [PATCH 08/14] Feature: tools: crm_resource --why now checks node
health status
Closes T65
---
tools/crm_resource.h | 1 +
tools/crm_resource_print.c | 13 +++++++++
tools/crm_resource_runtime.c | 56 ++++++++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+)
diff --git a/tools/crm_resource.h b/tools/crm_resource.h
index f7e44476d..ae4b02a98 100644
--- a/tools/crm_resource.h
+++ b/tools/crm_resource.h
@@ -37,6 +37,7 @@ enum resource_check_flags {
rsc_unpromotable = (1 << 1),
rsc_unmanaged = (1 << 2),
rsc_locked = (1 << 3),
+ rsc_node_health = (1 << 4),
};
typedef struct resource_checks_s {
diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
index 087819601..27fd76aaf 100644
--- a/tools/crm_resource_print.c
+++ b/tools/crm_resource_print.c
@@ -477,6 +477,15 @@ resource_check_list_default(pcmk__output_t *out, va_list args) {
parent->id, checks->lock_node);
}
+ if (pcmk_is_set(checks->flags, rsc_node_health)) {
+ out->list_item(out, "check",
+ "'%s' cannot run on unhealthy nodes due to "
+ PCMK__OPT_NODE_HEALTH_STRATEGY "='%s'",
+ parent->id,
+ pe_pref(checks->rsc->cluster->config_hash,
+ PCMK__OPT_NODE_HEALTH_STRATEGY));
+ }
+
out->end_list(out);
return pcmk_rc_ok;
}
@@ -508,6 +517,10 @@ resource_check_list_xml(pcmk__output_t *out, va_list args) {
crm_xml_add(node, "locked-to", checks->lock_node);
}
+ if (pcmk_is_set(checks->flags, rsc_node_health)) {
+ pcmk__xe_set_bool_attr(node, "unhealthy", true);
+ }
+
return pcmk_rc_ok;
}
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 68e899c45..2aa3efe38 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -914,6 +914,61 @@ check_locked(resource_checks_t *checks)
}
}
+static bool
+node_is_unhealthy(pe_node_t *node)
+{
+ switch (pe__health_strategy(node->details->data_set)) {
+ case pcmk__health_strategy_none:
+ break;
+
+ case pcmk__health_strategy_no_red:
+ if (pe__node_health(node) < 0) {
+ return true;
+ }
+ break;
+
+ case pcmk__health_strategy_only_green:
+ if (pe__node_health(node) <= 0) {
+ return true;
+ }
+ break;
+
+ case pcmk__health_strategy_progressive:
+ case pcmk__health_strategy_custom:
+ /* @TODO These are finite scores, possibly with rules, and possibly
+ * combining with other scores, so attributing these as a cause is
+ * nontrivial.
+ */
+ break;
+ }
+ return false;
+}
+
+static void
+check_node_health(resource_checks_t *checks, pe_node_t *node)
+{
+ if (node == NULL) {
+ GHashTableIter iter;
+ bool allowed = false;
+ bool all_nodes_unhealthy = true;
+
+ g_hash_table_iter_init(&iter, checks->rsc->allowed_nodes);
+ while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
+ allowed = true;
+ if (!node_is_unhealthy(node)) {
+ all_nodes_unhealthy = false;
+ break;
+ }
+ }
+ if (allowed && all_nodes_unhealthy) {
+ checks->flags |= rsc_node_health;
+ }
+
+ } else if (node_is_unhealthy(node)) {
+ checks->flags |= rsc_node_health;
+ }
+}
+
int
cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
{
@@ -922,6 +977,7 @@ cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
check_role(&checks);
check_managed(&checks);
check_locked(&checks);
+ check_node_health(&checks, node);
return out->message(out, "resource-check-list", &checks);
}
--
2.31.1
From 48730fd51a22e109514764a039e5c89fd204ad4c Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 10:41:48 -0500
Subject: [PATCH 09/14] Low: schemas: copy crm_resource API schema in
preparation for changes
---
include/crm/common/output_internal.h | 2 +-
xml/api/crm_resource-2.22.rng | 303 +++++++++++++++++++++++++++
2 files changed, 304 insertions(+), 1 deletion(-)
create mode 100644 xml/api/crm_resource-2.22.rng
diff --git a/include/crm/common/output_internal.h b/include/crm/common/output_internal.h
index ca16227fe..bdcae8ad6 100644
--- a/include/crm/common/output_internal.h
+++ b/include/crm/common/output_internal.h
@@ -28,7 +28,7 @@ extern "C" {
*/
-# define PCMK__API_VERSION "2.21"
+# define PCMK__API_VERSION "2.22"
#if defined(PCMK__WITH_ATTRIBUTE_OUTPUT_ARGS)
# define PCMK__OUTPUT_ARGS(ARGS...) __attribute__((output_args(ARGS)))
diff --git a/xml/api/crm_resource-2.22.rng b/xml/api/crm_resource-2.22.rng
new file mode 100644
index 000000000..cd74da0d8
--- /dev/null
+++ b/xml/api/crm_resource-2.22.rng
@@ -0,0 +1,303 @@
+<?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" />
+ <ref name="resource-agent-action" />
+ </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="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>
+ <optional>
+ <attribute name="execution_code"> <data type="integer" /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="execution_message"> <text/> </attribute>
+ </optional>
+ <optional>
+ <attribute name="reason"> <text/> </attribute>
+ </optional>
+ </element>
+ </define>
+
+ <define name="attribute-roles">
+ <choice>
+ <value>Stopped</value>
+ <value>Started</value>
+ <value>Promoted</value>
+ <value>Unpromoted</value>
+
+ <!-- These synonyms for Promoted/Unpromoted are allowed for
+ backward compatibility with output from older Pacemaker
+ versions that used them -->
+ <value>Master</value>
+ <value>Slave</value>
+ </choice>
+ </define>
+</grammar>
--
2.31.1
From 75a885d9da92c84038e3abf732c11cf3fb6a79a7 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 11:33:50 -0500
Subject: [PATCH 10/14] Fix: tools: correct crm_resource --why schema to match
actual output
If both a resource and node name are specified, "running_on" is optional
---
xml/api/crm_resource-2.22.rng | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/xml/api/crm_resource-2.22.rng b/xml/api/crm_resource-2.22.rng
index cd74da0d8..e89d850da 100644
--- a/xml/api/crm_resource-2.22.rng
+++ b/xml/api/crm_resource-2.22.rng
@@ -126,7 +126,9 @@
<define name="resource-and-uname">
<element name="reason">
- <attribute name="running_on"> <text/> </attribute>
+ <optional>
+ <attribute name="running_on"> <text/> </attribute>
+ </optional>
<ref name="resource-check"/>
</element>
</define>
--
2.31.1
From 5e4f993859dd68a3f88cb0648ace7b3837316288 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 11:20:03 -0500
Subject: [PATCH 11/14] Low: schemas: simplify crm_resource --why schema
---
xml/api/crm_resource-2.22.rng | 64 ++++++++++++-----------------------
1 file changed, 22 insertions(+), 42 deletions(-)
diff --git a/xml/api/crm_resource-2.22.rng b/xml/api/crm_resource-2.22.rng
index e89d850da..2d2ba839f 100644
--- a/xml/api/crm_resource-2.22.rng
+++ b/xml/api/crm_resource-2.22.rng
@@ -102,56 +102,36 @@
</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">
+ <!-- set only when resource and node are both specified -->
<optional>
<attribute name="running_on"> <text/> </attribute>
</optional>
- <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>
+ <!-- set only when only a resource is specified -->
+ <optional>
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ </optional>
+
+ <choice>
+ <ref name="reasons-with-no-resource"/>
+ <ref name="resource-check"/>
+ </choice>
</element>
</define>
- <define name="resource-but-no-uname">
- <element name="reason">
- <attribute name="running"> <data type="boolean"/> </attribute>
- <ref name="resource-check"/>
+ <define name="reasons-with-no-resource">
+ <element name="resources">
+ <zeroOrMore>
+ <element name="resource">
+ <attribute name="id"> <text/> </attribute>
+ <attribute name="running"> <data type="boolean"/> </attribute>
+ <optional>
+ <attribute name="host"> <text/> </attribute>
+ </optional>
+ <ref name="resource-check"/>
+ </element>
+ </zeroOrMore>
</element>
</define>
--
2.31.1
From 79bdbbde27ad340c2054089aaecf5e0b49296e59 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 11:28:11 -0500
Subject: [PATCH 12/14] Test: cts-cli: use validated XML output for
crm_resource --why test
---
cts/cli/regression.tools.exp | 8 ++++++--
cts/cts-cli.in | 4 ++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index 0d1cfa2ab..4237a3ec5 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -888,8 +888,12 @@ Deleted 'dummy' option: id=dummy-meta_attributes-is-managed name=is-managed
=#=#=#= End test: Create another resource meta attribute - OK (0) =#=#=#=
* Passed: crm_resource - Create another resource meta attribute
=#=#=#= Begin test: Show why a resource is not running =#=#=#=
-Resource dummy is not running
-Configuration specifies 'dummy' should remain stopped
+<pacemaker-result api-version="X" request="crm_resource -Y -r dummy --output-as=xml">
+ <reason running="false">
+ <check id="dummy" remain_stopped="true"/>
+ </reason>
+ <status code="0" message="OK"/>
+</pacemaker-result>
=#=#=#= End test: Show why a resource is not running - OK (0) =#=#=#=
* Passed: crm_resource - Show why a resource is not running
=#=#=#= Begin test: Remove another resource meta attribute =#=#=#=
diff --git a/cts/cts-cli.in b/cts/cts-cli.in
index 8565c485a..289ac966f 100755
--- a/cts/cts-cli.in
+++ b/cts/cts-cli.in
@@ -657,8 +657,8 @@ function test_tools() {
test_assert_validate $CRM_EX_OK 0
desc="Show why a resource is not running"
- cmd="crm_resource -Y -r dummy"
- test_assert $CRM_EX_OK 0
+ cmd="crm_resource -Y -r dummy --output-as=xml"
+ test_assert_validate $CRM_EX_OK 0
desc="Remove another resource meta attribute"
cmd="crm_resource -r dummy --meta -d target-role --output-as=xml"
--
2.31.1
From 929d1b40e82f186e7e31e380db2620e7e23968f1 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 10:43:22 -0500
Subject: [PATCH 13/14] Low: schemas: update crm_resource --why schema for new
health check
---
xml/api/crm_resource-2.22.rng | 3 +++
1 file changed, 3 insertions(+)
diff --git a/xml/api/crm_resource-2.22.rng b/xml/api/crm_resource-2.22.rng
index 2d2ba839f..8a4667559 100644
--- a/xml/api/crm_resource-2.22.rng
+++ b/xml/api/crm_resource-2.22.rng
@@ -157,6 +157,9 @@
<optional>
<attribute name="locked-to"> <text/> </attribute>
</optional>
+ <optional>
+ <attribute name="unhealthy"><value>true</value></attribute>
+ </optional>
</element>
</define>
--
2.31.1
From 6630e55abc7b26be294ab6d42f12cdb7e2c69b55 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Thu, 23 Jun 2022 11:07:20 -0500
Subject: [PATCH 14/14] Test: cts-cli: add tests for checking resource status
on unhealthy node
---
cts/cli/regression.tools.exp | 112 ++++++++++++++++++++++++++++++++++-
cts/cts-cli.in | 12 ++++
2 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
index 4237a3ec5..89ae4e97d 100644
--- a/cts/cli/regression.tools.exp
+++ b/cts/cli/regression.tools.exp
@@ -3406,13 +3406,14 @@ Removing constraint: cli-prefer-dummy
</cib>
=#=#=#= End test: Clear all implicit constraints for dummy - OK (0) =#=#=#=
* Passed: crm_resource - Clear all implicit constraints for dummy
-=#=#=#= Begin test: Delete a resource =#=#=#=
-=#=#=#= Current cib after: Delete a resource =#=#=#=
+=#=#=#= Begin test: Set a node health strategy =#=#=#=
+=#=#=#= Current cib after: Set a node health strategy =#=#=#=
<cib epoch="55" num_updates="0" admin_epoch="0">
<configuration>
<crm_config>
<cluster_property_set id="cib-bootstrap-options">
<nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="ignore"/>
+ <nvpair id="cib-bootstrap-options-node-health-strategy" name="node-health-strategy" value="migrate-on-red"/>
</cluster_property_set>
<cluster_property_set id="duplicate">
<nvpair id="duplicate-cluster-delay" name="cluster-delay" value="30s"/>
@@ -3427,6 +3428,113 @@ Removing constraint: cli-prefer-dummy
<node id="node2" uname="node2"/>
<node id="node3" uname="node3"/>
</nodes>
+ <resources>
+ <primitive id="dummy" class="ocf" provider="pacemaker" type="Dummy">
+ <meta_attributes id="dummy-meta_attributes"/>
+ <instance_attributes id="dummy-instance_attributes">
+ <nvpair id="dummy-instance_attributes-delay" name="delay" value="10s"/>
+ </instance_attributes>
+ </primitive>
+ <primitive id="Fence" class="stonith" type="fence_true"/>
+ <clone id="test-clone">
+ <primitive id="test-primitive" class="ocf" provider="pacemaker" type="Dummy">
+ <meta_attributes id="test-primitive-meta_attributes"/>
+ </primitive>
+ <meta_attributes id="test-clone-meta_attributes">
+ <nvpair id="test-clone-meta_attributes-is-managed" name="is-managed" value="true"/>
+ </meta_attributes>
+ </clone>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status/>
+</cib>
+=#=#=#= End test: Set a node health strategy - OK (0) =#=#=#=
+* Passed: crm_attribute - Set a node health strategy
+=#=#=#= Begin test: Set a node health attribute =#=#=#=
+=#=#=#= Current cib after: Set a node health attribute =#=#=#=
+<cib epoch="56" num_updates="0" admin_epoch="0">
+ <configuration>
+ <crm_config>
+ <cluster_property_set id="cib-bootstrap-options">
+ <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="ignore"/>
+ <nvpair id="cib-bootstrap-options-node-health-strategy" name="node-health-strategy" value="migrate-on-red"/>
+ </cluster_property_set>
+ <cluster_property_set id="duplicate">
+ <nvpair id="duplicate-cluster-delay" name="cluster-delay" value="30s"/>
+ </cluster_property_set>
+ </crm_config>
+ <nodes>
+ <node id="node1" uname="node1">
+ <instance_attributes id="nodes-node1">
+ <nvpair id="nodes-node1-ram" name="ram" value="1024M"/>
+ </instance_attributes>
+ </node>
+ <node id="node2" uname="node2"/>
+ <node id="node3" uname="node3">
+ <instance_attributes id="nodes-node3">
+ <nvpair id="nodes-node3-.health-cts-cli" name="#health-cts-cli" value="red"/>
+ </instance_attributes>
+ </node>
+ </nodes>
+ <resources>
+ <primitive id="dummy" class="ocf" provider="pacemaker" type="Dummy">
+ <meta_attributes id="dummy-meta_attributes"/>
+ <instance_attributes id="dummy-instance_attributes">
+ <nvpair id="dummy-instance_attributes-delay" name="delay" value="10s"/>
+ </instance_attributes>
+ </primitive>
+ <primitive id="Fence" class="stonith" type="fence_true"/>
+ <clone id="test-clone">
+ <primitive id="test-primitive" class="ocf" provider="pacemaker" type="Dummy">
+ <meta_attributes id="test-primitive-meta_attributes"/>
+ </primitive>
+ <meta_attributes id="test-clone-meta_attributes">
+ <nvpair id="test-clone-meta_attributes-is-managed" name="is-managed" value="true"/>
+ </meta_attributes>
+ </clone>
+ </resources>
+ <constraints/>
+ </configuration>
+ <status/>
+</cib>
+=#=#=#= End test: Set a node health attribute - OK (0) =#=#=#=
+* Passed: crm_attribute - Set a node health attribute
+=#=#=#= Begin test: Show why a resource is not running on an unhealthy node =#=#=#=
+<pacemaker-result api-version="X" request="crm_resource -N node3 -Y -r dummy --output-as=xml">
+ <reason>
+ <check id="dummy" unhealthy="true"/>
+ </reason>
+ <status code="0" message="OK"/>
+</pacemaker-result>
+=#=#=#= End test: Show why a resource is not running on an unhealthy node - OK (0) =#=#=#=
+* Passed: crm_resource - Show why a resource is not running on an unhealthy node
+=#=#=#= Begin test: Delete a resource =#=#=#=
+=#=#=#= Current cib after: Delete a resource =#=#=#=
+<cib epoch="57" num_updates="0" admin_epoch="0">
+ <configuration>
+ <crm_config>
+ <cluster_property_set id="cib-bootstrap-options">
+ <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="ignore"/>
+ <nvpair id="cib-bootstrap-options-node-health-strategy" name="node-health-strategy" value="migrate-on-red"/>
+ </cluster_property_set>
+ <cluster_property_set id="duplicate">
+ <nvpair id="duplicate-cluster-delay" name="cluster-delay" value="30s"/>
+ </cluster_property_set>
+ </crm_config>
+ <nodes>
+ <node id="node1" uname="node1">
+ <instance_attributes id="nodes-node1">
+ <nvpair id="nodes-node1-ram" name="ram" value="1024M"/>
+ </instance_attributes>
+ </node>
+ <node id="node2" uname="node2"/>
+ <node id="node3" uname="node3">
+ <instance_attributes id="nodes-node3">
+ <nvpair id="nodes-node3-.health-cts-cli" name="#health-cts-cli" value="red"/>
+ </instance_attributes>
+ </node>
+ </nodes>
<resources>
<primitive id="Fence" class="stonith" type="fence_true"/>
<clone id="test-clone">
diff --git a/cts/cts-cli.in b/cts/cts-cli.in
index 289ac966f..990d37cf7 100755
--- a/cts/cts-cli.in
+++ b/cts/cts-cli.in
@@ -883,6 +883,18 @@ function test_tools() {
cmd="crm_resource -r dummy -U"
test_assert $CRM_EX_OK
+ desc="Set a node health strategy"
+ cmd="crm_attribute -n node-health-strategy -v migrate-on-red"
+ test_assert $CRM_EX_OK
+
+ desc="Set a node health attribute"
+ cmd="crm_attribute -N node3 -n '#health-cts-cli' -v red"
+ test_assert $CRM_EX_OK
+
+ desc="Show why a resource is not running on an unhealthy node"
+ cmd="crm_resource -N node3 -Y -r dummy --output-as=xml"
+ test_assert_validate $CRM_EX_OK 0
+
desc="Delete a resource"
cmd="crm_resource -D -r dummy -t primitive"
test_assert $CRM_EX_OK
--
2.31.1