From db5c5f7b2bb2ef8eb25fcffe83d607027dcbb197 Mon Sep 17 00:00:00 2001 From: Oyvind Albrigtsen Date: Mar 09 2021 06:18:52 +0000 Subject: Feature/API: crmadmin/pcmk_list_nodes(): list remote/guest nodes and add parameter/variable to choose which node type(s) to list --- diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h index d8694ee..969a57d 100644 --- a/include/crm/common/xml_internal.h +++ b/include/crm/common/xml_internal.h @@ -123,6 +123,24 @@ do { } \ } while (0) +/* XML search strings for guest, remote and pacemaker_remote nodes */ + +/* search string to find CIB resources entries for guest nodes */ +#define XPATH_GUEST_NODE_CONFIG \ + "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \ + "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \ + "[@name='" XML_RSC_ATTR_REMOTE_NODE "']" + +/* search string to find CIB resources entries for remote nodes */ +#define XPATH_REMOTE_NODE_CONFIG \ + "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \ + "[@type='remote'][@provider='pacemaker']" + +/* search string to find CIB node status entries for pacemaker_remote nodes */ +#define XPATH_REMOTE_NODE_STATUS \ + "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \ + "[@" XML_NODE_IS_REMOTE "='true']" + enum pcmk__xml_artefact_ns { pcmk__xml_artefact_ns_legacy_rng = 1, pcmk__xml_artefact_ns_legacy_xslt, diff --git a/include/pacemaker.h b/include/pacemaker.h index 51bf585..42d096f 100644 --- a/include/pacemaker.h +++ b/include/pacemaker.h @@ -73,8 +73,6 @@ int pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc, pe_node_t *node, GHashTable *overrides, pe_working_set_t *data_set); -#ifdef BUILD_PUBLIC_LIBPACEMAKER - /*! * \brief Get nodes list * @@ -82,7 +80,9 @@ int pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc, * * \return Standard Pacemaker return code */ -int pcmk_list_nodes(xmlNodePtr *xml); +int pcmk_list_nodes(xmlNodePtr *xml, char *node_types); + +#ifdef BUILD_PUBLIC_LIBPACEMAKER /*! * \brief Perform a STONITH action. diff --git a/include/pcmki/pcmki_cluster_queries.h b/include/pcmki/pcmki_cluster_queries.h index eb3b51c..955eea3 100644 --- a/include/pcmki/pcmki_cluster_queries.h +++ b/include/pcmki/pcmki_cluster_queries.h @@ -8,7 +8,7 @@ int pcmk__controller_status(pcmk__output_t *out, char *dest_node, guint message_timeout_ms); int pcmk__designated_controller(pcmk__output_t *out, guint message_timeout_ms); int pcmk__pacemakerd_status(pcmk__output_t *out, char *ipc_name, guint message_timeout_ms); -int pcmk__list_nodes(pcmk__output_t *out, gboolean BASH_EXPORT); +int pcmk__list_nodes(pcmk__output_t *out, char *node_types, gboolean BASH_EXPORT); // remove when parameters removed from tools/crmadmin.c int pcmk__shutdown_controller(pcmk__output_t *out, char *dest_node); diff --git a/lib/cluster/membership.c b/lib/cluster/membership.c index 9c981b2..feed222 100644 --- a/lib/cluster/membership.c +++ b/lib/cluster/membership.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -209,22 +210,6 @@ is_dirty(gpointer key, gpointer value, gpointer user_data) return pcmk_is_set(((crm_node_t*)value)->flags, crm_node_dirty); } -/* search string to find CIB resources entries for guest nodes */ -#define XPATH_GUEST_NODE_CONFIG \ - "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \ - "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \ - "[@name='" XML_RSC_ATTR_REMOTE_NODE "']" - -/* search string to find CIB resources entries for remote nodes */ -#define XPATH_REMOTE_NODE_CONFIG \ - "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \ - "[@type='remote'][@provider='pacemaker']" - -/* search string to find CIB node status entries for pacemaker_remote nodes */ -#define XPATH_REMOTE_NODE_STATUS \ - "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \ - "[@" XML_NODE_IS_REMOTE "='true']" - /*! * \brief Repopulate the remote peer cache based on CIB XML * diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c index 1d1e775..fc5cfc4 100644 --- a/lib/pacemaker/pcmk_cluster_queries.c +++ b/lib/pacemaker/pcmk_cluster_queries.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -390,9 +391,33 @@ pcmk_pacemakerd_status(xmlNodePtr *xml, char *ipc_name, unsigned int message_tim return rc; } +/* user data for looping through remote node xpath searches */ +struct node_data { + pcmk__output_t *out; + int found; + const char *field; /* XML attribute to check for node name */ + const char *type; + gboolean BASH_EXPORT; +}; + +static void +remote_node_print_helper(xmlNode *result, void *user_data) +{ + struct node_data *data = user_data; + pcmk__output_t *out = data->out; + const char *remote = crm_element_value(result, data->field); + + // node name and node id are the same for remote/guest nodes + out->message(out, "crmadmin-node", data->type, + remote, + remote, + data->BASH_EXPORT); + data->found++; +} + // \return Standard Pacemaker return code int -pcmk__list_nodes(pcmk__output_t *out, gboolean BASH_EXPORT) +pcmk__list_nodes(pcmk__output_t *out, char *node_types, gboolean BASH_EXPORT) { cib_t *the_cib = cib_new(); xmlNode *xml_node = NULL; @@ -409,28 +434,60 @@ pcmk__list_nodes(pcmk__output_t *out, gboolean BASH_EXPORT) rc = the_cib->cmds->query(the_cib, NULL, &xml_node, cib_scope_local | cib_sync_call); if (rc == pcmk_ok) { - int found = 0; xmlNode *node = NULL; xmlNode *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node); + struct node_data data = { + .out = out, + .found = 0, + .BASH_EXPORT = BASH_EXPORT + }; out->begin_list(out, NULL, NULL, "nodes"); - for (node = first_named_child(nodes, XML_CIB_TAG_NODE); node != NULL; - node = crm_next_same_xml(node)) { - const char *node_type = BASH_EXPORT ? NULL : - crm_element_value(node, XML_ATTR_TYPE); - out->message(out, "crmadmin-node", node_type, - crm_str(crm_element_value(node, XML_ATTR_UNAME)), - crm_str(crm_element_value(node, XML_ATTR_ID)), - BASH_EXPORT); + if (!pcmk__str_empty(node_types) && strstr(node_types, "all")) { + node_types = NULL; + } + + if (pcmk__str_empty(node_types) || strstr(node_types, "member")) { + for (node = first_named_child(nodes, XML_CIB_TAG_NODE); node != NULL; + node = crm_next_same_xml(node)) { + const char *node_type = crm_element_value(node, XML_ATTR_TYPE); + //if (node_type == NULL || !strcmp(node_type, "member")) { + if (node_type == NULL) { + out->message(out, "crmadmin-node", node_type, + crm_str(crm_element_value(node, XML_ATTR_UNAME)), + crm_str(crm_element_value(node, XML_ATTR_ID)), + BASH_EXPORT); + data.found++; + } + + } + } + + if (pcmk__str_empty(node_types) || strstr(node_types, "pacemaker_remote")) { + data.field = "id"; + data.type = "pacemaker_remote"; + crm_foreach_xpath_result(xml_node, XPATH_REMOTE_NODE_STATUS, + remote_node_print_helper, &data); + } + + if (pcmk__str_empty(node_types) || strstr(node_types, "guest")) { + data.field = "value"; + data.type = "guest"; + crm_foreach_xpath_result(xml_node, XPATH_GUEST_NODE_CONFIG, + remote_node_print_helper, &data); + } - found++; + if (pcmk__str_empty(node_types) || !pcmk__strcmp(node_types, ",|^remote", pcmk__str_regex)) { + data.field = "id"; + data.type = "remote"; + crm_foreach_xpath_result(xml_node, XPATH_REMOTE_NODE_CONFIG, + remote_node_print_helper, &data); } - // @TODO List Pacemaker Remote nodes that don't have a entry out->end_list(out); - if (found == 0) { + if (data.found == 0) { out->info(out, "No nodes configured"); } @@ -440,9 +497,8 @@ pcmk__list_nodes(pcmk__output_t *out, gboolean BASH_EXPORT) return pcmk_legacy2rc(rc); } -#ifdef BUILD_PUBLIC_LIBPACEMAKER int -pcmk_list_nodes(xmlNodePtr *xml) +pcmk_list_nodes(xmlNodePtr *xml, char *node_types) { pcmk__output_t *out = NULL; int rc = pcmk_rc_ok; @@ -454,11 +510,10 @@ pcmk_list_nodes(xmlNodePtr *xml) pcmk__register_lib_messages(out); - rc = pcmk__list_nodes(out, FALSE); + rc = pcmk__list_nodes(out, node_types, FALSE); pcmk__out_epilogue(out, xml, rc); return rc; } -#endif // remove when parameters removed from tools/crmadmin.c int diff --git a/tools/crmadmin.c b/tools/crmadmin.c index 2d9d663..3f31c69 100644 --- a/tools/crmadmin.c +++ b/tools/crmadmin.c @@ -38,10 +38,12 @@ struct { gint timeout; char *dest_node; char *ipc_name; + char *node_types; gboolean BASH_EXPORT; } options = { .dest_node = NULL, .ipc_name = NULL, + .node_types = NULL, .BASH_EXPORT = FALSE }; @@ -93,6 +95,11 @@ static GOptionEntry additional_options[] = { "\n operation failed", NULL }, + { "node-types", 'T', 0, G_OPTION_ARG_STRING, &options.node_types, + "Node types to list (available options: all, member, pacemaker_remote," + "\n guest, remote) (valid with -N/--nodes)", + NULL + }, { "bash-export", 'B', 0, G_OPTION_ARG_NONE, &options.BASH_EXPORT, "Display nodes as shell commands of the form 'export uname=uuid'" "\n (valid with -N/--nodes)", @@ -264,7 +271,7 @@ main(int argc, char **argv) rc = pcmk__pacemakerd_status(out, options.ipc_name, options.timeout); break; case cmd_list_nodes: - rc = pcmk__list_nodes(out, options.BASH_EXPORT); + rc = pcmk__list_nodes(out, options.node_types, options.BASH_EXPORT); break; case cmd_whois_dc: rc = pcmk__designated_controller(out, options.timeout);