From a467f0953c61bd56a9b34a98c71855d3cfbf6ba4 Mon Sep 17 00:00:00 2001 From: Ken Gaillot 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 + +#include +#include + #include #include @@ -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 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 #include -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 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 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 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 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 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 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 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + promoted + + + + + + + + + + + + + + + + + + + + + + + + + + + ocf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Stopped + Started + Promoted + Unpromoted + + + Master + Slave + + + -- 2.31.1 From 75a885d9da92c84038e3abf732c11cf3fb6a79a7 Mon Sep 17 00:00:00 2001 From: Ken Gaillot 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 @@ - + + + -- 2.31.1 From 5e4f993859dd68a3f88cb0648ace7b3837316288 Mon Sep 17 00:00:00 2001 From: Ken Gaillot 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 @@ - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + + + + + + + + + - - - - + + + + + + + + + + + + -- 2.31.1 From 79bdbbde27ad340c2054089aaecf5e0b49296e59 Mon Sep 17 00:00:00 2001 From: Ken Gaillot 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 + + + + + + =#=#=#= 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 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 @@ + + true + -- 2.31.1 From 6630e55abc7b26be294ab6d42f12cdb7e2c69b55 Mon Sep 17 00:00:00 2001 From: Ken Gaillot 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 =#=#=#= 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 =#=#=#= + @@ -3427,6 +3428,113 @@ Removing constraint: cli-prefer-dummy + + + + + + + + + + + + + + + + + + + + + +=#=#=#= 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 =#=#=#= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +=#=#=#= 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 =#=#=#= + + + + + + +=#=#=#= 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 =#=#=#= + + + + + + + + + + + + + + + + + + + + + + + + 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