diff options
Diffstat (limited to '')
-rw-r--r-- | daemons/fenced/cts-fence-helper.c | 15 | ||||
-rw-r--r-- | daemons/fenced/fenced_cib.c | 219 | ||||
-rw-r--r-- | daemons/fenced/fenced_commands.c | 579 | ||||
-rw-r--r-- | daemons/fenced/fenced_history.c | 242 | ||||
-rw-r--r-- | daemons/fenced/fenced_remote.c | 459 | ||||
-rw-r--r-- | daemons/fenced/fenced_scheduler.c | 15 | ||||
-rw-r--r-- | daemons/fenced/pacemaker-fenced.c | 392 | ||||
-rw-r--r-- | daemons/fenced/pacemaker-fenced.h | 14 |
8 files changed, 950 insertions, 985 deletions
diff --git a/daemons/fenced/cts-fence-helper.c b/daemons/fenced/cts-fence-helper.c index 07bd500..edde8ca 100644 --- a/daemons/fenced/cts-fence-helper.c +++ b/daemons/fenced/cts-fence-helper.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * This source code is licensed under the GNU General Public License version 2 * or later (GPLv2+) WITHOUT ANY WARRANTY. @@ -20,7 +20,6 @@ #include <fcntl.h> #include <crm/crm.h> -#include <crm/msg_xml.h> #include <crm/common/ipc.h> #include <crm/cluster/internal.h> @@ -164,8 +163,10 @@ passive_test(void) stonith_api_delete(st); crm_exit(CRM_EX_DISCONNECT); } - st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback); - st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback); + st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_DISCONNECT, + st_callback); + st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_FENCE, + st_callback); st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback); st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback); st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback", @@ -325,8 +326,10 @@ sanity_tests(void) stonith_api_delete(st); crm_exit(CRM_EX_DISCONNECT); } - st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback); - st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback); + st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_DISCONNECT, + st_callback); + st->cmds->register_notification(st, PCMK__VALUE_ST_NOTIFY_FENCE, + st_callback); st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback); st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback); st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback", diff --git a/daemons/fenced/fenced_cib.c b/daemons/fenced/fenced_cib.c index e11bf68..6bf0e6f 100644 --- a/daemons/fenced/fenced_cib.c +++ b/daemons/fenced/fenced_cib.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -15,7 +15,6 @@ #include <libxml/xpath.h> #include <crm/crm.h> -#include <crm/msg_xml.h> #include <crm/common/xml.h> #include <crm/cluster/internal.h> @@ -55,11 +54,12 @@ node_has_attr(const char *node, const char *name, const char *value) */ xpath = g_string_sized_new(256); pcmk__g_strcat(xpath, - "//" XML_CIB_TAG_NODES "/" XML_CIB_TAG_NODE - "[@" XML_ATTR_UNAME "='", node, "']/" XML_TAG_ATTR_SETS - "/" XML_CIB_TAG_NVPAIR - "[@" XML_NVPAIR_ATTR_NAME "='", name, "' " - "and @" XML_NVPAIR_ATTR_VALUE "='", value, "']", NULL); + "//" PCMK_XE_NODES "/" PCMK_XE_NODE + "[@" PCMK_XA_UNAME "='", node, "']" + "/" PCMK_XE_INSTANCE_ATTRIBUTES + "/" PCMK_XE_NVPAIR + "[@" PCMK_XA_NAME "='", name, "' " + "and @" PCMK_XA_VALUE "='", value, "']", NULL); match = get_xpath_object((const char *) xpath->str, local_cib, LOG_NEVER); @@ -76,7 +76,7 @@ add_topology_level(xmlNode *match) CRM_CHECK(match != NULL, return); fenced_register_level(match, &desc, &result); - fenced_send_level_notification(STONITH_OP_LEVEL_ADD, &result, desc); + fenced_send_config_notification(STONITH_OP_LEVEL_ADD, &result, desc); pcmk__reset_result(&result); free(desc); } @@ -86,14 +86,14 @@ topology_remove_helper(const char *node, int level) { char *desc = NULL; pcmk__action_result_t result = PCMK__UNKNOWN_RESULT; - xmlNode *data = create_xml_node(NULL, XML_TAG_FENCING_LEVEL); + xmlNode *data = pcmk__xe_create(NULL, PCMK_XE_FENCING_LEVEL); - crm_xml_add(data, F_STONITH_ORIGIN, __func__); - crm_xml_add_int(data, XML_ATTR_STONITH_INDEX, level); - crm_xml_add(data, XML_ATTR_STONITH_TARGET, node); + crm_xml_add(data, PCMK__XA_ST_ORIGIN, __func__); + crm_xml_add_int(data, PCMK_XA_INDEX, level); + crm_xml_add(data, PCMK_XA_TARGET, node); fenced_unregister_level(data, &desc, &result); - fenced_send_level_notification(STONITH_OP_LEVEL_DEL, &result, desc); + fenced_send_config_notification(STONITH_OP_LEVEL_DEL, &result, desc); pcmk__reset_result(&result); free_xml(data); free(desc); @@ -108,7 +108,7 @@ remove_topology_level(xmlNode *match) CRM_CHECK(match != NULL, return); key = stonith_level_key(match, fenced_target_by_unknown); - crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index); + crm_element_value_int(match, PCMK_XA_INDEX, &index); topology_remove_helper(key, index); free(key); } @@ -149,7 +149,7 @@ void fencing_topology_init(void) { xmlXPathObjectPtr xpathObj = NULL; - const char *xpath = "//" XML_TAG_FENCING_LEVEL; + const char *xpath = "//" PCMK_XE_FENCING_LEVEL; crm_trace("Full topology refresh"); free_topology_list(); @@ -174,37 +174,41 @@ remove_cib_device(xmlXPathObjectPtr xpathObj) CRM_LOG_ASSERT(match != NULL); if(match != NULL) { - standard = crm_element_value(match, XML_AGENT_ATTR_CLASS); + standard = crm_element_value(match, PCMK_XA_CLASS); } if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) { continue; } - rsc_id = crm_element_value(match, XML_ATTR_ID); + rsc_id = crm_element_value(match, PCMK_XA_ID); stonith_device_remove(rsc_id, true); } } +#define XPATH_WATCHDOG_TIMEOUT "//" PCMK_XE_NVPAIR \ + "[@" PCMK_XA_NAME "='" \ + PCMK_OPT_STONITH_WATCHDOG_TIMEOUT "']" + static void update_stonith_watchdog_timeout_ms(xmlNode *cib) { - long timeout_ms = 0; + long long timeout_ms = 0; xmlNode *stonith_watchdog_xml = NULL; const char *value = NULL; - stonith_watchdog_xml = get_xpath_object("//nvpair[@name='stonith-watchdog-timeout']", - cib, LOG_NEVER); + stonith_watchdog_xml = get_xpath_object(XPATH_WATCHDOG_TIMEOUT, cib, + LOG_NEVER); if (stonith_watchdog_xml) { - value = crm_element_value(stonith_watchdog_xml, XML_NVPAIR_ATTR_VALUE); + value = crm_element_value(stonith_watchdog_xml, PCMK_XA_VALUE); } if (value) { timeout_ms = crm_get_msec(value); } if (timeout_ms < 0) { - timeout_ms = pcmk__auto_watchdog_timeout(); + timeout_ms = pcmk__auto_stonith_watchdog_timeout(); } stonith_watchdog_timeout_ms = timeout_ms; @@ -221,9 +225,9 @@ cib_devices_update(void) stonith_device_t *device = NULL; crm_info("Updating devices to version %s.%s.%s", - crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN), - crm_element_value(local_cib, XML_ATTR_GENERATION), - crm_element_value(local_cib, XML_ATTR_NUMUPDATES)); + crm_element_value(local_cib, PCMK_XA_ADMIN_EPOCH), + crm_element_value(local_cib, PCMK_XA_EPOCH), + crm_element_value(local_cib, PCMK_XA_NUM_UPDATES)); g_hash_table_iter_init(&iter, device_list); while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) { @@ -256,7 +260,9 @@ update_cib_stonith_devices_v1(const char *event, xmlNode * msg) xmlXPathObjectPtr xpath_obj = NULL; /* process new constraints */ - xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_CONS_TAG_RSC_LOCATION); + xpath_obj = xpath_search(msg, + "//" PCMK__XE_CIB_UPDATE_RESULT + "//" PCMK_XE_RSC_LOCATION); if (numXpathResults(xpath_obj) > 0) { int max = numXpathResults(xpath_obj), lpc = 0; @@ -273,14 +279,20 @@ update_cib_stonith_devices_v1(const char *event, xmlNode * msg) freeXpathObject(xpath_obj); /* process deletions */ - xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_CIB_TAG_RESOURCE); + xpath_obj = xpath_search(msg, + "//" PCMK__XE_CIB_UPDATE_RESULT + "//" PCMK__XE_DIFF_REMOVED + "//" PCMK_XE_PRIMITIVE); if (numXpathResults(xpath_obj) > 0) { remove_cib_device(xpath_obj); } freeXpathObject(xpath_obj); /* process additions */ - xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_RESOURCE); + xpath_obj = xpath_search(msg, + "//" PCMK__XE_CIB_UPDATE_RESULT + "//" PCMK__XE_DIFF_ADDED + "//" PCMK_XE_PRIMITIVE); if (numXpathResults(xpath_obj) > 0) { int max = numXpathResults(xpath_obj), lpc = 0; @@ -289,8 +301,8 @@ update_cib_stonith_devices_v1(const char *event, xmlNode * msg) const char *standard = NULL; xmlNode *match = getXpathResult(xpath_obj, lpc); - rsc_id = crm_element_value(match, XML_ATTR_ID); - standard = crm_element_value(match, XML_AGENT_ATTR_CLASS); + rsc_id = crm_element_value(match, PCMK_XA_ID); + standard = crm_element_value(match, PCMK_XA_CLASS); if (!pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) { continue; @@ -314,35 +326,39 @@ update_cib_stonith_devices_v2(const char *event, xmlNode * msg) { xmlNode *change = NULL; char *reason = NULL; - bool needs_update = FALSE; - xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); + xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, + NULL, NULL); + xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL); + + for (change = pcmk__xe_first_child(patchset, NULL, NULL, NULL); + change != NULL; change = pcmk__xe_next(change)) { - for (change = pcmk__xml_first_child(patchset); change != NULL; - change = pcmk__xml_next(change)) { - const char *op = crm_element_value(change, XML_DIFF_OP); - const char *xpath = crm_element_value(change, XML_DIFF_PATH); + const char *op = crm_element_value(change, PCMK_XA_OPERATION); + const char *xpath = crm_element_value(change, PCMK_XA_PATH); const char *shortpath = NULL; - if ((op == NULL) || - (strcmp(op, "move") == 0) || - strstr(xpath, "/"XML_CIB_TAG_STATUS)) { + if (pcmk__str_eq(op, PCMK_VALUE_MOVE, pcmk__str_null_matches) + || (strstr(xpath, "/" PCMK_XE_STATUS) != NULL)) { continue; - } else if (pcmk__str_eq(op, "delete", pcmk__str_casei) && strstr(xpath, "/"XML_CIB_TAG_RESOURCE)) { + } + + if (pcmk__str_eq(op, PCMK_VALUE_DELETE, pcmk__str_none) + && (strstr(xpath, "/" PCMK_XE_PRIMITIVE) != NULL)) { const char *rsc_id = NULL; char *search = NULL; char *mutable = NULL; - if (strstr(xpath, XML_TAG_ATTR_SETS) || - strstr(xpath, XML_TAG_META_SETS)) { - needs_update = TRUE; - pcmk__str_update(&reason, - "(meta) attribute deleted from resource"); + if ((strstr(xpath, PCMK_XE_INSTANCE_ATTRIBUTES) != NULL) + || (strstr(xpath, PCMK_XE_META_ATTRIBUTES) != NULL)) { + + reason = pcmk__str_copy("(meta) attribute deleted from " + "resource"); break; } - pcmk__str_update(&mutable, xpath); - rsc_id = strstr(mutable, "primitive[@" XML_ATTR_ID "=\'"); + mutable = pcmk__str_copy(xpath); + rsc_id = strstr(mutable, PCMK_XE_PRIMITIVE "[@" PCMK_XA_ID "=\'"); if (rsc_id != NULL) { - rsc_id += strlen("primitive[@" XML_ATTR_ID "=\'"); + rsc_id += strlen(PCMK_XE_PRIMITIVE "[@" PCMK_XA_ID "=\'"); search = strchr(rsc_id, '\''); } if (search != NULL) { @@ -355,30 +371,31 @@ update_cib_stonith_devices_v2(const char *event, xmlNode * msg) } free(mutable); - } else if (strstr(xpath, "/"XML_CIB_TAG_RESOURCES) || - strstr(xpath, "/"XML_CIB_TAG_CONSTRAINTS) || - strstr(xpath, "/"XML_CIB_TAG_RSCCONFIG)) { + } else if (strstr(xpath, "/" PCMK_XE_RESOURCES) + || strstr(xpath, "/" PCMK_XE_CONSTRAINTS) + || strstr(xpath, "/" PCMK_XE_RSC_DEFAULTS)) { shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath); reason = crm_strdup_printf("%s %s", op, shortpath+1); - needs_update = TRUE; break; } } - if(needs_update) { + if (reason != NULL) { crm_info("Updating device list from CIB: %s", reason); cib_devices_update(); + free(reason); } else { crm_trace("No updates for device list found in CIB"); } - free(reason); } static void update_cib_stonith_devices(const char *event, xmlNode * msg) { int format = 1; - xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); + xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, + NULL, NULL); + xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL); CRM_ASSERT(patchset); crm_element_value_int(patchset, PCMK_XA_FORMAT, &format); @@ -465,17 +482,19 @@ remove_fencing_topology(xmlXPathObjectPtr xpathObj) xmlNode *match = getXpathResult(xpathObj, lpc); CRM_LOG_ASSERT(match != NULL); - if (match && crm_element_value(match, XML_DIFF_MARKER)) { + if (match && crm_element_value(match, PCMK__XA_CRM_DIFF_MARKER)) { /* Deletion */ int index = 0; char *target = stonith_level_key(match, fenced_target_by_unknown); - crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index); + crm_element_value_int(match, PCMK_XA_INDEX, &index); if (target == NULL) { - crm_err("Invalid fencing target in element %s", ID(match)); + crm_err("Invalid fencing target in element %s", + pcmk__xe_id(match)); } else if (index <= 0) { - crm_err("Invalid level for %s in element %s", target, ID(match)); + crm_err("Invalid level for %s in element %s", + target, pcmk__xe_id(match)); } else { topology_remove_helper(target, index); @@ -491,21 +510,27 @@ update_fencing_topology(const char *event, xmlNode * msg) int format = 1; const char *xpath; xmlXPathObjectPtr xpathObj = NULL; - xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); + xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, + NULL, NULL); + xmlNode *patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL); CRM_ASSERT(patchset); crm_element_value_int(patchset, PCMK_XA_FORMAT, &format); if(format == 1) { /* Process deletions (only) */ - xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_FENCING_LEVEL; + xpath = "//" PCMK__XE_CIB_UPDATE_RESULT + "//" PCMK__XE_DIFF_REMOVED + "//" PCMK_XE_FENCING_LEVEL; xpathObj = xpath_search(msg, xpath); remove_fencing_topology(xpathObj); freeXpathObject(xpathObj); /* Process additions and changes */ - xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL; + xpath = "//" PCMK__XE_CIB_UPDATE_RESULT + "//" PCMK__XE_DIFF_ADDED + "//" PCMK_XE_FENCING_LEVEL; xpathObj = xpath_search(msg, xpath); register_fencing_topology(xpathObj); @@ -518,33 +543,36 @@ update_fencing_topology(const char *event, xmlNode * msg) xml_patch_versions(patchset, add, del); - for (change = pcmk__xml_first_child(patchset); change != NULL; - change = pcmk__xml_next(change)) { - const char *op = crm_element_value(change, XML_DIFF_OP); - const char *xpath = crm_element_value(change, XML_DIFF_PATH); + for (change = pcmk__xe_first_child(patchset, NULL, NULL, NULL); + change != NULL; change = pcmk__xe_next(change)) { + + const char *op = crm_element_value(change, PCMK_XA_OPERATION); + const char *xpath = crm_element_value(change, PCMK_XA_PATH); if(op == NULL) { continue; - } else if(strstr(xpath, "/" XML_TAG_FENCING_LEVEL) != NULL) { + } else if(strstr(xpath, "/" PCMK_XE_FENCING_LEVEL) != NULL) { /* Change to a specific entry */ crm_trace("Handling %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath); - if(strcmp(op, "move") == 0) { + if (strcmp(op, PCMK_VALUE_MOVE) == 0) { continue; - } else if(strcmp(op, "create") == 0) { + } else if (strcmp(op, PCMK_VALUE_CREATE) == 0) { add_topology_level(change->children); - } else if(strcmp(op, "modify") == 0) { - xmlNode *match = first_named_child(change, XML_DIFF_RESULT); + } else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) { + xmlNode *match = pcmk__xe_first_child(change, + PCMK_XE_CHANGE_RESULT, + NULL, NULL); if(match) { remove_topology_level(match->children); add_topology_level(match->children); } - } else if(strcmp(op, "delete") == 0) { + } else if (strcmp(op, PCMK_VALUE_DELETE) == 0) { /* Nuclear option, all we have is the path and an id... not enough to remove a specific entry */ crm_info("Re-initializing fencing topology after %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath); @@ -552,20 +580,23 @@ update_fencing_topology(const char *event, xmlNode * msg) return; } - } else if (strstr(xpath, "/" XML_TAG_FENCING_TOPOLOGY) != NULL) { + } else if (strstr(xpath, "/" PCMK_XE_FENCING_TOPOLOGY) != NULL) { /* Change to the topology in general */ crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath); fencing_topology_init(); return; - } else if (strstr(xpath, "/" XML_CIB_TAG_CONFIGURATION)) { + } else if (strstr(xpath, "/" PCMK_XE_CONFIGURATION)) { /* Changes to the whole config section, possibly including the topology as a whild */ - if(first_named_child(change, XML_TAG_FENCING_TOPOLOGY) == NULL) { + if (pcmk__xe_first_child(change, PCMK_XE_FENCING_TOPOLOGY, NULL, + NULL) == NULL) { crm_trace("Nothing for us in %s operation %d.%d.%d for %s.", op, add[0], add[1], add[2], xpath); - } else if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) { + } else if (pcmk__str_any_of(op, + PCMK_VALUE_DELETE, + PCMK_VALUE_CREATE, NULL)) { crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s.", op, add[0], add[1], add[2], xpath); fencing_topology_init(); @@ -586,7 +617,7 @@ update_fencing_topology(const char *event, xmlNode * msg) static void update_cib_cache_cb(const char *event, xmlNode * msg) { - long timeout_ms_saved = stonith_watchdog_timeout_ms; + long long timeout_ms_saved = stonith_watchdog_timeout_ms; bool need_full_refresh = false; if(!have_cib_devices) { @@ -603,14 +634,18 @@ update_cib_cache_cb(const char *event, xmlNode * msg) */ if (local_cib != NULL) { int rc = pcmk_ok; + xmlNode *wrapper = NULL; xmlNode *patchset = NULL; - crm_element_value_int(msg, F_CIB_RC, &rc); + crm_element_value_int(msg, PCMK__XA_CIB_RC, &rc); if (rc != pcmk_ok) { return; } - patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); + wrapper = pcmk__xe_first_child(msg, PCMK__XE_CIB_UPDATE_RESULT, NULL, + NULL); + patchset = pcmk__xe_first_child(wrapper, NULL, NULL, NULL); + rc = xml_apply_patchset(local_cib, patchset, TRUE); switch (rc) { case pcmk_ok: @@ -660,7 +695,7 @@ init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *us { crm_info("Updating device list from CIB"); have_cib_devices = TRUE; - local_cib = copy_xml(output); + local_cib = pcmk__xml_copy(NULL, output); pcmk__refresh_node_caches_from_cib(local_cib); update_stonith_watchdog_timeout_ms(local_cib); @@ -693,7 +728,7 @@ void fenced_cib_cleanup(void) { if (cib_api != NULL) { - cib_api->cmds->del_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, + cib_api->cmds->del_notify_callback(cib_api, PCMK__VALUE_CIB_DIFF_NOTIFY, update_cib_cache_cb); cib__clean_up_connection(&cib_api); } @@ -719,16 +754,20 @@ setup_cib(void) if (rc != pcmk_ok) { crm_err("Could not connect to the CIB manager: %s (%d)", pcmk_strerror(rc), rc); + return; + } - } else if (pcmk_ok != - cib_api->cmds->add_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, update_cib_cache_cb)) { + rc = cib_api->cmds->add_notify_callback(cib_api, + PCMK__VALUE_CIB_DIFF_NOTIFY, + update_cib_cache_cb); + if (rc != pcmk_ok) { crm_err("Could not set CIB notification callback"); - - } else { - rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local); - cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL, "init_cib_cache_cb", - init_cib_cache_cb); - cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy); - crm_info("Watching for fencing topology changes"); + return; } + + rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local); + cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL, + "init_cib_cache_cb", init_cib_cache_cb); + cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy); + crm_info("Watching for fencing topology changes"); } diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 7a62ed6..223a701 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -23,7 +23,6 @@ #include <ctype.h> #include <crm/crm.h> -#include <crm/msg_xml.h> #include <crm/common/ipc.h> #include <crm/common/ipc_internal.h> #include <crm/cluster/internal.h> @@ -129,7 +128,7 @@ static int get_action_delay_max(const stonith_device_t *device, const char *action) { const char *value = NULL; - int delay_max = 0; + guint delay_max = 0U; if (!pcmk__is_fencing_action(action)) { return 0; @@ -137,10 +136,11 @@ get_action_delay_max(const stonith_device_t *device, const char *action) value = g_hash_table_lookup(device->params, PCMK_STONITH_DELAY_MAX); if (value) { - delay_max = crm_parse_interval_spec(value) / 1000; + pcmk_parse_interval_spec(value, &delay_max); + delay_max /= 1000; } - return delay_max; + return (int) delay_max; } static int @@ -148,7 +148,7 @@ get_action_delay_base(const stonith_device_t *device, const char *action, const char *target) { char *hash_value = NULL; - int delay_base = 0; + guint delay_base = 0U; if (!pcmk__is_fencing_action(action)) { return 0; @@ -157,11 +157,9 @@ get_action_delay_base(const stonith_device_t *device, const char *action, hash_value = g_hash_table_lookup(device->params, PCMK_STONITH_DELAY_BASE); if (hash_value) { - char *value = strdup(hash_value); + char *value = pcmk__str_copy(hash_value); char *valptr = value; - CRM_ASSERT(value != NULL); - if (target != NULL) { for (char *val = strtok(value, "; \t"); val != NULL; val = strtok(NULL, "; \t")) { char *mapval = strchr(val, ':'); @@ -181,13 +179,14 @@ get_action_delay_base(const stonith_device_t *device, const char *action, } if (strchr(value, ':') == 0) { - delay_base = crm_parse_interval_spec(value) / 1000; + pcmk_parse_interval_spec(value, &delay_base); + delay_base /= 1000; } free(valptr); } - return delay_base; + return (int) delay_base; } /*! @@ -232,7 +231,8 @@ get_action_timeout(const stonith_device_t *device, const char *action, snprintf(buffer, sizeof(buffer), "pcmk_%s_timeout", action); value = g_hash_table_lookup(device->params, buffer); if (value) { - return atoi(value); + long long timeout_ms = crm_get_msec(value); + return (int) QB_MIN(timeout_ms / 1000, INT_MAX); } } return default_timeout; @@ -345,34 +345,33 @@ create_async_command(xmlNode *msg) return NULL; } - op = get_xpath_object("//@" F_STONITH_ACTION, msg, LOG_ERR); + op = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, msg, LOG_ERR); if (op == NULL) { return NULL; } - cmd = calloc(1, sizeof(async_command_t)); - CRM_ASSERT(cmd != NULL); + cmd = pcmk__assert_alloc(1, sizeof(async_command_t)); // All messages must include these - cmd->action = crm_element_value_copy(op, F_STONITH_ACTION); - cmd->op = crm_element_value_copy(msg, F_STONITH_OPERATION); - cmd->client = crm_element_value_copy(msg, F_STONITH_CLIENTID); + cmd->action = crm_element_value_copy(op, PCMK__XA_ST_DEVICE_ACTION); + cmd->op = crm_element_value_copy(msg, PCMK__XA_ST_OP); + cmd->client = crm_element_value_copy(msg, PCMK__XA_ST_CLIENTID); if ((cmd->action == NULL) || (cmd->op == NULL) || (cmd->client == NULL)) { free_async_command(cmd); return NULL; } - crm_element_value_int(msg, F_STONITH_CALLID, &(cmd->id)); - crm_element_value_int(msg, F_STONITH_CALLOPTS, &(cmd->options)); - crm_element_value_int(msg, F_STONITH_DELAY, &(cmd->start_delay)); - crm_element_value_int(msg, F_STONITH_TIMEOUT, &(cmd->default_timeout)); + crm_element_value_int(msg, PCMK__XA_ST_CALLID, &(cmd->id)); + crm_element_value_int(msg, PCMK__XA_ST_CALLOPT, &(cmd->options)); + crm_element_value_int(msg, PCMK__XA_ST_DELAY, &(cmd->start_delay)); + crm_element_value_int(msg, PCMK__XA_ST_TIMEOUT, &(cmd->default_timeout)); cmd->timeout = cmd->default_timeout; - cmd->origin = crm_element_value_copy(msg, F_ORIG); - cmd->remote_op_id = crm_element_value_copy(msg, F_STONITH_REMOTE_OP_ID); - cmd->client_name = crm_element_value_copy(msg, F_STONITH_CLIENTNAME); - cmd->target = crm_element_value_copy(op, F_STONITH_TARGET); - cmd->device = crm_element_value_copy(op, F_STONITH_DEVICE); + cmd->origin = crm_element_value_copy(msg, PCMK__XA_SRC); + cmd->remote_op_id = crm_element_value_copy(msg, PCMK__XA_ST_REMOTE_OP); + cmd->client_name = crm_element_value_copy(msg, PCMK__XA_ST_CLIENTNAME); + cmd->target = crm_element_value_copy(op, PCMK__XA_ST_TARGET); + cmd->device = crm_element_value_copy(op, PCMK__XA_ST_DEVICE_ID); cmd->done_cb = st_child_done; @@ -645,12 +644,13 @@ schedule_stonith_command(async_command_t * cmd, stonith_device_t * device) } if (device->include_nodeid && (cmd->target != NULL)) { - crm_node_t *node = crm_get_peer(0, cmd->target); + crm_node_t *node = pcmk__get_node(0, cmd->target, NULL, + pcmk__node_search_cluster_member); cmd->target_nodeid = node->id; } - cmd->device = strdup(device->id); + cmd->device = pcmk__str_copy(device->id); cmd->timeout = get_action_timeout(device, cmd->action, cmd->default_timeout); if (cmd->remote_op_id) { @@ -785,7 +785,7 @@ build_port_aliases(const char *hostmap, GList ** targets) case ':': if (lpc > last) { free(name); - name = calloc(1, 1 + lpc - last); + name = pcmk__assert_alloc(1, 1 + lpc - last); memcpy(name, hostmap + last, lpc - last); } last = lpc + 1; @@ -801,7 +801,7 @@ build_port_aliases(const char *hostmap, GList ** targets) char *value = NULL; int k = 0; - value = calloc(1, 1 + lpc - last); + value = pcmk__assert_alloc(1, 1 + lpc - last); memcpy(value, hostmap + last, lpc - last); for (int i = 0; value[i] != '\0'; i++) { @@ -814,7 +814,7 @@ build_port_aliases(const char *hostmap, GList ** targets) crm_debug("Adding alias '%s'='%s'", name, value); g_hash_table_replace(aliases, name, value); if (targets) { - *targets = g_list_append(*targets, strdup(value)); + *targets = g_list_append(*targets, pcmk__str_copy(value)); } value = NULL; name = NULL; @@ -888,10 +888,10 @@ get_agent_metadata(const char *agent, xmlNode ** metadata) crm_err("Could not retrieve metadata for fencing agent %s", agent); return EAGAIN; } - g_hash_table_replace(metadata_cache, strdup(agent), buffer); + g_hash_table_replace(metadata_cache, pcmk__str_copy(agent), buffer); } - *metadata = string2xml(buffer); + *metadata = pcmk__xml_parse(buffer); return pcmk_rc_ok; } @@ -908,7 +908,8 @@ is_nodeid_required(xmlNode * xml) return FALSE; } - xpath = xpath_search(xml, "//parameter[@name='nodeid']"); + xpath = xpath_search(xml, + "//" PCMK_XE_PARAMETER "[@" PCMK_XA_NAME "='nodeid']"); if (numXpathResults(xpath) <= 0) { freeXpathObject(xpath); return FALSE; @@ -944,7 +945,7 @@ read_action_metadata(stonith_device_t *device) CRM_LOG_ASSERT(match != NULL); if(match == NULL) { continue; }; - action = crm_element_value(match, "name"); + action = crm_element_value(match, PCMK_XA_NAME); if (pcmk__str_eq(action, PCMK_ACTION_LIST, pcmk__str_none)) { stonith__set_device_flags(device->flags, device->id, @@ -956,16 +957,23 @@ read_action_metadata(stonith_device_t *device) stonith__set_device_flags(device->flags, device->id, st_device_supports_reboot); } else if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none)) { - /* "automatic" means the cluster will unfence node when it joins */ - /* "required" is a deprecated synonym for "automatic" */ - if (pcmk__xe_attr_is_true(match, "automatic") || pcmk__xe_attr_is_true(match, "required")) { + /* PCMK_XA_AUTOMATIC means the cluster will unfence a node when it + * joins. + * + * @COMPAT PCMK__XA_REQUIRED is a deprecated synonym for + * PCMK_XA_AUTOMATIC. + */ + if (pcmk__xe_attr_is_true(match, PCMK_XA_AUTOMATIC) + || pcmk__xe_attr_is_true(match, PCMK__XA_REQUIRED)) { device->automatic_unfencing = TRUE; } stonith__set_device_flags(device->flags, device->id, st_device_supports_on); } - if ((action != NULL) && pcmk__xe_attr_is_true(match, "on_target")) { + if ((action != NULL) + && pcmk__xe_attr_is_true(match, PCMK_XA_ON_TARGET)) { + pcmk__add_word(&(device->on_target_actions), 64, action); } } @@ -993,7 +1001,7 @@ map_action(GHashTable *params, const char *action, const char *value) } else { crm_warn("Mapping %s='%s' to %s='%s'", STONITH_ATTR_ACTION_OP, value, key, value); - g_hash_table_insert(params, key, strdup(value)); + g_hash_table_insert(params, key, pcmk__str_copy(value)); } } @@ -1023,7 +1031,8 @@ xml2device_params(const char *name, const xmlNode *dev) crm_warn("Ignoring empty '%s' parameter", STONITH_ATTR_ACTION_OP); } else if (strcmp(value, PCMK_ACTION_REBOOT) == 0) { - crm_warn("Ignoring %s='reboot' (see stonith-action cluster property instead)", + crm_warn("Ignoring %s='reboot' (see " PCMK_OPT_STONITH_ACTION + " cluster property instead)", STONITH_ATTR_ACTION_OP); } else if (strcmp(value, PCMK_ACTION_OFF) == 0) { @@ -1050,15 +1059,15 @@ target_list_type(stonith_device_t * dev) if (check_type == NULL) { if (g_hash_table_lookup(dev->params, PCMK_STONITH_HOST_LIST)) { - check_type = "static-list"; + check_type = PCMK_VALUE_STATIC_LIST; } else if (g_hash_table_lookup(dev->params, PCMK_STONITH_HOST_MAP)) { - check_type = "static-list"; + check_type = PCMK_VALUE_STATIC_LIST; } else if (pcmk_is_set(dev->flags, st_device_supports_list)) { - check_type = "dynamic-list"; + check_type = PCMK_VALUE_DYNAMIC_LIST; } else if (pcmk_is_set(dev->flags, st_device_supports_status)) { - check_type = "status"; + check_type = PCMK_VALUE_STATUS; } else { - check_type = PCMK__VALUE_NONE; + check_type = PCMK_VALUE_NONE; } } @@ -1070,17 +1079,15 @@ build_device_from_xml(xmlNode *dev) { const char *value; stonith_device_t *device = NULL; - char *agent = crm_element_value_copy(dev, "agent"); + char *agent = crm_element_value_copy(dev, PCMK_XA_AGENT); CRM_CHECK(agent != NULL, return device); - device = calloc(1, sizeof(stonith_device_t)); - - CRM_CHECK(device != NULL, {free(agent); return device;}); + device = pcmk__assert_alloc(1, sizeof(stonith_device_t)); - device->id = crm_element_value_copy(dev, XML_ATTR_ID); + device->id = crm_element_value_copy(dev, PCMK_XA_ID); device->agent = agent; - device->namespace = crm_element_value_copy(dev, "namespace"); + device->namespace = crm_element_value_copy(dev, PCMK__XA_NAMESPACE); device->params = xml2device_params(device->id, dev); value = g_hash_table_lookup(device->params, PCMK_STONITH_HOST_LIST); @@ -1092,8 +1099,10 @@ build_device_from_xml(xmlNode *dev) device->aliases = build_port_aliases(value, &(device->targets)); value = target_list_type(device); - if (!pcmk__str_eq(value, "static-list", pcmk__str_casei) && device->targets) { - /* Other than "static-list", dev-> targets is unnecessary. */ + if (!pcmk__str_eq(value, PCMK_VALUE_STATIC_LIST, pcmk__str_casei) + && (device->targets != NULL)) { + + // device->targets is necessary only with PCMK_VALUE_STATIC_LIST g_list_free_full(device->targets, free); device->targets = NULL; } @@ -1125,8 +1134,8 @@ build_device_from_xml(xmlNode *dev) device->include_nodeid = is_nodeid_required(device->agent_metadata); } - value = crm_element_value(dev, "rsc_provides"); - if (pcmk__str_eq(value, PCMK__VALUE_UNFENCING, pcmk__str_casei)) { + value = crm_element_value(dev, PCMK__XA_RSC_PROVIDES); + if (pcmk__str_eq(value, PCMK_VALUE_UNFENCING, pcmk__str_casei)) { device->automatic_unfencing = TRUE; } @@ -1159,17 +1168,17 @@ schedule_internal_command(const char *origin, { async_command_t *cmd = NULL; - cmd = calloc(1, sizeof(async_command_t)); + cmd = pcmk__assert_alloc(1, sizeof(async_command_t)); cmd->id = -1; cmd->default_timeout = timeout ? timeout : 60; cmd->timeout = cmd->default_timeout; - cmd->action = strdup(action); - pcmk__str_update(&cmd->target, target); - cmd->device = strdup(device->id); - cmd->origin = strdup(origin); - cmd->client = strdup(crm_system_name); - cmd->client_name = strdup(crm_system_name); + cmd->action = pcmk__str_copy(action); + cmd->target = pcmk__str_copy(target); + cmd->device = pcmk__str_copy(device->id); + cmd->origin = pcmk__str_copy(origin); + cmd->client = pcmk__str_copy(crm_system_name); + cmd->client_name = pcmk__str_copy(crm_system_name); cmd->internal_user_data = internal_user_data; cmd->done_cb = done_cb; /* cmd, not internal_user_data, is passed to 'done_cb' as the userdata */ @@ -1292,13 +1301,13 @@ dynamic_list_search_cb(int pid, const pcmk__action_result_t *result, ((result->exit_reason == NULL)? "" : ")")); } - /* Fall back to pcmk_host_check="status" if the user didn't explicitly - * specify "dynamic-list". + /* Fall back to pcmk_host_check=PCMK_VALUE_STATUS if the user didn't + * explicitly specify PCMK_VALUE_DYNAMIC_LIST */ if (g_hash_table_lookup(dev->params, PCMK_STONITH_HOST_CHECK) == NULL) { crm_notice("Switching to pcmk_host_check='status' for %s", dev->id); - g_hash_table_replace(dev->params, strdup(PCMK_STONITH_HOST_CHECK), - strdup("status")); + pcmk__insert_dup(dev->params, PCMK_STONITH_HOST_CHECK, + PCMK_VALUE_STATUS); } } @@ -1330,7 +1339,7 @@ device_params_diff(GHashTable *first, GHashTable *second) { if(strstr(key, "CRM_meta") == key) { continue; - } else if(strcmp(key, "crm_feature_set") == 0) { + } else if (strcmp(key, PCMK_XA_CRM_FEATURE_SET) == 0) { continue; } else { char *other_value = g_hash_table_lookup(second, key); @@ -1389,7 +1398,7 @@ stonith_device_register(xmlNode *dev, gboolean from_cib) STONITH_WATCHDOG_AGENT_INTERNAL, NULL)) do { if (stonith_watchdog_timeout_ms <= 0) { crm_err("Ignoring watchdog fence device without " - "stonith-watchdog-timeout set."); + PCMK_OPT_STONITH_WATCHDOG_TIMEOUT " set."); rv = -ENODEV; /* fall through to cleanup & return */ } else if (!pcmk__str_any_of(device->agent, STONITH_WATCHDOG_AGENT, @@ -1419,9 +1428,8 @@ stonith_device_register(xmlNode *dev, gboolean from_cib) if (node_does_watchdog_fencing(stonith_our_uname)) { g_list_free_full(device->targets, free); device->targets = stonith__parse_targets(stonith_our_uname); - g_hash_table_replace(device->params, - strdup(PCMK_STONITH_HOST_LIST), - strdup(stonith_our_uname)); + pcmk__insert_dup(device->params, + PCMK_STONITH_HOST_LIST, stonith_our_uname); /* proceed as with any other stonith-device */ break; } @@ -1578,18 +1586,18 @@ stonith_level_key(const xmlNode *level, enum fenced_target_by mode) } switch (mode) { case fenced_target_by_name: - return crm_element_value_copy(level, XML_ATTR_STONITH_TARGET); + return crm_element_value_copy(level, PCMK_XA_TARGET); case fenced_target_by_pattern: - return crm_element_value_copy(level, XML_ATTR_STONITH_TARGET_PATTERN); + return crm_element_value_copy(level, PCMK_XA_TARGET_PATTERN); case fenced_target_by_attribute: return crm_strdup_printf("%s=%s", - crm_element_value(level, XML_ATTR_STONITH_TARGET_ATTRIBUTE), - crm_element_value(level, XML_ATTR_STONITH_TARGET_VALUE)); + crm_element_value(level, PCMK_XA_TARGET_ATTRIBUTE), + crm_element_value(level, PCMK_XA_TARGET_VALUE)); default: - return crm_strdup_printf("unknown-%s", ID(level)); + return crm_strdup_printf("unknown-%s", pcmk__xe_id(level)); } } @@ -1604,15 +1612,15 @@ stonith_level_key(const xmlNode *level, enum fenced_target_by mode) static enum fenced_target_by unpack_level_kind(const xmlNode *level) { - if (crm_element_value(level, XML_ATTR_STONITH_TARGET) != NULL) { + if (crm_element_value(level, PCMK_XA_TARGET) != NULL) { return fenced_target_by_name; } - if (crm_element_value(level, XML_ATTR_STONITH_TARGET_PATTERN) != NULL) { + if (crm_element_value(level, PCMK_XA_TARGET_PATTERN) != NULL) { return fenced_target_by_pattern; } if (!stand_alone /* if standalone, there's no attribute manager */ - && (crm_element_value(level, XML_ATTR_STONITH_TARGET_ATTRIBUTE) != NULL) - && (crm_element_value(level, XML_ATTR_STONITH_TARGET_VALUE) != NULL)) { + && (crm_element_value(level, PCMK_XA_TARGET_ATTRIBUTE) != NULL) + && (crm_element_value(level, PCMK_XA_TARGET_VALUE) != NULL)) { return fenced_target_by_attribute; } return fenced_target_by_unknown; @@ -1670,8 +1678,8 @@ unpack_level_request(xmlNode *xml, enum fenced_target_by *mode, char **target, * search by xpath, because it might give multiple hits if the XML is the * CIB. */ - if ((xml != NULL) && !pcmk__xe_is(xml, XML_TAG_FENCING_LEVEL)) { - xml = get_xpath_object("//" XML_TAG_FENCING_LEVEL, xml, LOG_WARNING); + if ((xml != NULL) && !pcmk__xe_is(xml, PCMK_XE_FENCING_LEVEL)) { + xml = get_xpath_object("//" PCMK_XE_FENCING_LEVEL, xml, LOG_WARNING); } if (xml == NULL) { @@ -1681,7 +1689,7 @@ unpack_level_request(xmlNode *xml, enum fenced_target_by *mode, char **target, } else { local_mode = unpack_level_kind(xml); local_target = stonith_level_key(xml, local_mode); - crm_element_value_int(xml, XML_ATTR_STONITH_INDEX, &local_id); + crm_element_value_int(xml, PCMK_XA_INDEX, &local_id); if (desc != NULL) { *desc = crm_strdup_printf("%s[%d]", local_target, local_id); } @@ -1737,7 +1745,7 @@ fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) } // Ensure an ID was given (even the client API adds an ID) - if (pcmk__str_empty(ID(level))) { + if (pcmk__str_empty(pcmk__xe_id(level))) { crm_warn("Ignoring registration for topology level without ID"); free(target); crm_log_xml_trace(level, "Bad level"); @@ -1749,12 +1757,12 @@ fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) // Ensure a valid target was specified if (mode == fenced_target_by_unknown) { crm_warn("Ignoring registration for topology level '%s' " - "without valid target", ID(level)); + "without valid target", pcmk__xe_id(level)); free(target); crm_log_xml_trace(level, "Bad level"); pcmk__format_result(result, CRM_EX_INVALID_PARAM, PCMK_EXEC_INVALID, "Invalid target for topology level '%s'", - ID(level)); + pcmk__xe_id(level)); return; } @@ -1766,28 +1774,24 @@ fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) crm_log_xml_trace(level, "Bad level"); pcmk__format_result(result, CRM_EX_INVALID_PARAM, PCMK_EXEC_INVALID, "Invalid level number '%s' for topology level '%s'", - pcmk__s(crm_element_value(level, - XML_ATTR_STONITH_INDEX), + pcmk__s(crm_element_value(level, PCMK_XA_INDEX), ""), - ID(level)); + pcmk__xe_id(level)); return; } /* Find or create topology table entry */ tp = g_hash_table_lookup(topology, target); if (tp == NULL) { - tp = calloc(1, sizeof(stonith_topology_t)); - if (tp == NULL) { - pcmk__set_result(result, CRM_EX_ERROR, PCMK_EXEC_ERROR, - strerror(ENOMEM)); - free(target); - return; - } + tp = pcmk__assert_alloc(1, sizeof(stonith_topology_t)); + tp->kind = mode; tp->target = target; - tp->target_value = crm_element_value_copy(level, XML_ATTR_STONITH_TARGET_VALUE); - tp->target_pattern = crm_element_value_copy(level, XML_ATTR_STONITH_TARGET_PATTERN); - tp->target_attribute = crm_element_value_copy(level, XML_ATTR_STONITH_TARGET_ATTRIBUTE); + tp->target_value = crm_element_value_copy(level, PCMK_XA_TARGET_VALUE); + tp->target_pattern = crm_element_value_copy(level, + PCMK_XA_TARGET_PATTERN); + tp->target_attribute = crm_element_value_copy(level, + PCMK_XA_TARGET_ATTRIBUTE); g_hash_table_replace(topology, tp->target, tp); crm_trace("Added %s (%d) to the topology (%d active entries)", @@ -1801,12 +1805,12 @@ fenced_register_level(xmlNode *msg, char **desc, pcmk__action_result_t *result) tp->target, id); } - devices = parse_device_list(crm_element_value(level, XML_ATTR_STONITH_DEVICES)); + devices = parse_device_list(crm_element_value(level, PCMK_XA_DEVICES)); for (dIter = devices; dIter; dIter = dIter->next) { const char *device = dIter->value; crm_trace("Adding device '%s' for %s[%d]", device, tp->target, id); - tp->levels[id] = g_list_append(tp->levels[id], strdup(device)); + tp->levels[id] = g_list_append(tp->levels[id], pcmk__str_copy(device)); } stonith_key_value_freeall(devices, 1, 1); @@ -1857,12 +1861,11 @@ fenced_unregister_level(xmlNode *msg, char **desc, crm_log_xml_trace(level, "Bad level"); pcmk__format_result(result, CRM_EX_INVALID_PARAM, PCMK_EXEC_INVALID, "Invalid level number '%s' for topology level %s", - pcmk__s(crm_element_value(level, - XML_ATTR_STONITH_INDEX), + pcmk__s(crm_element_value(level, PCMK_XA_INDEX), "<null>"), // Client API doesn't add ID to unregistration XML - pcmk__s(ID(level), "")); + pcmk__s(pcmk__xe_id(level), "")); return; } @@ -1906,26 +1909,29 @@ list_to_string(GList *list, const char *delim, gboolean terminate_with_delim) char *rv; GList *gIter; + char *pos = NULL; + const char *lead_delim = ""; + for (gIter = list; gIter != NULL; gIter = gIter->next) { const char *value = (const char *) gIter->data; alloc_size += strlen(value); } - rv = calloc(alloc_size, sizeof(char)); - if (rv) { - char *pos = rv; - const char *lead_delim = ""; - for (gIter = list; gIter != NULL; gIter = gIter->next) { - const char *value = (const char *) gIter->data; + rv = pcmk__assert_alloc(alloc_size, sizeof(char)); + pos = rv; - pos = &pos[sprintf(pos, "%s%s", lead_delim, value)]; - lead_delim = delim; - } - if (max && terminate_with_delim) { - sprintf(pos, "%s", delim); - } + for (gIter = list; gIter != NULL; gIter = gIter->next) { + const char *value = (const char *) gIter->data; + + pos = &pos[sprintf(pos, "%s%s", lead_delim, value)]; + lead_delim = delim; + } + + if (max && terminate_with_delim) { + sprintf(pos, "%s", delim); } + return rv; } @@ -1947,10 +1953,11 @@ list_to_string(GList *list, const char *delim, gboolean terminate_with_delim) static void execute_agent_action(xmlNode *msg, pcmk__action_result_t *result) { - xmlNode *dev = get_xpath_object("//" F_STONITH_DEVICE, msg, LOG_ERR); - xmlNode *op = get_xpath_object("//@" F_STONITH_ACTION, msg, LOG_ERR); - const char *id = crm_element_value(dev, F_STONITH_DEVICE); - const char *action = crm_element_value(op, F_STONITH_ACTION); + xmlNode *dev = get_xpath_object("//" PCMK__XE_ST_DEVICE_ID, msg, LOG_ERR); + xmlNode *op = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, msg, + LOG_ERR); + const char *id = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID); + const char *action = crm_element_value(op, PCMK__XA_ST_DEVICE_ACTION); async_command_t *cmd = NULL; stonith_device_t *device = NULL; @@ -2023,7 +2030,8 @@ search_devices_record_result(struct device_search_s *search, const char *device, return; } } - search->capable = g_list_append(search->capable, strdup(device)); + search->capable = g_list_append(search->capable, + pcmk__str_copy(device)); } if (search->replies_needed == search->replies_received) { @@ -2158,10 +2166,12 @@ can_fence_host_with_device(stonith_device_t *dev, // Check eligibility as specified by pcmk_host_check check_type = target_list_type(dev); alias = g_hash_table_lookup(dev->aliases, target); - if (pcmk__str_eq(check_type, PCMK__VALUE_NONE, pcmk__str_casei)) { + if (pcmk__str_eq(check_type, PCMK_VALUE_NONE, pcmk__str_casei)) { can = TRUE; - } else if (pcmk__str_eq(check_type, "static-list", pcmk__str_casei)) { + } else if (pcmk__str_eq(check_type, PCMK_VALUE_STATIC_LIST, + pcmk__str_casei)) { + if (pcmk__str_in_list(target, dev->targets, pcmk__str_casei)) { can = TRUE; } else if (g_hash_table_lookup(dev->params, PCMK_STONITH_HOST_MAP) @@ -2169,7 +2179,8 @@ can_fence_host_with_device(stonith_device_t *dev, can = TRUE; } - } else if (pcmk__str_eq(check_type, "dynamic-list", pcmk__str_casei)) { + } else if (pcmk__str_eq(check_type, PCMK_VALUE_DYNAMIC_LIST, + pcmk__str_casei)) { time_t now = time(NULL); if (dev->targets == NULL || dev->targets_age + 60 < now) { @@ -2177,8 +2188,10 @@ can_fence_host_with_device(stonith_device_t *dev, search->per_device_timeout); if (device_timeout > search->per_device_timeout) { - crm_notice("Since the pcmk_list_timeout(%ds) parameter of %s is larger than stonith-timeout(%ds), timeout may occur", - device_timeout, dev_id, search->per_device_timeout); + crm_notice("Since the pcmk_list_timeout (%ds) parameter of %s " + "is larger than " PCMK_OPT_STONITH_TIMEOUT + " (%ds), timeout may occur", + device_timeout, dev_id, search->per_device_timeout); } crm_trace("Running '%s' to check whether %s is eligible to fence %s (%s)", @@ -2196,12 +2209,14 @@ can_fence_host_with_device(stonith_device_t *dev, can = TRUE; } - } else if (pcmk__str_eq(check_type, "status", pcmk__str_casei)) { + } else if (pcmk__str_eq(check_type, PCMK_VALUE_STATUS, pcmk__str_casei)) { int device_timeout = get_action_timeout(dev, check_type, search->per_device_timeout); if (device_timeout > search->per_device_timeout) { - crm_notice("Since the pcmk_status_timeout(%ds) parameter of %s is larger than stonith-timeout(%ds), timeout may occur", - device_timeout, dev_id, search->per_device_timeout); + crm_notice("Since the pcmk_status_timeout (%ds) parameter of %s is " + "larger than " PCMK_OPT_STONITH_TIMEOUT " (%ds), " + "timeout may occur", + device_timeout, dev_id, search->per_device_timeout); } crm_trace("Running '%s' to check whether %s is eligible to fence %s (%s)", @@ -2246,16 +2261,10 @@ get_capable_devices(const char *host, const char *action, int timeout, bool suic return; } - search = calloc(1, sizeof(struct device_search_s)); - if (!search) { - crm_crit("Cannot search for capable fence devices: %s", - strerror(ENOMEM)); - callback(NULL, user_data); - return; - } + search = pcmk__assert_alloc(1, sizeof(struct device_search_s)); - pcmk__str_update(&search->host, host); - pcmk__str_update(&search->action, action); + search->host = pcmk__str_copy(host); + search->action = pcmk__str_copy(action); search->per_device_timeout = timeout; search->allow_suicide = suicide; search->callback = callback; @@ -2303,28 +2312,31 @@ add_action_specific_attributes(xmlNode *xml, const char *action, CRM_CHECK(xml && action && device, return); + // PCMK__XA_ST_REQUIRED is currently used only for unfencing if (is_action_required(action, device)) { crm_trace("Action '%s' is required using %s", action, device->id); - crm_xml_add_int(xml, F_STONITH_DEVICE_REQUIRED, 1); + crm_xml_add_int(xml, PCMK__XA_ST_REQUIRED, 1); } + // pcmk_<action>_timeout if configured action_specific_timeout = get_action_timeout(device, action, 0); if (action_specific_timeout) { - crm_trace("Action '%s' has timeout %dms using %s", + crm_trace("Action '%s' has timeout %ds using %s", action, action_specific_timeout, device->id); - crm_xml_add_int(xml, F_STONITH_ACTION_TIMEOUT, action_specific_timeout); + crm_xml_add_int(xml, PCMK__XA_ST_ACTION_TIMEOUT, + action_specific_timeout); } delay_max = get_action_delay_max(device, action); if (delay_max > 0) { crm_trace("Action '%s' has maximum random delay %ds using %s", action, delay_max, device->id); - crm_xml_add_int(xml, F_STONITH_DELAY_MAX, delay_max); + crm_xml_add_int(xml, PCMK__XA_ST_DELAY_MAX, delay_max); } delay_base = get_action_delay_base(device, action, target); if (delay_base > 0) { - crm_xml_add_int(xml, F_STONITH_DELAY_BASE, delay_base); + crm_xml_add_int(xml, PCMK__XA_ST_DELAY_BASE, delay_base); } if ((delay_max > 0) && (delay_base == 0)) { @@ -2357,7 +2369,7 @@ add_disallowed(xmlNode *xml, const char *action, const stonith_device_t *device, if (!localhost_is_eligible(device, action, target, allow_suicide)) { crm_trace("Action '%s' using %s is disallowed for local host", action, device->id); - pcmk__xe_set_bool_attr(xml, F_STONITH_ACTION_DISALLOWED, true); + pcmk__xe_set_bool_attr(xml, PCMK__XA_ST_ACTION_DISALLOWED, true); } } @@ -2376,9 +2388,9 @@ add_action_reply(xmlNode *xml, const char *action, const stonith_device_t *device, const char *target, gboolean allow_suicide) { - xmlNode *child = create_xml_node(xml, F_STONITH_ACTION); + xmlNode *child = pcmk__xe_create(xml, PCMK__XE_ST_DEVICE_ACTION); - crm_xml_add(child, XML_ATTR_ID, action); + crm_xml_add(child, PCMK_XA_ID, action); add_action_specific_attributes(child, action, device, target); add_disallowed(child, action, device, target, allow_suicide); } @@ -2402,8 +2414,11 @@ stonith_send_reply(const xmlNode *reply, int call_options, if (remote_peer == NULL) { do_local_reply(reply, client, call_options); } else { - send_cluster_message(crm_get_peer(0, remote_peer), crm_msg_stonith_ng, - reply, FALSE); + const crm_node_t *node = + pcmk__get_node(0, remote_peer, NULL, + pcmk__node_search_cluster_member); + + pcmk__cluster_send_message(node, crm_msg_stonith_ng, reply); } } @@ -2412,7 +2427,7 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) { struct st_query_data *query = user_data; int available_devices = 0; - xmlNode *dev = NULL; + xmlNode *wrapper = NULL; xmlNode *list = NULL; GList *lpc = NULL; pcmk__client_t *client = NULL; @@ -2426,12 +2441,15 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) } } - /* Pack the results into XML */ - list = create_xml_node(NULL, __func__); - crm_xml_add(list, F_STONITH_TARGET, query->target); + // Pack the results into XML + wrapper = pcmk__xe_create(query->reply, PCMK__XE_ST_CALLDATA); + list = pcmk__xe_create(wrapper, __func__); + crm_xml_add(list, PCMK__XA_ST_TARGET, query->target); + for (lpc = devices; lpc != NULL; lpc = lpc->next) { stonith_device_t *device = g_hash_table_lookup(device_list, lpc->data); const char *action = query->action; + xmlNode *dev = NULL; if (!device) { /* It is possible the device got unregistered while @@ -2441,12 +2459,15 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) available_devices++; - dev = create_xml_node(list, F_STONITH_DEVICE); - crm_xml_add(dev, XML_ATTR_ID, device->id); - crm_xml_add(dev, "namespace", device->namespace); - crm_xml_add(dev, "agent", device->agent); - crm_xml_add_int(dev, F_STONITH_DEVICE_VERIFIED, device->verified); - crm_xml_add_int(dev, F_STONITH_DEVICE_SUPPORT_FLAGS, device->flags); + dev = pcmk__xe_create(list, PCMK__XE_ST_DEVICE_ID); + crm_xml_add(dev, PCMK_XA_ID, device->id); + crm_xml_add(dev, PCMK__XA_NAMESPACE, device->namespace); + crm_xml_add(dev, PCMK_XA_AGENT, device->agent); + + // Has had successful monitor, list, or status on this node + crm_xml_add_int(dev, PCMK__XA_ST_MONITOR_VERIFIED, device->verified); + + crm_xml_add_int(dev, PCMK__XA_ST_DEVICE_SUPPORT_FLAGS, device->flags); /* If the originating fencer wants to reboot the node, and we have a * capable device that doesn't support "reboot", remap to "off" instead. @@ -2482,13 +2503,13 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) /* A query without a target wants device parameters */ if (query->target == NULL) { - xmlNode *attrs = create_xml_node(dev, XML_TAG_ATTRS); + xmlNode *attrs = pcmk__xe_create(dev, PCMK__XE_ATTRIBUTES); g_hash_table_foreach(device->params, hash2field, attrs); } } - crm_xml_add_int(list, F_STONITH_AVAILABLE_DEVICES, available_devices); + crm_xml_add_int(list, PCMK__XA_ST_AVAILABLE_DEVICES, available_devices); if (query->target) { crm_debug("Found %d matching device%s for target '%s'", available_devices, pcmk__plural_s(available_devices), @@ -2498,10 +2519,7 @@ stonith_query_capable_device_cb(GList * devices, void *user_data) available_devices, pcmk__plural_s(available_devices)); } - if (list != NULL) { - crm_log_xml_trace(list, "Add query results"); - add_message_xml(query->reply, F_STONITH_CALLDATA, list); - } + crm_log_xml_trace(list, "query-result"); stonith_send_reply(query->reply, query->call_options, query->remote_peer, client); @@ -2513,7 +2531,6 @@ done: free(query->target); free(query->action); free(query); - free_xml(list); g_list_free_full(devices, free); } @@ -2542,14 +2559,16 @@ log_async_result(const async_command_t *cmd, if (pcmk__result_ok(result)) { log_level = (cmd->target == NULL)? LOG_DEBUG : LOG_NOTICE; if ((result->action_stdout != NULL) - && !pcmk__str_eq(cmd->action, "metadata", pcmk__str_none)) { + && !pcmk__str_eq(cmd->action, PCMK_ACTION_METADATA, + pcmk__str_none)) { output_log_level = LOG_DEBUG; } next = NULL; } else { log_level = (cmd->target == NULL)? LOG_NOTICE : LOG_ERR; if ((result->action_stdout != NULL) - && !pcmk__str_eq(cmd->action, "metadata", pcmk__str_none)) { + && !pcmk__str_eq(cmd->action, PCMK_ACTION_METADATA, + pcmk__str_none)) { output_log_level = LOG_WARNING; } } @@ -2633,7 +2652,7 @@ send_async_reply(const async_command_t *cmd, const pcmk__action_result_t *result reply = construct_async_reply(cmd, result); if (merged) { - pcmk__xe_set_bool_attr(reply, F_STONITH_MERGED, true); + pcmk__xe_set_bool_attr(reply, PCMK__XA_ST_OP_MERGED, true); } if (!stand_alone && pcmk__is_fencing_action(cmd->action) @@ -2643,9 +2662,9 @@ send_async_reply(const async_command_t *cmd, const pcmk__action_result_t *result */ crm_trace("Broadcast '%s' result for %s (target was also originator)", cmd->action, cmd->target); - crm_xml_add(reply, F_SUBTYPE, "broadcast"); - crm_xml_add(reply, F_STONITH_OPERATION, T_STONITH_NOTIFY); - send_cluster_message(NULL, crm_msg_stonith_ng, reply, FALSE); + crm_xml_add(reply, PCMK__XA_SUBT, PCMK__VALUE_BROADCAST); + crm_xml_add(reply, PCMK__XA_ST_OP, STONITH_OP_NOTIFY); + pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, reply); } else { // Reply only to the originator stonith_send_reply(reply, cmd->options, cmd->origin, client); @@ -2656,18 +2675,19 @@ send_async_reply(const async_command_t *cmd, const pcmk__action_result_t *result if (stand_alone) { /* Do notification with a clean data object */ - xmlNode *notify_data = create_xml_node(NULL, T_STONITH_NOTIFY_FENCE); + xmlNode *notify_data = pcmk__xe_create(NULL, PCMK__XE_ST_NOTIFY_FENCE); stonith__xe_set_result(notify_data, result); - crm_xml_add(notify_data, F_STONITH_TARGET, cmd->target); - crm_xml_add(notify_data, F_STONITH_OPERATION, cmd->op); - crm_xml_add(notify_data, F_STONITH_DELEGATE, "localhost"); - crm_xml_add(notify_data, F_STONITH_DEVICE, cmd->device); - crm_xml_add(notify_data, F_STONITH_REMOTE_OP_ID, cmd->remote_op_id); - crm_xml_add(notify_data, F_STONITH_ORIGIN, cmd->client); + crm_xml_add(notify_data, PCMK__XA_ST_TARGET, cmd->target); + crm_xml_add(notify_data, PCMK__XA_ST_OP, cmd->op); + crm_xml_add(notify_data, PCMK__XA_ST_DELEGATE, "localhost"); + crm_xml_add(notify_data, PCMK__XA_ST_DEVICE_ID, cmd->device); + crm_xml_add(notify_data, PCMK__XA_ST_REMOTE_OP, cmd->remote_op_id); + crm_xml_add(notify_data, PCMK__XA_ST_ORIGIN, cmd->client); - fenced_send_notification(T_STONITH_NOTIFY_FENCE, result, notify_data); - fenced_send_notification(T_STONITH_NOTIFY_HISTORY, NULL, NULL); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_FENCE, result, + notify_data); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_HISTORY, NULL, NULL); } } @@ -2890,7 +2910,7 @@ fence_locally(xmlNode *msg, pcmk__action_result_t *result) CRM_CHECK((msg != NULL) && (result != NULL), return); - dev = get_xpath_object("//@" F_STONITH_TARGET, msg, LOG_ERR); + dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, msg, LOG_ERR); cmd = create_async_command(msg); if (cmd == NULL) { @@ -2899,7 +2919,7 @@ fence_locally(xmlNode *msg, pcmk__action_result_t *result) return; } - device_id = crm_element_value(dev, F_STONITH_DEVICE); + device_id = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID); if (device_id != NULL) { device = g_hash_table_lookup(device_list, device_id); if (device == NULL) { @@ -2911,14 +2931,16 @@ fence_locally(xmlNode *msg, pcmk__action_result_t *result) schedule_stonith_command(cmd, device); } else { - const char *host = crm_element_value(dev, F_STONITH_TARGET); + const char *host = crm_element_value(dev, PCMK__XA_ST_TARGET); if (pcmk_is_set(cmd->options, st_opt_cs_nodeid)) { int nodeid = 0; crm_node_t *node = NULL; pcmk__scan_min_int(host, &nodeid, 0); - node = pcmk__search_known_node_cache(nodeid, NULL, CRM_GET_PEER_ANY); + node = pcmk__search_node_caches(nodeid, NULL, + pcmk__node_search_any + |pcmk__node_search_cluster_cib); if (node != NULL) { host = node->uname; } @@ -2953,10 +2975,10 @@ fenced_construct_reply(const xmlNode *request, xmlNode *data, { xmlNode *reply = NULL; - reply = create_xml_node(NULL, T_STONITH_REPLY); + reply = pcmk__xe_create(NULL, PCMK__XE_ST_REPLY); - crm_xml_add(reply, "st_origin", __func__); - crm_xml_add(reply, F_TYPE, T_STONITH_NG); + crm_xml_add(reply, PCMK__XA_ST_ORIGIN, __func__); + crm_xml_add(reply, PCMK__XA_T, PCMK__VALUE_STONITH_NG); stonith__xe_set_result(reply, result); if (request == NULL) { @@ -2976,12 +2998,12 @@ fenced_construct_reply(const xmlNode *request, xmlNode *data, // Attributes to copy from request to reply const char *names[] = { - F_STONITH_OPERATION, - F_STONITH_CALLID, - F_STONITH_CLIENTID, - F_STONITH_CLIENTNAME, - F_STONITH_REMOTE_OP_ID, - F_STONITH_CALLOPTS + PCMK__XA_ST_OP, + PCMK__XA_ST_CALLID, + PCMK__XA_ST_CLIENTID, + PCMK__XA_ST_CLIENTNAME, + PCMK__XA_ST_REMOTE_OP, + PCMK__XA_ST_CALLOPT, }; for (int lpc = 0; lpc < PCMK__NELEM(names); lpc++) { @@ -2990,7 +3012,9 @@ fenced_construct_reply(const xmlNode *request, xmlNode *data, crm_xml_add(reply, name, value); } if (data != NULL) { - add_message_xml(reply, F_STONITH_CALLDATA, data); + xmlNode *wrapper = pcmk__xe_create(reply, PCMK__XE_ST_CALLDATA); + + pcmk__xml_copy(wrapper, data); } } return reply; @@ -3007,20 +3031,20 @@ static xmlNode * construct_async_reply(const async_command_t *cmd, const pcmk__action_result_t *result) { - xmlNode *reply = create_xml_node(NULL, T_STONITH_REPLY); - - crm_xml_add(reply, "st_origin", __func__); - crm_xml_add(reply, F_TYPE, T_STONITH_NG); - crm_xml_add(reply, F_STONITH_OPERATION, cmd->op); - crm_xml_add(reply, F_STONITH_DEVICE, cmd->device); - crm_xml_add(reply, F_STONITH_REMOTE_OP_ID, cmd->remote_op_id); - crm_xml_add(reply, F_STONITH_CLIENTID, cmd->client); - crm_xml_add(reply, F_STONITH_CLIENTNAME, cmd->client_name); - crm_xml_add(reply, F_STONITH_TARGET, cmd->target); - crm_xml_add(reply, F_STONITH_ACTION, cmd->op); - crm_xml_add(reply, F_STONITH_ORIGIN, cmd->origin); - crm_xml_add_int(reply, F_STONITH_CALLID, cmd->id); - crm_xml_add_int(reply, F_STONITH_CALLOPTS, cmd->options); + xmlNode *reply = pcmk__xe_create(NULL, PCMK__XE_ST_REPLY); + + crm_xml_add(reply, PCMK__XA_ST_ORIGIN, __func__); + crm_xml_add(reply, PCMK__XA_T, PCMK__VALUE_STONITH_NG); + crm_xml_add(reply, PCMK__XA_ST_OP, cmd->op); + crm_xml_add(reply, PCMK__XA_ST_DEVICE_ID, cmd->device); + crm_xml_add(reply, PCMK__XA_ST_REMOTE_OP, cmd->remote_op_id); + crm_xml_add(reply, PCMK__XA_ST_CLIENTID, cmd->client); + crm_xml_add(reply, PCMK__XA_ST_CLIENTNAME, cmd->client_name); + crm_xml_add(reply, PCMK__XA_ST_TARGET, cmd->target); + crm_xml_add(reply, PCMK__XA_ST_DEVICE_ACTION, cmd->op); + crm_xml_add(reply, PCMK__XA_ST_ORIGIN, cmd->origin); + crm_xml_add_int(reply, PCMK__XA_ST_CALLID, cmd->id); + crm_xml_add_int(reply, PCMK__XA_ST_CALLOPT, cmd->options); stonith__xe_set_result(reply, result); return reply; @@ -3081,7 +3105,8 @@ check_alternate_host(const char *target) static void remove_relay_op(xmlNode * request) { - xmlNode *dev = get_xpath_object("//@" F_STONITH_ACTION, request, LOG_TRACE); + xmlNode *dev = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, request, + LOG_TRACE); const char *relay_op_id = NULL; const char *op_id = NULL; const char *client_name = NULL; @@ -3089,12 +3114,12 @@ remove_relay_op(xmlNode * request) remote_fencing_op_t *relay_op = NULL; if (dev) { - target = crm_element_value(dev, F_STONITH_TARGET); + target = crm_element_value(dev, PCMK__XA_ST_TARGET); } - relay_op_id = crm_element_value(request, F_STONITH_REMOTE_OP_ID_RELAY); - op_id = crm_element_value(request, F_STONITH_REMOTE_OP_ID); - client_name = crm_element_value(request, F_STONITH_CLIENTNAME); + relay_op_id = crm_element_value(request, PCMK__XA_ST_REMOTE_OP_RELAY); + op_id = crm_element_value(request, PCMK__XA_ST_REMOTE_OP); + client_name = crm_element_value(request, PCMK__XA_ST_CLIENTNAME); /* Delete RELAY operation. */ if (relay_op_id && target && pcmk__str_eq(target, stonith_our_uname, pcmk__str_casei)) { @@ -3162,11 +3187,11 @@ is_privileged(const pcmk__client_t *c, const char *op) static xmlNode * handle_register_request(pcmk__request_t *request) { - xmlNode *reply = create_xml_node(NULL, "reply"); + xmlNode *reply = pcmk__xe_create(NULL, "reply"); CRM_ASSERT(request->ipc_client != NULL); - crm_xml_add(reply, F_STONITH_OPERATION, CRM_OP_REGISTER); - crm_xml_add(reply, F_STONITH_CLIENTID, request->ipc_client->id); + crm_xml_add(reply, PCMK__XA_ST_OP, CRM_OP_REGISTER); + crm_xml_add(reply, PCMK__XA_ST_CLIENTID, request->ipc_client->id); pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); pcmk__set_request_flags(request, pcmk__request_reuse_options); return reply; @@ -3187,11 +3212,12 @@ handle_agent_request(pcmk__request_t *request) static xmlNode * handle_update_timeout_request(pcmk__request_t *request) { - const char *call_id = crm_element_value(request->xml, F_STONITH_CALLID); - const char *client_id = crm_element_value(request->xml, F_STONITH_CLIENTID); + const char *call_id = crm_element_value(request->xml, PCMK__XA_ST_CALLID); + const char *client_id = crm_element_value(request->xml, + PCMK__XA_ST_CLIENTID); int op_timeout = 0; - crm_element_value_int(request->xml, F_STONITH_TIMEOUT, &op_timeout); + crm_element_value_int(request->xml, PCMK__XA_ST_TIMEOUT, &op_timeout); do_stonith_async_timeout_update(client_id, call_id, op_timeout); pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); return NULL; @@ -3205,7 +3231,8 @@ handle_query_request(pcmk__request_t *request) xmlNode *dev = NULL; const char *action = NULL; const char *target = NULL; - const char *client_id = crm_element_value(request->xml, F_STONITH_CLIENTID); + const char *client_id = crm_element_value(request->xml, + PCMK__XA_ST_CLIENTID); struct st_query_data *query = NULL; if (request->peer != NULL) { @@ -3218,51 +3245,51 @@ handle_query_request(pcmk__request_t *request) pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); - dev = get_xpath_object("//@" F_STONITH_ACTION, request->xml, LOG_NEVER); + dev = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, request->xml, + LOG_NEVER); if (dev != NULL) { - const char *device = crm_element_value(dev, F_STONITH_DEVICE); + const char *device = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID); if (pcmk__str_eq(device, "manual_ack", pcmk__str_casei)) { return NULL; // No query or reply necessary } - target = crm_element_value(dev, F_STONITH_TARGET); - action = crm_element_value(dev, F_STONITH_ACTION); + target = crm_element_value(dev, PCMK__XA_ST_TARGET); + action = crm_element_value(dev, PCMK__XA_ST_DEVICE_ACTION); } crm_log_xml_trace(request->xml, "Query"); - query = calloc(1, sizeof(struct st_query_data)); - CRM_ASSERT(query != NULL); + query = pcmk__assert_alloc(1, sizeof(struct st_query_data)); query->reply = fenced_construct_reply(request->xml, NULL, &request->result); - pcmk__str_update(&query->remote_peer, request->peer); - pcmk__str_update(&query->client_id, client_id); - pcmk__str_update(&query->target, target); - pcmk__str_update(&query->action, action); + query->remote_peer = pcmk__str_copy(request->peer); + query->client_id = pcmk__str_copy(client_id); + query->target = pcmk__str_copy(target); + query->action = pcmk__str_copy(action); query->call_options = request->call_options; - crm_element_value_int(request->xml, F_STONITH_TIMEOUT, &timeout); + crm_element_value_int(request->xml, PCMK__XA_ST_TIMEOUT, &timeout); get_capable_devices(target, action, timeout, pcmk_is_set(query->call_options, st_opt_allow_suicide), query, stonith_query_capable_device_cb, st_device_supports_none); return NULL; } -// T_STONITH_NOTIFY +// STONITH_OP_NOTIFY static xmlNode * handle_notify_request(pcmk__request_t *request) { const char *flag_name = NULL; CRM_ASSERT(request->ipc_client != NULL); - flag_name = crm_element_value(request->xml, F_STONITH_NOTIFY_ACTIVATE); + flag_name = crm_element_value(request->xml, PCMK__XA_ST_NOTIFY_ACTIVATE); if (flag_name != NULL) { crm_debug("Enabling %s callbacks for client %s", flag_name, pcmk__request_origin(request)); pcmk__set_client_flags(request->ipc_client, get_stonith_flag(flag_name)); } - flag_name = crm_element_value(request->xml, F_STONITH_NOTIFY_DEACTIVATE); + flag_name = crm_element_value(request->xml, PCMK__XA_ST_NOTIFY_DEACTIVATE); if (flag_name != NULL) { crm_debug("Disabling %s callbacks for client %s", flag_name, pcmk__request_origin(request)); @@ -3273,22 +3300,23 @@ handle_notify_request(pcmk__request_t *request) pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); pcmk__set_request_flags(request, pcmk__request_reuse_options); - return pcmk__ipc_create_ack(request->ipc_flags, "ack", NULL, CRM_EX_OK); + return pcmk__ipc_create_ack(request->ipc_flags, PCMK__XE_ACK, NULL, + CRM_EX_OK); } // STONITH_OP_RELAY static xmlNode * handle_relay_request(pcmk__request_t *request) { - xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, request->xml, + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, request->xml, LOG_TRACE); crm_notice("Received forwarded fencing request from " "%s %s to fence (%s) peer %s", pcmk__request_origin_type(request), pcmk__request_origin(request), - crm_element_value(dev, F_STONITH_ACTION), - crm_element_value(dev, F_STONITH_TARGET)); + crm_element_value(dev, PCMK__XA_ST_DEVICE_ACTION), + crm_element_value(dev, PCMK__XA_ST_TARGET)); if (initiate_remote_stonith_op(NULL, request->xml, FALSE) == NULL) { fenced_set_protocol_error(&request->result); @@ -3324,11 +3352,11 @@ handle_fence_request(pcmk__request_t *request) } else { const char *alternate_host = NULL; - xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, request->xml, + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, request->xml, LOG_TRACE); - const char *target = crm_element_value(dev, F_STONITH_TARGET); - const char *action = crm_element_value(dev, F_STONITH_ACTION); - const char *device = crm_element_value(dev, F_STONITH_DEVICE); + const char *target = crm_element_value(dev, PCMK__XA_ST_TARGET); + const char *action = crm_element_value(dev, PCMK__XA_ST_DEVICE_ACTION); + const char *device = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID); if (request->ipc_client != NULL) { int tolerance = 0; @@ -3336,7 +3364,7 @@ handle_fence_request(pcmk__request_t *request) crm_notice("Client %s wants to fence (%s) %s using %s", pcmk__request_origin(request), action, target, (device? device : "any device")); - crm_element_value_int(dev, F_STONITH_TOLERANCE, &tolerance); + crm_element_value_int(dev, PCMK__XA_ST_TOLERANCE, &tolerance); if (stonith_check_fence_tolerance(tolerance, target, action)) { pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); @@ -3354,9 +3382,12 @@ handle_fence_request(pcmk__request_t *request) if (alternate_host != NULL) { const char *client_id = NULL; remote_fencing_op_t *op = NULL; + crm_node_t *node = pcmk__get_node(0, alternate_host, NULL, + pcmk__node_search_cluster_member); if (request->ipc_client->id == 0) { - client_id = crm_element_value(request->xml, F_STONITH_CLIENTID); + client_id = crm_element_value(request->xml, + PCMK__XA_ST_CLIENTID); } else { client_id = request->ipc_client->id; } @@ -3367,12 +3398,11 @@ handle_fence_request(pcmk__request_t *request) */ op = create_remote_stonith_op(client_id, request->xml, FALSE); - crm_xml_add(request->xml, F_STONITH_OPERATION, STONITH_OP_RELAY); - crm_xml_add(request->xml, F_STONITH_CLIENTID, + crm_xml_add(request->xml, PCMK__XA_ST_OP, STONITH_OP_RELAY); + crm_xml_add(request->xml, PCMK__XA_ST_CLIENTID, request->ipc_client->id); - crm_xml_add(request->xml, F_STONITH_REMOTE_OP_ID, op->id); - send_cluster_message(crm_get_peer(0, alternate_host), - crm_msg_stonith_ng, request->xml, FALSE); + crm_xml_add(request->xml, PCMK__XA_ST_REMOTE_OP, op->id); + pcmk__cluster_send_message(node, crm_msg_stonith_ng, request->xml); pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_PENDING, NULL); @@ -3416,8 +3446,8 @@ handle_history_request(pcmk__request_t *request) static xmlNode * handle_device_add_request(pcmk__request_t *request) { - const char *op = crm_element_value(request->xml, F_STONITH_OPERATION); - xmlNode *dev = get_xpath_object("//" F_STONITH_DEVICE, request->xml, + const char *op = crm_element_value(request->xml, PCMK__XA_ST_OP); + xmlNode *dev = get_xpath_object("//" PCMK__XE_ST_DEVICE_ID, request->xml, LOG_ERR); if (is_privileged(request->ipc_client, op)) { @@ -3432,8 +3462,8 @@ handle_device_add_request(pcmk__request_t *request) PCMK_EXEC_INVALID, "Unprivileged users must register device via CIB"); } - fenced_send_device_notification(op, &request->result, - (dev == NULL)? NULL : ID(dev)); + fenced_send_config_notification(op, &request->result, + (dev == NULL)? NULL : pcmk__xe_id(dev)); return fenced_construct_reply(request->xml, NULL, &request->result); } @@ -3441,10 +3471,10 @@ handle_device_add_request(pcmk__request_t *request) static xmlNode * handle_device_delete_request(pcmk__request_t *request) { - xmlNode *dev = get_xpath_object("//" F_STONITH_DEVICE, request->xml, + xmlNode *dev = get_xpath_object("//" PCMK__XE_ST_DEVICE_ID, request->xml, LOG_ERR); - const char *device_id = crm_element_value(dev, XML_ATTR_ID); - const char *op = crm_element_value(request->xml, F_STONITH_OPERATION); + const char *device_id = crm_element_value(dev, PCMK_XA_ID); + const char *op = crm_element_value(request->xml, PCMK__XA_ST_OP); if (is_privileged(request->ipc_client, op)) { stonith_device_remove(device_id, false); @@ -3454,7 +3484,7 @@ handle_device_delete_request(pcmk__request_t *request) PCMK_EXEC_INVALID, "Unprivileged users must delete device via CIB"); } - fenced_send_device_notification(op, &request->result, device_id); + fenced_send_config_notification(op, &request->result, device_id); return fenced_construct_reply(request->xml, NULL, &request->result); } @@ -3463,7 +3493,7 @@ static xmlNode * handle_level_add_request(pcmk__request_t *request) { char *desc = NULL; - const char *op = crm_element_value(request->xml, F_STONITH_OPERATION); + const char *op = crm_element_value(request->xml, PCMK__XA_ST_OP); if (is_privileged(request->ipc_client, op)) { fenced_register_level(request->xml, &desc, &request->result); @@ -3473,7 +3503,7 @@ handle_level_add_request(pcmk__request_t *request) PCMK_EXEC_INVALID, "Unprivileged users must add level via CIB"); } - fenced_send_level_notification(op, &request->result, desc); + fenced_send_config_notification(op, &request->result, desc); free(desc); return fenced_construct_reply(request->xml, NULL, &request->result); } @@ -3483,7 +3513,7 @@ static xmlNode * handle_level_delete_request(pcmk__request_t *request) { char *desc = NULL; - const char *op = crm_element_value(request->xml, F_STONITH_OPERATION); + const char *op = crm_element_value(request->xml, PCMK__XA_ST_OP); if (is_privileged(request->ipc_client, op)) { fenced_unregister_level(request->xml, &desc, &request->result); @@ -3493,7 +3523,7 @@ handle_level_delete_request(pcmk__request_t *request) PCMK_EXEC_INVALID, "Unprivileged users must delete level via CIB"); } - fenced_send_level_notification(op, &request->result, desc); + fenced_send_config_notification(op, &request->result, desc); free(desc); return fenced_construct_reply(request->xml, NULL, &request->result); } @@ -3505,9 +3535,9 @@ handle_cache_request(pcmk__request_t *request) int node_id = 0; const char *name = NULL; - crm_element_value_int(request->xml, XML_ATTR_ID, &node_id); - name = crm_element_value(request->xml, XML_ATTR_UNAME); - reap_crm_member(node_id, name); + crm_element_value_int(request->xml, PCMK_XA_ID, &node_id); + name = crm_element_value(request->xml, PCMK_XA_UNAME); + pcmk__cluster_forget_cluster_node(node_id, name); pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); return NULL; } @@ -3531,7 +3561,7 @@ fenced_register_handlers(void) { STONITH_OP_EXEC, handle_agent_request }, { STONITH_OP_TIMEOUT_UPDATE, handle_update_timeout_request }, { STONITH_OP_QUERY, handle_query_request }, - { T_STONITH_NOTIFY, handle_notify_request }, + { STONITH_OP_NOTIFY, handle_notify_request }, { STONITH_OP_RELAY, handle_relay_request }, { STONITH_OP_FENCE, handle_fence_request }, { STONITH_OP_FENCE_HISTORY, handle_history_request }, @@ -3596,12 +3626,15 @@ static void handle_reply(pcmk__client_t *client, xmlNode *request, const char *remote_peer) { // Copy, because request might be freed before we want to log this - char *op = crm_element_value_copy(request, F_STONITH_OPERATION); + char *op = crm_element_value_copy(request, PCMK__XA_ST_OP); if (pcmk__str_eq(op, STONITH_OP_QUERY, pcmk__str_none)) { process_remote_stonith_query(request); - } else if (pcmk__str_any_of(op, T_STONITH_NOTIFY, STONITH_OP_FENCE, NULL)) { + + } else if (pcmk__str_any_of(op, STONITH_OP_NOTIFY, STONITH_OP_FENCE, + NULL)) { fenced_process_fencing_reply(request); + } else { crm_err("Ignoring unknown %s reply from %s %s", pcmk__s(op, "untyped"), ((client == NULL)? "peer" : "client"), @@ -3635,13 +3668,13 @@ stonith_command(pcmk__client_t *client, uint32_t id, uint32_t flags, CRM_CHECK(message != NULL, return); - if (get_xpath_object("//" T_STONITH_REPLY, message, LOG_NEVER) != NULL) { + if (get_xpath_object("//" PCMK__XE_ST_REPLY, message, LOG_NEVER) != NULL) { is_reply = true; } - crm_element_value_int(message, F_STONITH_CALLOPTS, &call_options); + crm_element_value_int(message, PCMK__XA_ST_CALLOPT, &call_options); crm_debug("Processing %ssynchronous %s %s %u from %s %s", pcmk_is_set(call_options, st_opt_sync_call)? "" : "a", - crm_element_value(message, F_STONITH_OPERATION), + crm_element_value(message, PCMK__XA_ST_OP), (is_reply? "reply" : "request"), id, ((client == NULL)? "peer" : "client"), ((client == NULL)? remote_peer : pcmk__client_name(client))); @@ -3663,7 +3696,7 @@ stonith_command(pcmk__client_t *client, uint32_t id, uint32_t flags, .result = PCMK__UNKNOWN_RESULT, }; - request.op = crm_element_value_copy(request.xml, F_STONITH_OPERATION); + request.op = crm_element_value_copy(request.xml, PCMK__XA_ST_OP); CRM_CHECK(request.op != NULL, return); if (pcmk_is_set(request.call_options, st_opt_sync_call)) { diff --git a/daemons/fenced/fenced_history.c b/daemons/fenced/fenced_history.c index a766477..5fcdb1f 100644 --- a/daemons/fenced/fenced_history.c +++ b/daemons/fenced/fenced_history.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2022 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -14,7 +14,6 @@ #include <stdlib.h> #include <crm/crm.h> -#include <crm/msg_xml.h> #include <crm/common/ipc.h> #include <crm/common/ipc_internal.h> #include <crm/cluster/internal.h> @@ -42,23 +41,22 @@ stonith_send_broadcast_history(xmlNode *history, int callopts, const char *target) { - xmlNode *bcast = create_xml_node(NULL, "stonith_command"); - xmlNode *data = create_xml_node(NULL, __func__); - - if (target) { - crm_xml_add(data, F_STONITH_TARGET, target); - } - crm_xml_add(bcast, F_TYPE, T_STONITH_NG); - crm_xml_add(bcast, F_SUBTYPE, "broadcast"); - crm_xml_add(bcast, F_STONITH_OPERATION, STONITH_OP_FENCE_HISTORY); - crm_xml_add_int(bcast, F_STONITH_CALLOPTS, callopts); - if (history) { - add_node_copy(data, history); + xmlNode *bcast = pcmk__xe_create(NULL, PCMK__XE_STONITH_COMMAND); + xmlNode *wrapper = pcmk__xe_create(bcast, PCMK__XE_ST_CALLDATA); + xmlNode *call_data = pcmk__xe_create(wrapper, __func__); + + crm_xml_add(bcast, PCMK__XA_T, PCMK__VALUE_STONITH_NG); + crm_xml_add(bcast, PCMK__XA_SUBT, PCMK__VALUE_BROADCAST); + crm_xml_add(bcast, PCMK__XA_ST_OP, STONITH_OP_FENCE_HISTORY); + crm_xml_add_int(bcast, PCMK__XA_ST_CALLOPT, callopts); + + pcmk__xml_copy(call_data, history); + if (target != NULL) { + crm_xml_add(call_data, PCMK__XA_ST_TARGET, target); } - add_message_xml(bcast, F_STONITH_CALLDATA, data); - send_cluster_message(NULL, crm_msg_stonith_ng, bcast, FALSE); - free_xml(data); + pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, bcast); + free_xml(bcast); } @@ -100,7 +98,7 @@ stonith_fence_history_cleanup(const char *target, g_hash_table_foreach_remove(stonith_remote_op_list, stonith_remove_history_entry, (gpointer) target); - fenced_send_notification(T_STONITH_NOTIFY_HISTORY, NULL, NULL); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_HISTORY, NULL, NULL); } } @@ -133,34 +131,68 @@ stonith_fence_history_cleanup(const char *target, * situations where it would be handy to have it probably. */ - -static int -op_time_sort(const void *a_voidp, const void *b_voidp) +/*! + * \internal + * \brief Compare two remote fencing operations by status and completion time + * + * A pending operation is ordered before a completed operation. If both + * operations have completed, then the more recently completed operation is + * ordered first. Two pending operations are considered equal. + * + * \param[in] a First \c remote_fencing_op_t to compare + * \param[in] b Second \c remote_fencing_op_t to compare + * + * \return Standard comparison result (a negative integer if \p a is lesser, + * 0 if the values are equal, and a positive integer if \p a is greater) + */ +static gint +cmp_op_by_completion(gconstpointer a, gconstpointer b) { - const remote_fencing_op_t **a = (const remote_fencing_op_t **) a_voidp; - const remote_fencing_op_t **b = (const remote_fencing_op_t **) b_voidp; - gboolean a_pending = ((*a)->state != st_failed) && ((*a)->state != st_done); - gboolean b_pending = ((*b)->state != st_failed) && ((*b)->state != st_done); + const remote_fencing_op_t *op1 = a; + const remote_fencing_op_t *op2 = b; + bool op1_pending = stonith__op_state_pending(op1->state); + bool op2_pending = stonith__op_state_pending(op2->state); - if (a_pending && b_pending) { + if (op1_pending && op2_pending) { return 0; - } else if (a_pending) { + } + if (op1_pending) { return -1; - } else if (b_pending) { + } + if (op2_pending) { return 1; - } else if ((*b)->completed == (*a)->completed) { - if ((*b)->completed_nsec > (*a)->completed_nsec) { - return 1; - } else if ((*b)->completed_nsec == (*a)->completed_nsec) { - return 0; - } - } else if ((*b)->completed > (*a)->completed) { + } + if (op1->completed > op2->completed) { + return -1; + } + if (op1->completed < op2->completed) { return 1; } - - return -1; + if (op1->completed_nsec > op2->completed_nsec) { + return -1; + } + if (op1->completed_nsec < op2->completed_nsec) { + return 1; + } + return 0; } +/*! + * \internal + * \brief Remove a completed operation from \c stonith_remote_op_list + * + * \param[in] data \c remote_fencing_op_t to remove + * \param[in] user_data Ignored + */ +static void +remove_completed_remote_op(gpointer data, gpointer user_data) +{ + const remote_fencing_op_t *op = data; + + if (!stonith__op_state_pending(op->state)) { + g_hash_table_remove(stonith_remote_op_list, op->id); + } +} /*! * \internal @@ -170,43 +202,24 @@ op_time_sort(const void *a_voidp, const void *b_voidp) void stonith_fence_history_trim(void) { - guint num_ops; - - if (!stonith_remote_op_list) { + if (stonith_remote_op_list == NULL) { return; } - num_ops = g_hash_table_size(stonith_remote_op_list); - if (num_ops > MAX_STONITH_HISTORY) { - remote_fencing_op_t *ops[num_ops]; - remote_fencing_op_t *op = NULL; - GHashTableIter iter; - int i; - crm_trace("Fencing History growing beyond limit of %d so purge " - "half of failed/successful attempts", MAX_STONITH_HISTORY); + if (g_hash_table_size(stonith_remote_op_list) > MAX_STONITH_HISTORY) { + GList *ops = g_hash_table_get_values(stonith_remote_op_list); - /* write all ops into an array */ - i = 0; - g_hash_table_iter_init(&iter, stonith_remote_op_list); - while (g_hash_table_iter_next(&iter, NULL, (void **)&op)) { - ops[i++] = op; - } - /* run quicksort over the array so that we get pending ops - * first and then sorted most recent to oldest - */ - qsort(ops, num_ops, sizeof(remote_fencing_op_t *), op_time_sort); - /* purgest oldest half of the history entries */ - for (i = MAX_STONITH_HISTORY / 2; i < num_ops; i++) { - /* keep pending ops even if they shouldn't fill more than - * half of our buffer - */ - if ((ops[i]->state == st_failed) || (ops[i]->state == st_done)) { - g_hash_table_remove(stonith_remote_op_list, ops[i]->id); - } - } - /* we've just purged valid data from the list so there is no need - * to create a notification - if displayed it can stay - */ + crm_trace("More than %d entries in fencing history, purging oldest " + "completed operations", MAX_STONITH_HISTORY); + + ops = g_list_sort(ops, cmp_op_by_completion); + + // Always keep pending ops regardless of number of entries + g_list_foreach(g_list_nth(ops, MAX_STONITH_HISTORY / 2), + remove_completed_remote_op, NULL); + + // No need for a notification after purging old data + g_list_free(ops); } } @@ -228,10 +241,11 @@ stonith_xml_history_to_list(const xmlNode *history) CRM_LOG_ASSERT(rv != NULL); - for (xml_op = pcmk__xml_first_child(history); xml_op != NULL; - xml_op = pcmk__xml_next(xml_op)) { + for (xml_op = pcmk__xe_first_child(history, NULL, NULL, NULL); + xml_op != NULL; xml_op = pcmk__xe_next(xml_op)) { + remote_fencing_op_t *op = NULL; - char *id = crm_element_value_copy(xml_op, F_STONITH_REMOTE_OP_ID); + char *id = crm_element_value_copy(xml_op, PCMK__XA_ST_REMOTE_OP); int state; int exit_status = CRM_EX_OK; int execution_status = PCMK_EXEC_DONE; @@ -245,35 +259,37 @@ stonith_xml_history_to_list(const xmlNode *history) crm_trace("Attaching op %s to hashtable", id); - op = calloc(1, sizeof(remote_fencing_op_t)); + op = pcmk__assert_alloc(1, sizeof(remote_fencing_op_t)); op->id = id; - op->target = crm_element_value_copy(xml_op, F_STONITH_TARGET); - op->action = crm_element_value_copy(xml_op, F_STONITH_ACTION); - op->originator = crm_element_value_copy(xml_op, F_STONITH_ORIGIN); - op->delegate = crm_element_value_copy(xml_op, F_STONITH_DELEGATE); - op->client_name = crm_element_value_copy(xml_op, F_STONITH_CLIENTNAME); - crm_element_value_ll(xml_op, F_STONITH_DATE, &completed); + op->target = crm_element_value_copy(xml_op, PCMK__XA_ST_TARGET); + op->action = crm_element_value_copy(xml_op, PCMK__XA_ST_DEVICE_ACTION); + op->originator = crm_element_value_copy(xml_op, PCMK__XA_ST_ORIGIN); + op->delegate = crm_element_value_copy(xml_op, PCMK__XA_ST_DELEGATE); + op->client_name = crm_element_value_copy(xml_op, + PCMK__XA_ST_CLIENTNAME); + crm_element_value_ll(xml_op, PCMK__XA_ST_DATE, &completed); op->completed = (time_t) completed; - crm_element_value_ll(xml_op, F_STONITH_DATE_NSEC, &completed_nsec); + crm_element_value_ll(xml_op, PCMK__XA_ST_DATE_NSEC, &completed_nsec); op->completed_nsec = completed_nsec; - crm_element_value_int(xml_op, F_STONITH_STATE, &state); + crm_element_value_int(xml_op, PCMK__XA_ST_STATE, &state); op->state = (enum op_state) state; /* @COMPAT We can't use stonith__xe_get_result() here because * fencers <2.1.3 didn't include results, leading it to assume an error * status. Instead, set an unknown status in that case. */ - if ((crm_element_value_int(xml_op, XML_LRM_ATTR_RC, &exit_status) < 0) - || (crm_element_value_int(xml_op, XML_LRM_ATTR_OPSTATUS, + if ((crm_element_value_int(xml_op, PCMK__XA_RC_CODE, &exit_status) < 0) + || (crm_element_value_int(xml_op, PCMK__XA_OP_STATUS, &execution_status) < 0)) { exit_status = CRM_EX_INDETERMINATE; execution_status = PCMK_EXEC_UNKNOWN; } pcmk__set_result(&op->result, exit_status, execution_status, - crm_element_value(xml_op, XML_LRM_ATTR_EXIT_REASON)); + crm_element_value(xml_op, PCMK_XA_EXIT_REASON)); pcmk__set_result_output(&op->result, - crm_element_value_copy(xml_op, F_STONITH_OUTPUT), + crm_element_value_copy(xml_op, + PCMK__XA_ST_OUTPUT), NULL); @@ -309,7 +325,7 @@ stonith_local_history_diff_and_merge(GHashTable *remote_history, if (stonith_remote_op_list) { char *id = NULL; - history = create_xml_node(NULL, F_STONITH_HISTORY_LIST); + history = pcmk__xe_create(NULL, PCMK__XE_ST_HISTORY); g_hash_table_iter_init(&iter, stonith_remote_op_list); while (g_hash_table_iter_next(&iter, (void **)&id, (void **)&op)) { @@ -361,18 +377,19 @@ stonith_local_history_diff_and_merge(GHashTable *remote_history, cnt++; crm_trace("Attaching op %s", op->id); - entry = create_xml_node(history, STONITH_OP_EXEC); + entry = pcmk__xe_create(history, STONITH_OP_EXEC); if (add_id) { - crm_xml_add(entry, F_STONITH_REMOTE_OP_ID, op->id); + crm_xml_add(entry, PCMK__XA_ST_REMOTE_OP, op->id); } - crm_xml_add(entry, F_STONITH_TARGET, op->target); - crm_xml_add(entry, F_STONITH_ACTION, op->action); - crm_xml_add(entry, F_STONITH_ORIGIN, op->originator); - crm_xml_add(entry, F_STONITH_DELEGATE, op->delegate); - crm_xml_add(entry, F_STONITH_CLIENTNAME, op->client_name); - crm_xml_add_ll(entry, F_STONITH_DATE, op->completed); - crm_xml_add_ll(entry, F_STONITH_DATE_NSEC, op->completed_nsec); - crm_xml_add_int(entry, F_STONITH_STATE, op->state); + crm_xml_add(entry, PCMK__XA_ST_TARGET, op->target); + crm_xml_add(entry, PCMK__XA_ST_DEVICE_ACTION, op->action); + crm_xml_add(entry, PCMK__XA_ST_ORIGIN, op->originator); + crm_xml_add(entry, PCMK__XA_ST_DELEGATE, op->delegate); + crm_xml_add(entry, PCMK__XA_ST_CLIENTNAME, op->client_name); + crm_xml_add_ll(entry, PCMK__XA_ST_DATE, op->completed); + crm_xml_add_ll(entry, PCMK__XA_ST_DATE_NSEC, + op->completed_nsec); + crm_xml_add_int(entry, PCMK__XA_ST_STATE, op->state); stonith__xe_set_result(entry, &op->result); } } @@ -418,7 +435,7 @@ stonith_local_history_diff_and_merge(GHashTable *remote_history, if (updated) { stonith_fence_history_trim(); - fenced_send_notification(T_STONITH_NOTIFY_HISTORY, NULL, NULL); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_HISTORY, NULL, NULL); } if (cnt == 0) { @@ -459,17 +476,19 @@ stonith_fence_history(xmlNode *msg, xmlNode **output, const char *remote_peer, int options) { const char *target = NULL; - xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, msg, LOG_NEVER); + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, msg, LOG_NEVER); xmlNode *out_history = NULL; if (dev) { - target = crm_element_value(dev, F_STONITH_TARGET); + target = crm_element_value(dev, PCMK__XA_ST_TARGET); if (target && (options & st_opt_cs_nodeid)) { int nodeid; crm_node_t *node; pcmk__scan_min_int(target, &nodeid, 0); - node = pcmk__search_known_node_cache(nodeid, NULL, CRM_GET_PEER_ANY); + node = pcmk__search_node_caches(nodeid, NULL, + pcmk__node_search_any + |pcmk__node_search_cluster_cib); if (node) { target = node->uname; } @@ -477,18 +496,20 @@ stonith_fence_history(xmlNode *msg, xmlNode **output, } if (options & st_opt_cleanup) { + const char *call_id = crm_element_value(msg, PCMK__XA_ST_CALLID); + crm_trace("Cleaning up operations on %s in %p", target, stonith_remote_op_list); + stonith_fence_history_cleanup(target, (call_id != NULL)); - stonith_fence_history_cleanup(target, - crm_element_value(msg, F_STONITH_CALLID) != NULL); } else if (options & st_opt_broadcast) { /* there is no clear sign atm for when a history sync is done so send a notification for anything that smells like history-sync */ - fenced_send_notification(T_STONITH_NOTIFY_HISTORY_SYNCED, NULL, NULL); - if (crm_element_value(msg, F_STONITH_CALLID)) { + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED, NULL, + NULL); + if (crm_element_value(msg, PCMK__XA_ST_CALLID) != NULL) { /* this is coming from the stonith-API * * craft a broadcast with node's history @@ -502,8 +523,8 @@ stonith_fence_history(xmlNode *msg, xmlNode **output, NULL); } else if (remote_peer && !pcmk__str_eq(remote_peer, stonith_our_uname, pcmk__str_casei)) { - xmlNode *history = get_xpath_object("//" F_STONITH_HISTORY_LIST, - msg, LOG_NEVER); + xmlNode *history = get_xpath_object("//" PCMK__XE_ST_HISTORY, msg, + LOG_NEVER); /* either a broadcast created directly upon stonith-API request * or a diff as response to such a thing @@ -514,7 +535,9 @@ stonith_fence_history(xmlNode *msg, xmlNode **output, * otherwise broadcast what we have on top * marking as differential and merge in afterwards */ - if (!history || !pcmk__xe_attr_is_true(history, F_STONITH_DIFFERENTIAL)) { + if (!history + || !pcmk__xe_attr_is_true(history, PCMK__XA_ST_DIFFERENTIAL)) { + GHashTable *received_history = NULL; if (history != NULL) { @@ -524,7 +547,8 @@ stonith_fence_history(xmlNode *msg, xmlNode **output, stonith_local_history_diff_and_merge(received_history, TRUE, NULL); if (out_history) { crm_trace("Broadcasting history-diff to peers"); - pcmk__xe_set_bool_attr(out_history, F_STONITH_DIFFERENTIAL, true); + pcmk__xe_set_bool_attr(out_history, + PCMK__XA_ST_DIFFERENTIAL, true); stonith_send_broadcast_history(out_history, st_opt_broadcast | st_opt_discard_reply, NULL); diff --git a/daemons/fenced/fenced_remote.c b/daemons/fenced/fenced_remote.c index 843b3d4..f87eeb6 100644 --- a/daemons/fenced/fenced_remote.c +++ b/daemons/fenced/fenced_remote.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -24,7 +24,6 @@ #include <regex.h> #include <crm/crm.h> -#include <crm/msg_xml.h> #include <crm/common/ipc.h> #include <crm/common/ipc_internal.h> #include <crm/cluster/internal.h> @@ -370,24 +369,25 @@ undo_op_remap(remote_fencing_op_t *op) * \internal * \brief Create notification data XML for a fencing operation result * - * \param[in] op Fencer operation that completed + * \param[in,out] parent Parent XML element for newly created element + * \param[in] op Fencer operation that completed * * \return Newly created XML to add as notification data * \note The caller is responsible for freeing the result. */ static xmlNode * -fencing_result2xml(const remote_fencing_op_t *op) +fencing_result2xml(xmlNode *parent, const remote_fencing_op_t *op) { - xmlNode *notify_data = create_xml_node(NULL, T_STONITH_NOTIFY_FENCE); + xmlNode *notify_data = pcmk__xe_create(parent, PCMK__XE_ST_NOTIFY_FENCE); - crm_xml_add_int(notify_data, "state", op->state); - crm_xml_add(notify_data, F_STONITH_TARGET, op->target); - crm_xml_add(notify_data, F_STONITH_ACTION, op->action); - crm_xml_add(notify_data, F_STONITH_DELEGATE, op->delegate); - crm_xml_add(notify_data, F_STONITH_REMOTE_OP_ID, op->id); - crm_xml_add(notify_data, F_STONITH_ORIGIN, op->originator); - crm_xml_add(notify_data, F_STONITH_CLIENTID, op->client_id); - crm_xml_add(notify_data, F_STONITH_CLIENTNAME, op->client_name); + crm_xml_add_int(notify_data, PCMK_XA_STATE, op->state); + crm_xml_add(notify_data, PCMK__XA_ST_TARGET, op->target); + crm_xml_add(notify_data, PCMK__XA_ST_DEVICE_ACTION, op->action); + crm_xml_add(notify_data, PCMK__XA_ST_DELEGATE, op->delegate); + crm_xml_add(notify_data, PCMK__XA_ST_REMOTE_OP, op->id); + crm_xml_add(notify_data, PCMK__XA_ST_ORIGIN, op->originator); + crm_xml_add(notify_data, PCMK__XA_ST_CLIENTID, op->client_id); + crm_xml_add(notify_data, PCMK__XA_ST_CLIENTNAME, op->client_name); return notify_data; } @@ -403,25 +403,26 @@ void fenced_broadcast_op_result(const remote_fencing_op_t *op, bool op_merged) { static int count = 0; - xmlNode *bcast = create_xml_node(NULL, T_STONITH_REPLY); - xmlNode *notify_data = fencing_result2xml(op); + xmlNode *bcast = pcmk__xe_create(NULL, PCMK__XE_ST_REPLY); + xmlNode *wrapper = NULL; + xmlNode *notify_data = NULL; count++; crm_trace("Broadcasting result to peers"); - crm_xml_add(bcast, F_TYPE, T_STONITH_NOTIFY); - crm_xml_add(bcast, F_SUBTYPE, "broadcast"); - crm_xml_add(bcast, F_STONITH_OPERATION, T_STONITH_NOTIFY); - crm_xml_add_int(bcast, "count", count); + crm_xml_add(bcast, PCMK__XA_T, PCMK__VALUE_ST_NOTIFY); + crm_xml_add(bcast, PCMK__XA_SUBT, PCMK__VALUE_BROADCAST); + crm_xml_add(bcast, PCMK__XA_ST_OP, STONITH_OP_NOTIFY); + crm_xml_add_int(bcast, PCMK_XA_COUNT, count); if (op_merged) { - pcmk__xe_set_bool_attr(bcast, F_STONITH_MERGED, true); + pcmk__xe_set_bool_attr(bcast, PCMK__XA_ST_OP_MERGED, true); } + wrapper = pcmk__xe_create(bcast, PCMK__XE_ST_CALLDATA); + notify_data = fencing_result2xml(wrapper, op); stonith__xe_set_result(notify_data, &op->result); - add_message_xml(bcast, F_STONITH_CALLDATA, notify_data); - send_cluster_message(NULL, crm_msg_stonith_ng, bcast, FALSE); - free_xml(notify_data); + pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, bcast); free_xml(bcast); return; @@ -447,12 +448,12 @@ handle_local_reply_and_notify(remote_fencing_op_t *op, xmlNode *data) } /* Do notification with a clean data object */ - crm_xml_add_int(data, "state", op->state); - crm_xml_add(data, F_STONITH_TARGET, op->target); - crm_xml_add(data, F_STONITH_OPERATION, op->action); + crm_xml_add_int(data, PCMK_XA_STATE, op->state); + crm_xml_add(data, PCMK__XA_ST_TARGET, op->target); + crm_xml_add(data, PCMK__XA_ST_OP, op->action); reply = fenced_construct_reply(op->request, data, &op->result); - crm_xml_add(reply, F_STONITH_DELEGATE, op->delegate); + crm_xml_add(reply, PCMK__XA_ST_DELEGATE, op->delegate); /* Send fencing OP reply to local client that initiated fencing */ client = pcmk__find_client_by_id(op->client_id); @@ -463,10 +464,11 @@ handle_local_reply_and_notify(remote_fencing_op_t *op, xmlNode *data) } /* bcast to all local clients that the fencing operation happend */ - notify_data = fencing_result2xml(op); - fenced_send_notification(T_STONITH_NOTIFY_FENCE, &op->result, notify_data); + notify_data = fencing_result2xml(NULL, op); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_FENCE, &op->result, + notify_data); free_xml(notify_data); - fenced_send_notification(T_STONITH_NOTIFY_HISTORY, NULL, NULL); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_HISTORY, NULL, NULL); /* mark this op as having notify's already sent */ op->notify_sent = TRUE; @@ -509,12 +511,13 @@ finalize_op_duplicates(remote_fencing_op_t *op, xmlNode *data) static char * delegate_from_xml(xmlNode *xml) { - xmlNode *match = get_xpath_object("//@" F_STONITH_DELEGATE, xml, LOG_NEVER); + xmlNode *match = get_xpath_object("//@" PCMK__XA_ST_DELEGATE, xml, + LOG_NEVER); if (match == NULL) { - return crm_element_value_copy(xml, F_ORIG); + return crm_element_value_copy(xml, PCMK__XA_SRC); } else { - return crm_element_value_copy(match, F_STONITH_DELEGATE); + return crm_element_value_copy(match, PCMK__XA_ST_DELEGATE); } } @@ -564,7 +567,7 @@ finalize_op(remote_fencing_op_t *op, xmlNode *data, bool dup) undo_op_remap(op); if (data == NULL) { - data = create_xml_node(NULL, "remote-op"); + data = pcmk__xe_create(NULL, "remote-op"); local_data = data; } else if (op->delegate == NULL) { @@ -584,15 +587,15 @@ finalize_op(remote_fencing_op_t *op, xmlNode *data, bool dup) } } - if (dup || (crm_element_value(data, F_STONITH_MERGED) != NULL)) { + if (dup || (crm_element_value(data, PCMK__XA_ST_OP_MERGED) != NULL)) { op_merged = true; } /* Tell everyone the operation is done, we will continue * with doing the local notifications once we receive * the broadcast back. */ - subt = crm_element_value(data, F_SUBTYPE); - if (!dup && !pcmk__str_eq(subt, "broadcast", pcmk__str_casei)) { + subt = crm_element_value(data, PCMK__XA_SUBT); + if (!dup && !pcmk__str_eq(subt, PCMK__VALUE_BROADCAST, pcmk__str_none)) { /* Defer notification until the bcast message arrives */ fenced_broadcast_op_result(op, op_merged); free_xml(local_data); @@ -800,7 +803,8 @@ add_required_device(remote_fencing_op_t *op, const char *device) sort_strings); if (!match) { - op->automatic_list = g_list_prepend(op->automatic_list, strdup(device)); + op->automatic_list = g_list_prepend(op->automatic_list, + pcmk__str_copy(device)); } } @@ -833,7 +837,10 @@ set_op_device_list(remote_fencing_op_t * op, GList *devices) op->devices_list = NULL; } for (lpc = devices; lpc != NULL; lpc = lpc->next) { - op->devices_list = g_list_append(op->devices_list, strdup(lpc->data)); + const char *device = lpc->data; + + op->devices_list = g_list_append(op->devices_list, + pcmk__str_copy(device)); } op->devices = op->devices_list; } @@ -1001,6 +1008,7 @@ merge_duplicates(remote_fencing_op_t *op) g_hash_table_iter_init(&iter, stonith_remote_op_list); while (g_hash_table_iter_next(&iter, NULL, (void **)&other)) { const char *other_action = op_requested_action(other); + crm_node_t *node = NULL; if (!strcmp(op->id, other->id)) { continue; // Don't compare against self @@ -1030,7 +1038,11 @@ merge_duplicates(remote_fencing_op_t *op) op->id, other->id, other->target); continue; } - if (!fencing_peer_active(crm_get_peer(0, other->originator))) { + + node = pcmk__get_node(0, other->originator, NULL, + pcmk__node_search_cluster_member); + + if (!fencing_peer_active(node)) { crm_notice("Failing action '%s' targeting %s originating from " "client %s@%s: Originator is dead " CRM_XS " id=%.8s", other->action, other->target, other->client_name, @@ -1042,8 +1054,8 @@ merge_duplicates(remote_fencing_op_t *op) } if ((other->total_timeout > 0) && (now > (other->total_timeout + other->created))) { - crm_trace("%.8s not duplicate of %.8s: old (%ld vs. %ld + %d)", - op->id, other->id, now, other->created, + crm_trace("%.8s not duplicate of %.8s: old (%lld vs. %lld + %ds)", + op->id, other->id, (long long)now, (long long)other->created, other->total_timeout); continue; } @@ -1055,7 +1067,7 @@ merge_duplicates(remote_fencing_op_t *op) if (other->total_timeout == 0) { other->total_timeout = op->total_timeout = TIMEOUT_MULTIPLY_FACTOR * get_op_total_timeout(op, NULL); - crm_trace("Best guess as to timeout used for %.8s: %d", + crm_trace("Best guess as to timeout used for %.8s: %ds", other->id, other->total_timeout); } crm_notice("Merging fencing action '%s' targeting %s originating from " @@ -1097,12 +1109,12 @@ int fenced_handle_manual_confirmation(const pcmk__client_t *client, xmlNode *msg) { remote_fencing_op_t *op = NULL; - xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, msg, LOG_ERR); + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, msg, LOG_ERR); CRM_CHECK(dev != NULL, return EPROTO); crm_notice("Received manual confirmation that %s has been fenced", - pcmk__s(crm_element_value(dev, F_STONITH_TARGET), + pcmk__s(crm_element_value(dev, PCMK__XA_ST_TARGET), "unknown target")); op = initiate_remote_stonith_op(client, msg, TRUE); if (op == NULL) { @@ -1110,7 +1122,7 @@ fenced_handle_manual_confirmation(const pcmk__client_t *client, xmlNode *msg) } op->state = st_done; set_fencing_completed(op); - op->delegate = strdup("a human"); + op->delegate = pcmk__str_copy("a human"); // For the fencer's purposes, the fencing operation is done pcmk__set_result(&op->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); @@ -1137,7 +1149,8 @@ void * create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer) { remote_fencing_op_t *op = NULL; - xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, request, LOG_NEVER); + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, request, + LOG_NEVER); int call_options = 0; const char *operation = NULL; @@ -1146,7 +1159,7 @@ create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer) /* If this operation is owned by another node, check to make * sure we haven't already created this operation. */ if (peer && dev) { - const char *op_id = crm_element_value(dev, F_STONITH_REMOTE_OP_ID); + const char *op_id = crm_element_value(dev, PCMK__XA_ST_REMOTE_OP); CRM_CHECK(op_id != NULL, return NULL); @@ -1158,15 +1171,14 @@ create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer) } } - op = calloc(1, sizeof(remote_fencing_op_t)); - CRM_ASSERT(op != NULL); + op = pcmk__assert_alloc(1, sizeof(remote_fencing_op_t)); - crm_element_value_int(request, F_STONITH_TIMEOUT, &(op->base_timeout)); + crm_element_value_int(request, PCMK__XA_ST_TIMEOUT, &(op->base_timeout)); // Value -1 means disable any static/random fencing delays - crm_element_value_int(request, F_STONITH_DELAY, &(op->client_delay)); + crm_element_value_int(request, PCMK__XA_ST_DELAY, &(op->client_delay)); if (peer && dev) { - op->id = crm_element_value_copy(dev, F_STONITH_REMOTE_OP_ID); + op->id = crm_element_value_copy(dev, PCMK__XA_ST_REMOTE_OP); } else { op->id = crm_generate_uuid(); } @@ -1175,41 +1187,49 @@ create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer) op->state = st_query; op->replies_expected = fencing_active_peers(); - op->action = crm_element_value_copy(dev, F_STONITH_ACTION); - op->originator = crm_element_value_copy(dev, F_STONITH_ORIGIN); - op->delegate = crm_element_value_copy(dev, F_STONITH_DELEGATE); /* May not be set */ - op->created = time(NULL); + op->action = crm_element_value_copy(dev, PCMK__XA_ST_DEVICE_ACTION); + /* The node initiating the stonith operation. If an operation is relayed, + * this is the last node the operation lands on. When in standalone mode, + * origin is the ID of the client that originated the operation. + * + * Or may be the name of the function that created the operation. + */ + op->originator = crm_element_value_copy(dev, PCMK__XA_ST_ORIGIN); if (op->originator == NULL) { /* Local or relayed request */ - op->originator = strdup(stonith_our_uname); + op->originator = pcmk__str_copy(stonith_our_uname); } - CRM_LOG_ASSERT(client != NULL); - if (client) { - op->client_id = strdup(client); - } + // Delegate may not be set + op->delegate = crm_element_value_copy(dev, PCMK__XA_ST_DELEGATE); + op->created = time(NULL); + CRM_LOG_ASSERT(client != NULL); + op->client_id = pcmk__str_copy(client); /* For a RELAY operation, set fenced on the client. */ - operation = crm_element_value(request, F_STONITH_OPERATION); + operation = crm_element_value(request, PCMK__XA_ST_OP); if (pcmk__str_eq(operation, STONITH_OP_RELAY, pcmk__str_none)) { op->client_name = crm_strdup_printf("%s.%lu", crm_system_name, (unsigned long) getpid()); } else { - op->client_name = crm_element_value_copy(request, F_STONITH_CLIENTNAME); + op->client_name = crm_element_value_copy(request, + PCMK__XA_ST_CLIENTNAME); } - op->target = crm_element_value_copy(dev, F_STONITH_TARGET); - op->request = copy_xml(request); /* TODO: Figure out how to avoid this */ - crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options); + op->target = crm_element_value_copy(dev, PCMK__XA_ST_TARGET); + + // @TODO Figure out how to avoid copying XML here + op->request = pcmk__xml_copy(NULL, request); + crm_element_value_int(request, PCMK__XA_ST_CALLOPT, &call_options); op->call_options = call_options; - crm_element_value_int(request, F_STONITH_CALLID, &(op->client_callid)); + crm_element_value_int(request, PCMK__XA_ST_CALLID, &(op->client_callid)); crm_trace("%s new fencing op %s ('%s' targeting %s for client %s, " - "base timeout %d, %u %s expected)", + "base timeout %ds, %u %s expected)", (peer && dev)? "Recorded" : "Generated", op->id, op->action, op->target, op->client_name, op->base_timeout, op->replies_expected, @@ -1220,14 +1240,15 @@ create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer) crm_node_t *node; pcmk__scan_min_int(op->target, &nodeid, 0); - node = pcmk__search_known_node_cache(nodeid, NULL, CRM_GET_PEER_ANY); + node = pcmk__search_node_caches(nodeid, NULL, + pcmk__node_search_any + |pcmk__node_search_cluster_cib); /* Ensure the conversion only happens once */ stonith__clear_call_options(op->call_options, op->id, st_opt_cs_nodeid); if (node && node->uname) { - free(op->target); - op->target = strdup(node->uname); + pcmk__str_update(&(op->target), node->uname); } else { crm_warn("Could not expand nodeid '%s' into a host name", op->target); @@ -1239,7 +1260,7 @@ create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer) if (op->state != st_duplicate) { /* kick history readers */ - fenced_send_notification(T_STONITH_NOTIFY_HISTORY, NULL, NULL); + fenced_send_notification(PCMK__VALUE_ST_NOTIFY_HISTORY, NULL, NULL); } /* safe to trim as long as that doesn't touch pending ops */ @@ -1272,7 +1293,7 @@ initiate_remote_stonith_op(const pcmk__client_t *client, xmlNode *request, if (client) { client_id = client->id; } else { - client_id = crm_element_value(request, F_STONITH_CLIENTID); + client_id = crm_element_value(request, PCMK__XA_ST_CLIENTID); } CRM_LOG_ASSERT(client_id != NULL); @@ -1305,7 +1326,7 @@ initiate_remote_stonith_op(const pcmk__client_t *client, xmlNode *request, default: crm_notice("Requesting peer fencing (%s) targeting %s " - CRM_XS " id=%.8s state=%s base_timeout=%d", + CRM_XS " id=%.8s state=%s base_timeout=%ds", op->action, op->target, op->id, stonith_op_state_str(op->state), op->base_timeout); } @@ -1313,24 +1334,24 @@ initiate_remote_stonith_op(const pcmk__client_t *client, xmlNode *request, query = stonith_create_op(op->client_callid, op->id, STONITH_OP_QUERY, NULL, op->call_options); - crm_xml_add(query, F_STONITH_REMOTE_OP_ID, op->id); - crm_xml_add(query, F_STONITH_TARGET, op->target); - crm_xml_add(query, F_STONITH_ACTION, op_requested_action(op)); - crm_xml_add(query, F_STONITH_ORIGIN, op->originator); - crm_xml_add(query, F_STONITH_CLIENTID, op->client_id); - crm_xml_add(query, F_STONITH_CLIENTNAME, op->client_name); - crm_xml_add_int(query, F_STONITH_TIMEOUT, op->base_timeout); + crm_xml_add(query, PCMK__XA_ST_REMOTE_OP, op->id); + crm_xml_add(query, PCMK__XA_ST_TARGET, op->target); + crm_xml_add(query, PCMK__XA_ST_DEVICE_ACTION, op_requested_action(op)); + crm_xml_add(query, PCMK__XA_ST_ORIGIN, op->originator); + crm_xml_add(query, PCMK__XA_ST_CLIENTID, op->client_id); + crm_xml_add(query, PCMK__XA_ST_CLIENTNAME, op->client_name); + crm_xml_add_int(query, PCMK__XA_ST_TIMEOUT, op->base_timeout); /* In case of RELAY operation, RELAY information is added to the query to delete the original operation of RELAY. */ - operation = crm_element_value(request, F_STONITH_OPERATION); + operation = crm_element_value(request, PCMK__XA_ST_OP); if (pcmk__str_eq(operation, STONITH_OP_RELAY, pcmk__str_none)) { - relay_op_id = crm_element_value(request, F_STONITH_REMOTE_OP_ID); + relay_op_id = crm_element_value(request, PCMK__XA_ST_REMOTE_OP); if (relay_op_id) { - crm_xml_add(query, F_STONITH_REMOTE_OP_ID_RELAY, relay_op_id); + crm_xml_add(query, PCMK__XA_ST_REMOTE_OP_RELAY, relay_op_id); } } - send_cluster_message(NULL, crm_msg_stonith_ng, query, FALSE); + pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, query); free_xml(query); query_timeout = op->base_timeout * TIMEOUT_MULTIPLY_FACTOR; @@ -1348,6 +1369,16 @@ enum find_best_peer_options { FIND_PEER_VERIFIED_ONLY = 0x0004, }; +static bool +is_watchdog_fencing(const remote_fencing_op_t *op, const char *device) +{ + return (stonith_watchdog_timeout_ms > 0 + // Only an explicit mismatch is considered not a watchdog fencing. + && pcmk__str_eq(device, STONITH_WATCHDOG_ID, pcmk__str_null_matches) + && pcmk__is_fencing_action(op->action) + && node_does_watchdog_fencing(op->target)); +} + static peer_device_info_t * find_best_peer(const char *device, remote_fencing_op_t * op, enum find_best_peer_options options) { @@ -1443,10 +1474,10 @@ stonith_choose_peer(remote_fencing_op_t * op) && pcmk_is_set(op->call_options, st_opt_topology) && (advance_topology_level(op, false) == pcmk_rc_ok)); - if ((stonith_watchdog_timeout_ms > 0) - && pcmk__is_fencing_action(op->action) - && pcmk__str_eq(device, STONITH_WATCHDOG_ID, pcmk__str_none) - && node_does_watchdog_fencing(op->target)) { + /* With a simple watchdog fencing configuration without a topology, + * "device" is NULL here. Consider it should be done with watchdog fencing. + */ + if (is_watchdog_fencing(op, device)) { crm_info("Couldn't contact watchdog-fencing target-node (%s)", op->target); /* check_watchdog_fencing_and_wait will log additional info */ @@ -1458,32 +1489,69 @@ stonith_choose_peer(remote_fencing_op_t * op) } static int +valid_fencing_timeout(int specified_timeout, bool action_specific, + const remote_fencing_op_t *op, const char *device) +{ + int timeout = specified_timeout; + + if (!is_watchdog_fencing(op, device)) { + return timeout; + } + + timeout = (int) QB_MIN(QB_MAX(specified_timeout, + stonith_watchdog_timeout_ms / 1000), INT_MAX); + + if (timeout > specified_timeout) { + if (action_specific) { + crm_warn("pcmk_%s_timeout %ds for %s is too short (must be >= " + PCMK_OPT_STONITH_WATCHDOG_TIMEOUT " %ds), using %ds " + "instead", + op->action, specified_timeout, device? device : "watchdog", + timeout, timeout); + + } else { + crm_warn("Fencing timeout %ds is too short (must be >= " + PCMK_OPT_STONITH_WATCHDOG_TIMEOUT " %ds), using %ds " + "instead", + specified_timeout, timeout, timeout); + } + } + + return timeout; +} + +static int get_device_timeout(const remote_fencing_op_t *op, const peer_device_info_t *peer, const char *device, bool with_delay) { + int timeout = op->base_timeout; device_properties_t *props; - int delay = 0; + + timeout = valid_fencing_timeout(op->base_timeout, false, op, device); if (!peer || !device) { - return op->base_timeout; + return timeout; } props = g_hash_table_lookup(peer->devices, device); if (!props) { - return op->base_timeout; + return timeout; + } + + if (props->custom_action_timeout[op->phase]) { + timeout = valid_fencing_timeout(props->custom_action_timeout[op->phase], + true, op, device); } // op->client_delay < 0 means disable any static/random fencing delays if (with_delay && (op->client_delay >= 0)) { // delay_base is eventually limited by delay_max - delay = (props->delay_max[op->phase] > 0 ? - props->delay_max[op->phase] : props->delay_base[op->phase]); + timeout += (props->delay_max[op->phase] > 0 ? + props->delay_max[op->phase] : props->delay_base[op->phase]); } - return (props->custom_action_timeout[op->phase]? - props->custom_action_timeout[op->phase] : op->base_timeout) - + delay; + return timeout; } struct timeout_data { @@ -1532,7 +1600,7 @@ static int get_op_total_timeout(const remote_fencing_op_t *op, const peer_device_info_t *chosen_peer) { - int total_timeout = 0; + long long total_timeout = 0; stonith_topology_t *tp = find_topology_for_host(op->target); if (pcmk_is_set(op->call_options, st_opt_topology) && tp) { @@ -1558,17 +1626,7 @@ get_op_total_timeout(const remote_fencing_op_t *op, continue; } for (device_list = tp->levels[i]; device_list; device_list = device_list->next) { - /* in case of watchdog-device we add the timeout to the budget - regardless of if we got a reply or not - */ - if ((stonith_watchdog_timeout_ms > 0) - && pcmk__is_fencing_action(op->action) - && pcmk__str_eq(device_list->data, STONITH_WATCHDOG_ID, - pcmk__str_none) - && node_does_watchdog_fencing(op->target)) { - total_timeout += stonith_watchdog_timeout_ms / 1000; - continue; - } + bool found = false; for (iter = op->query_results; iter != NULL; iter = iter->next) { const peer_device_info_t *peer = iter->data; @@ -1586,9 +1644,17 @@ get_op_total_timeout(const remote_fencing_op_t *op, total_timeout += get_device_timeout(op, peer, device_list->data, true); + found = true; break; } } /* End Loop3: match device with peer that owns device, find device's timeout period */ + + /* in case of watchdog-device we add the timeout to the budget + if didn't get a reply + */ + if (!found && is_watchdog_fencing(op, device_list->data)) { + total_timeout += stonith_watchdog_timeout_ms / 1000; + } } /* End Loop2: iterate through devices at a specific level */ } /*End Loop1: iterate through fencing levels */ @@ -1612,15 +1678,23 @@ get_op_total_timeout(const remote_fencing_op_t *op, } else if (chosen_peer) { total_timeout = get_peer_timeout(op, chosen_peer); + } else { + total_timeout = valid_fencing_timeout(op->base_timeout, false, op, + NULL); + } + + if (total_timeout <= 0) { total_timeout = op->base_timeout; } /* Take any requested fencing delay into account to prevent it from eating * up the total timeout. */ - return ((total_timeout ? total_timeout : op->base_timeout) - + ((op->client_delay > 0)? op->client_delay : 0)); + if (op->client_delay > 0) { + total_timeout += op->client_delay; + } + return (int) QB_MIN(total_timeout, INT_MAX); } static void @@ -1643,9 +1717,9 @@ report_timeout_period(remote_fencing_op_t * op, int op_timeout) } crm_trace("Reporting timeout for %s (id=%.8s)", op->client_name, op->id); - client_node = crm_element_value(op->request, F_STONITH_CLIENTNODE); - call_id = crm_element_value(op->request, F_STONITH_CALLID); - client_id = crm_element_value(op->request, F_STONITH_CLIENTID); + client_node = crm_element_value(op->request, PCMK__XA_ST_CLIENTNODE); + call_id = crm_element_value(op->request, PCMK__XA_ST_CALLID); + client_id = crm_element_value(op->request, PCMK__XA_ST_CLIENTID); if (!client_node || !call_id || !client_id) { return; } @@ -1658,12 +1732,14 @@ report_timeout_period(remote_fencing_op_t * op, int op_timeout) /* The client is connected to another node, relay this update to them */ update = stonith_create_op(op->client_callid, op->id, STONITH_OP_TIMEOUT_UPDATE, NULL, 0); - crm_xml_add(update, F_STONITH_REMOTE_OP_ID, op->id); - crm_xml_add(update, F_STONITH_CLIENTID, client_id); - crm_xml_add(update, F_STONITH_CALLID, call_id); - crm_xml_add_int(update, F_STONITH_TIMEOUT, op_timeout); + crm_xml_add(update, PCMK__XA_ST_REMOTE_OP, op->id); + crm_xml_add(update, PCMK__XA_ST_CLIENTID, client_id); + crm_xml_add(update, PCMK__XA_ST_CALLID, call_id); + crm_xml_add_int(update, PCMK__XA_ST_TIMEOUT, op_timeout); - send_cluster_message(crm_get_peer(0, client_node), crm_msg_stonith_ng, update, FALSE); + pcmk__cluster_send_message(pcmk__get_node(0, client_node, NULL, + pcmk__node_search_cluster_member), + crm_msg_stonith_ng, update); free_xml(update); @@ -1742,17 +1818,18 @@ static gboolean check_watchdog_fencing_and_wait(remote_fencing_op_t * op) { if (node_does_watchdog_fencing(op->target)) { + guint timeout_ms = QB_MIN(stonith_watchdog_timeout_ms, UINT_MAX); - crm_notice("Waiting %lds for %s to self-fence (%s) for " + crm_notice("Waiting %s for %s to self-fence (%s) for " "client %s " CRM_XS " id=%.8s", - (stonith_watchdog_timeout_ms / 1000), - op->target, op->action, op->client_name, op->id); + pcmk__readable_interval(timeout_ms), op->target, op->action, + op->client_name, op->id); if (op->op_timer_one) { g_source_remove(op->op_timer_one); } - op->op_timer_one = g_timeout_add(stonith_watchdog_timeout_ms, - remote_op_watchdog_done, op); + op->op_timer_one = g_timeout_add(timeout_ms, remote_op_watchdog_done, + op); return TRUE; } else { crm_debug("Skipping fallback to watchdog-fencing as %s is " @@ -1819,7 +1896,7 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) op->total_timeout = TIMEOUT_MULTIPLY_FACTOR * get_op_total_timeout(op, peer); op->op_timer_total = g_timeout_add(1000 * op->total_timeout, remote_op_timeout, op); report_timeout_period(op, op->total_timeout); - crm_info("Total timeout set to %d for peer's fencing targeting %s for %s" + crm_info("Total timeout set to %ds for peer's fencing targeting %s for %s" CRM_XS "id=%.8s", op->total_timeout, op->target, op->client_name, op->id); } @@ -1846,6 +1923,9 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) if (peer) { int timeout_one = 0; xmlNode *remote_op = stonith_create_op(op->client_callid, op->id, STONITH_OP_FENCE, NULL, 0); + const crm_node_t *peer_node = + pcmk__get_node(0, peer->host, NULL, + pcmk__node_search_cluster_member); if (op->client_delay > 0) { /* Take requested fencing delay into account to prevent it from @@ -1854,15 +1934,15 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) timeout_one = TIMEOUT_MULTIPLY_FACTOR * op->client_delay; } - crm_xml_add(remote_op, F_STONITH_REMOTE_OP_ID, op->id); - crm_xml_add(remote_op, F_STONITH_TARGET, op->target); - crm_xml_add(remote_op, F_STONITH_ACTION, op->action); - crm_xml_add(remote_op, F_STONITH_ORIGIN, op->originator); - crm_xml_add(remote_op, F_STONITH_CLIENTID, op->client_id); - crm_xml_add(remote_op, F_STONITH_CLIENTNAME, op->client_name); - crm_xml_add_int(remote_op, F_STONITH_TIMEOUT, timeout); - crm_xml_add_int(remote_op, F_STONITH_CALLOPTS, op->call_options); - crm_xml_add_int(remote_op, F_STONITH_DELAY, op->client_delay); + crm_xml_add(remote_op, PCMK__XA_ST_REMOTE_OP, op->id); + crm_xml_add(remote_op, PCMK__XA_ST_TARGET, op->target); + crm_xml_add(remote_op, PCMK__XA_ST_DEVICE_ACTION, op->action); + crm_xml_add(remote_op, PCMK__XA_ST_ORIGIN, op->originator); + crm_xml_add(remote_op, PCMK__XA_ST_CLIENTID, op->client_id); + crm_xml_add(remote_op, PCMK__XA_ST_CLIENTNAME, op->client_name); + crm_xml_add_int(remote_op, PCMK__XA_ST_TIMEOUT, timeout); + crm_xml_add_int(remote_op, PCMK__XA_ST_CALLOPT, op->call_options); + crm_xml_add_int(remote_op, PCMK__XA_ST_DELAY, op->client_delay); if (device) { timeout_one += TIMEOUT_MULTIPLY_FACTOR * @@ -1871,14 +1951,15 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) "using %s " CRM_XS " for client %s (%ds)", peer->host, op->action, op->target, device, op->client_name, timeout_one); - crm_xml_add(remote_op, F_STONITH_DEVICE, device); + crm_xml_add(remote_op, PCMK__XA_ST_DEVICE_ID, device); } else { timeout_one += TIMEOUT_MULTIPLY_FACTOR * get_peer_timeout(op, peer); crm_notice("Requesting that %s perform '%s' action targeting %s " - CRM_XS " for client %s (%ds, %lds)", + CRM_XS " for client %s (%ds, %s)", peer->host, op->action, op->target, op->client_name, - timeout_one, stonith_watchdog_timeout_ms); + timeout_one, + pcmk__readable_interval(stonith_watchdog_timeout_ms)); } op->state = st_exec; @@ -1887,11 +1968,8 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) op->op_timer_one = 0; } - if (!((stonith_watchdog_timeout_ms > 0) - && (pcmk__str_eq(device, STONITH_WATCHDOG_ID, pcmk__str_none) - || (pcmk__str_eq(peer->host, op->target, pcmk__str_casei) - && pcmk__is_fencing_action(op->action))) - && check_watchdog_fencing_and_wait(op))) { + if (!is_watchdog_fencing(op, device) + || !check_watchdog_fencing_and_wait(op)) { /* Some thoughts about self-fencing cases reaching this point: - Actually check in check_watchdog_fencing_and_wait @@ -1907,8 +1985,8 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) enabled for a node but the watchdog-fencing-device isn't explicitly chosen for suicide. Local pe-execution in sbd may detect the node as unclean and lead to timely suicide. - Otherwise the selection of stonith-watchdog-timeout at - least is questionable. + Otherwise the selection of PCMK_OPT_STONITH_WATCHDOG_TIMEOUT + at least is questionable. */ /* coming here we're not waiting for watchdog timeout - @@ -1916,7 +1994,7 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) op->op_timer_one = g_timeout_add((1000 * timeout_one), remote_op_timeout_one, op); } - send_cluster_message(crm_get_peer(0, peer->host), crm_msg_stonith_ng, remote_op, FALSE); + pcmk__cluster_send_message(peer_node, crm_msg_stonith_ng, remote_op); peer->tried = TRUE; free_xml(remote_op); return; @@ -1948,11 +2026,15 @@ request_peer_fencing(remote_fencing_op_t *op, peer_device_info_t *peer) * but we have all the expected replies, then no devices * are available to execute the fencing operation. */ - if(stonith_watchdog_timeout_ms > 0 && pcmk__str_eq(device, - STONITH_WATCHDOG_ID, pcmk__str_null_matches)) { - if (check_watchdog_fencing_and_wait(op)) { - return; - } + if (is_watchdog_fencing(op, device) + && check_watchdog_fencing_and_wait(op)) { + /* Consider a watchdog fencing targeting an offline node executing + * once it starts waiting for the target to self-fence. So that when + * the query timer pops, remote_op_query_timeout() considers the + * fencing already in progress. + */ + op->state = st_exec; + return; } if (op->state == st_query) { @@ -2078,24 +2160,25 @@ parse_action_specific(const xmlNode *xml, const char *peer, const char *device, enum st_remap_phase phase, device_properties_t *props) { props->custom_action_timeout[phase] = 0; - crm_element_value_int(xml, F_STONITH_ACTION_TIMEOUT, + crm_element_value_int(xml, PCMK__XA_ST_ACTION_TIMEOUT, &props->custom_action_timeout[phase]); if (props->custom_action_timeout[phase]) { - crm_trace("Peer %s with device %s returned %s action timeout %d", + crm_trace("Peer %s with device %s returned %s action timeout %ds", peer, device, action, props->custom_action_timeout[phase]); } props->delay_max[phase] = 0; - crm_element_value_int(xml, F_STONITH_DELAY_MAX, &props->delay_max[phase]); + crm_element_value_int(xml, PCMK__XA_ST_DELAY_MAX, &props->delay_max[phase]); if (props->delay_max[phase]) { - crm_trace("Peer %s with device %s returned maximum of random delay %d for %s", + crm_trace("Peer %s with device %s returned maximum of random delay %ds for %s", peer, device, props->delay_max[phase], action); } props->delay_base[phase] = 0; - crm_element_value_int(xml, F_STONITH_DELAY_BASE, &props->delay_base[phase]); + crm_element_value_int(xml, PCMK__XA_ST_DELAY_BASE, + &props->delay_base[phase]); if (props->delay_base[phase]) { - crm_trace("Peer %s with device %s returned base delay %d for %s", + crm_trace("Peer %s with device %s returned base delay %ds for %s", peer, device, props->delay_base[phase], action); } @@ -2103,7 +2186,7 @@ parse_action_specific(const xmlNode *xml, const char *peer, const char *device, if (pcmk__str_eq(action, PCMK_ACTION_ON, pcmk__str_none)) { int required = 0; - crm_element_value_int(xml, F_STONITH_DEVICE_REQUIRED, &required); + crm_element_value_int(xml, PCMK__XA_ST_REQUIRED, &required); if (required) { crm_trace("Peer %s requires device %s to execute for action %s", peer, device, action); @@ -2114,7 +2197,7 @@ parse_action_specific(const xmlNode *xml, const char *peer, const char *device, /* If a reboot is remapped to off+on, it's possible that a node is allowed * to perform one action but not another. */ - if (pcmk__xe_attr_is_true(xml, F_STONITH_ACTION_DISALLOWED)) { + if (pcmk__xe_attr_is_true(xml, PCMK__XA_ST_ACTION_DISALLOWED)) { props->disallowed[phase] = TRUE; crm_trace("Peer %s is disallowed from executing %s for device %s", peer, action, device); @@ -2136,37 +2219,39 @@ add_device_properties(const xmlNode *xml, remote_fencing_op_t *op, { xmlNode *child; int verified = 0; - device_properties_t *props = calloc(1, sizeof(device_properties_t)); + device_properties_t *props = + pcmk__assert_alloc(1, sizeof(device_properties_t)); int flags = st_device_supports_on; /* Old nodes that don't set the flag assume they support the on action */ /* Add a new entry to this peer's devices list */ - CRM_ASSERT(props != NULL); - g_hash_table_insert(peer->devices, strdup(device), props); + g_hash_table_insert(peer->devices, pcmk__str_copy(device), props); /* Peers with verified (monitored) access will be preferred */ - crm_element_value_int(xml, F_STONITH_DEVICE_VERIFIED, &verified); + crm_element_value_int(xml, PCMK__XA_ST_MONITOR_VERIFIED, &verified); if (verified) { crm_trace("Peer %s has confirmed a verified device %s", peer->host, device); props->verified = TRUE; } - crm_element_value_int(xml, F_STONITH_DEVICE_SUPPORT_FLAGS, &flags); + crm_element_value_int(xml, PCMK__XA_ST_DEVICE_SUPPORT_FLAGS, &flags); props->device_support_flags = flags; /* Parse action-specific device properties */ parse_action_specific(xml, peer->host, device, op_requested_action(op), op, st_phase_requested, props); - for (child = pcmk__xml_first_child(xml); child != NULL; - child = pcmk__xml_next(child)) { + for (child = pcmk__xe_first_child(xml, NULL, NULL, NULL); child != NULL; + child = pcmk__xe_next(child)) { /* Replies for "reboot" operations will include the action-specific * values for "off" and "on" in child elements, just in case the reboot * winds up getting remapped. */ - if (pcmk__str_eq(ID(child), PCMK_ACTION_OFF, pcmk__str_none)) { + if (pcmk__str_eq(pcmk__xe_id(child), PCMK_ACTION_OFF, pcmk__str_none)) { parse_action_specific(child, peer->host, device, PCMK_ACTION_OFF, op, st_phase_off, props); - } else if (pcmk__str_eq(ID(child), PCMK_ACTION_ON, pcmk__str_none)) { + + } else if (pcmk__str_eq(pcmk__xe_id(child), PCMK_ACTION_ON, + pcmk__str_none)) { parse_action_specific(child, peer->host, device, PCMK_ACTION_ON, op, st_phase_on, props); } @@ -2188,19 +2273,17 @@ static peer_device_info_t * add_result(remote_fencing_op_t *op, const char *host, int ndevices, const xmlNode *xml) { - peer_device_info_t *peer = calloc(1, sizeof(peer_device_info_t)); + peer_device_info_t *peer = pcmk__assert_alloc(1, + sizeof(peer_device_info_t)); xmlNode *child; - // cppcheck seems not to understand the abort logic in CRM_CHECK - // cppcheck-suppress memleak - CRM_CHECK(peer != NULL, return NULL); - peer->host = strdup(host); + peer->host = pcmk__str_copy(host); peer->devices = pcmk__strkey_table(free, free); /* Each child element describes one capable device available to the peer */ - for (child = pcmk__xml_first_child(xml); child != NULL; - child = pcmk__xml_next(child)) { - const char *device = ID(child); + for (child = pcmk__xe_first_child(xml, NULL, NULL, NULL); child != NULL; + child = pcmk__xe_next(child)) { + const char *device = pcmk__xe_id(child); if (device) { add_device_properties(child, op, peer, device); @@ -2241,16 +2324,16 @@ process_remote_stonith_query(xmlNode *msg) remote_fencing_op_t *op = NULL; peer_device_info_t *peer = NULL; uint32_t replies_expected; - xmlNode *dev = get_xpath_object("//@" F_STONITH_REMOTE_OP_ID, msg, LOG_ERR); + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_REMOTE_OP, msg, LOG_ERR); CRM_CHECK(dev != NULL, return -EPROTO); - id = crm_element_value(dev, F_STONITH_REMOTE_OP_ID); + id = crm_element_value(dev, PCMK__XA_ST_REMOTE_OP); CRM_CHECK(id != NULL, return -EPROTO); - dev = get_xpath_object("//@" F_STONITH_AVAILABLE_DEVICES, msg, LOG_ERR); + dev = get_xpath_object("//@" PCMK__XA_ST_AVAILABLE_DEVICES, msg, LOG_ERR); CRM_CHECK(dev != NULL, return -EPROTO); - crm_element_value_int(dev, F_STONITH_AVAILABLE_DEVICES, &ndevices); + crm_element_value_int(dev, PCMK__XA_ST_AVAILABLE_DEVICES, &ndevices); op = g_hash_table_lookup(stonith_remote_op_list, id); if (op == NULL) { @@ -2266,7 +2349,7 @@ process_remote_stonith_query(xmlNode *msg) if ((++op->replies >= replies_expected) && (op->state == st_query)) { have_all_replies = TRUE; } - host = crm_element_value(msg, F_ORIG); + host = crm_element_value(msg, PCMK__XA_SRC); host_is_target = pcmk__str_eq(host, op->target, pcmk__str_casei); crm_info("Query result %d of %d from %s for %s/%s (%d device%s) %s", @@ -2339,12 +2422,12 @@ fenced_process_fencing_reply(xmlNode *msg) const char *id = NULL; const char *device = NULL; remote_fencing_op_t *op = NULL; - xmlNode *dev = get_xpath_object("//@" F_STONITH_REMOTE_OP_ID, msg, LOG_ERR); + xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_REMOTE_OP, msg, LOG_ERR); pcmk__action_result_t result = PCMK__UNKNOWN_RESULT; CRM_CHECK(dev != NULL, return); - id = crm_element_value(dev, F_STONITH_REMOTE_OP_ID); + id = crm_element_value(dev, PCMK__XA_ST_REMOTE_OP); CRM_CHECK(id != NULL, return); dev = stonith__find_xe_with_result(msg); @@ -2352,7 +2435,7 @@ fenced_process_fencing_reply(xmlNode *msg) stonith__xe_get_result(dev, &result); - device = crm_element_value(dev, F_STONITH_DEVICE); + device = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID); if (stonith_remote_op_list) { op = g_hash_table_lookup(stonith_remote_op_list, id); @@ -2360,7 +2443,7 @@ fenced_process_fencing_reply(xmlNode *msg) if ((op == NULL) && pcmk__result_ok(&result)) { /* Record successful fencing operations */ - const char *client_id = crm_element_value(dev, F_STONITH_CLIENTID); + const char *client_id = crm_element_value(dev, PCMK__XA_ST_CLIENTID); op = create_remote_stonith_op(client_id, dev, TRUE); } @@ -2383,7 +2466,9 @@ fenced_process_fencing_reply(xmlNode *msg) return; } - if (pcmk__str_eq(crm_element_value(msg, F_SUBTYPE), "broadcast", pcmk__str_casei)) { + if (pcmk__str_eq(crm_element_value(msg, PCMK__XA_SUBT), + PCMK__VALUE_BROADCAST, pcmk__str_none)) { + if (pcmk__result_ok(&op->result)) { op->state = st_done; } else { @@ -2412,7 +2497,7 @@ fenced_process_fencing_reply(xmlNode *msg) return; } - device = crm_element_value(msg, F_STONITH_DEVICE); + device = crm_element_value(msg, PCMK__XA_ST_DEVICE_ID); if ((op->phase == 2) && !pcmk__result_ok(&op->result)) { /* A remapped "on" failed, but the node was already turned off diff --git a/daemons/fenced/fenced_scheduler.c b/daemons/fenced/fenced_scheduler.c index 27d990f..69e16fa 100644 --- a/daemons/fenced/fenced_scheduler.c +++ b/daemons/fenced/fenced_scheduler.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -124,14 +124,14 @@ register_if_fencing_device(gpointer data, gpointer user_data) if (rsc->children != NULL) { for (GList *iter = rsc->children; iter != NULL; iter = iter->next) { register_if_fencing_device(iter->data, NULL); - if (pe_rsc_is_clone(rsc)) { + if (pcmk__is_clone(rsc)) { return; // Only one instance needs to be checked for clones } } return; } - rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); + rclass = crm_element_value(rsc->xml, PCMK_XA_CLASS); if (!pcmk__str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) { return; // Not a fencing device } @@ -163,8 +163,7 @@ register_if_fencing_device(gpointer data, gpointer user_data) } // If device is in a group, check whether local node is allowed for group - if ((rsc->parent != NULL) - && (rsc->parent->variant == pcmk_rsc_variant_group)) { + if (pcmk__is_group(rsc->parent)) { pcmk_node_t *group_node = local_node_allowed_for(rsc->parent); if ((group_node != NULL) && (group_node->weight < 0)) { @@ -177,8 +176,12 @@ register_if_fencing_device(gpointer data, gpointer user_data) crm_debug("Reloading configuration of fencing device %s", rsc->id); - agent = crm_element_value(rsc->xml, XML_EXPR_ATTR_TYPE); + agent = crm_element_value(rsc->xml, PCMK_XA_TYPE); + /* @COMPAT Support for node attribute expressions in rules for resource + * meta-attributes is deprecated. When we can break behavioral backward + * compatibility, replace node with NULL here. + */ get_meta_attributes(rsc->meta, rsc, node, scheduler); rsc_provides = g_hash_table_lookup(rsc->meta, PCMK_STONITH_PROVIDES); diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index 7c69fb8..5ba97b5 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -22,7 +22,6 @@ #include <inttypes.h> // PRIu32, PRIx32 #include <crm/crm.h> -#include <crm/msg_xml.h> #include <crm/common/cmdline_internal.h> #include <crm/common/ipc.h> #include <crm/common/ipc_internal.h> @@ -42,7 +41,7 @@ #define SUMMARY "daemon for executing fencing devices in a Pacemaker cluster" char *stonith_our_uname = NULL; -long stonith_watchdog_timeout_ms = 0; +long long stonith_watchdog_timeout_ms = 0; GList *stonith_watchdog_targets = NULL; static GMainLoop *mainloop = NULL; @@ -75,11 +74,11 @@ st_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) if (stonith_shutdown_flag) { crm_info("Ignoring new client [%d] during shutdown", pcmk__client_pid(c)); - return -EPERM; + return -ECONNREFUSED; } if (pcmk__new_client(c, uid, gid) == NULL) { - return -EIO; + return -ENOMEM; } return 0; } @@ -102,34 +101,31 @@ st_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) request = pcmk__client_data2xml(c, data, &id, &flags); if (request == NULL) { - pcmk__ipc_send_ack(c, id, flags, "nack", NULL, CRM_EX_PROTOCOL); + pcmk__ipc_send_ack(c, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); return 0; } - op = crm_element_value(request, F_CRM_TASK); + op = crm_element_value(request, PCMK__XA_CRM_TASK); if(pcmk__str_eq(op, CRM_OP_RM_NODE_CACHE, pcmk__str_casei)) { - crm_xml_add(request, F_TYPE, T_STONITH_NG); - crm_xml_add(request, F_STONITH_OPERATION, op); - crm_xml_add(request, F_STONITH_CLIENTID, c->id); - crm_xml_add(request, F_STONITH_CLIENTNAME, pcmk__client_name(c)); - crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname); + crm_xml_add(request, PCMK__XA_T, PCMK__VALUE_STONITH_NG); + crm_xml_add(request, PCMK__XA_ST_OP, op); + crm_xml_add(request, PCMK__XA_ST_CLIENTID, c->id); + crm_xml_add(request, PCMK__XA_ST_CLIENTNAME, pcmk__client_name(c)); + crm_xml_add(request, PCMK__XA_ST_CLIENTNODE, stonith_our_uname); - send_cluster_message(NULL, crm_msg_stonith_ng, request, FALSE); + pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, request); free_xml(request); return 0; } if (c->name == NULL) { - const char *value = crm_element_value(request, F_STONITH_CLIENTNAME); + const char *value = crm_element_value(request, PCMK__XA_ST_CLIENTNAME); - if (value == NULL) { - value = "unknown"; - } - c->name = crm_strdup_printf("%s.%u", value, c->pid); + c->name = crm_strdup_printf("%s.%u", pcmk__s(value, "unknown"), c->pid); } - crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options); + crm_element_value_int(request, PCMK__XA_ST_CALLOPT, &call_options); crm_trace("Flags %#08" PRIx32 "/%#08x for command %" PRIu32 " from client %s", flags, call_options, id, pcmk__client_name(c)); @@ -139,9 +135,9 @@ st_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) c->request_id = id; /* Reply only to the last one */ } - crm_xml_add(request, F_STONITH_CLIENTID, c->id); - crm_xml_add(request, F_STONITH_CLIENTNAME, pcmk__client_name(c)); - crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname); + crm_xml_add(request, PCMK__XA_ST_CLIENTID, c->id); + crm_xml_add(request, PCMK__XA_ST_CLIENTNAME, pcmk__client_name(c)); + crm_xml_add(request, PCMK__XA_ST_CLIENTNODE, stonith_our_uname); crm_log_xml_trace(request, "ipc-received"); stonith_command(c, id, flags, request, NULL); @@ -177,10 +173,10 @@ st_ipc_destroy(qb_ipcs_connection_t * c) static void stonith_peer_callback(xmlNode * msg, void *private_data) { - const char *remote_peer = crm_element_value(msg, F_ORIG); - const char *op = crm_element_value(msg, F_STONITH_OPERATION); + const char *remote_peer = crm_element_value(msg, PCMK__XA_SRC); + const char *op = crm_element_value(msg, PCMK__XA_ST_OP); - if (pcmk__str_eq(op, "poke", pcmk__str_none)) { + if (pcmk__str_eq(op, STONITH_OP_POKE, pcmk__str_none)) { return; } @@ -197,20 +193,19 @@ stonith_peer_ais_callback(cpg_handle_t handle, uint32_t kind = 0; xmlNode *xml = NULL; const char *from = NULL; - char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from); + char *data = pcmk__cpg_message_data(handle, nodeid, pid, msg, &kind, &from); if(data == NULL) { return; } if (kind == crm_class_cluster) { - xml = string2xml(data); + xml = pcmk__xml_parse(data); if (xml == NULL) { crm_err("Invalid XML: '%.120s'", data); free(data); return; } - crm_xml_add(xml, F_ORIG, from); - /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */ + crm_xml_add(xml, PCMK__XA_SRC, from); stonith_peer_callback(xml, NULL); } @@ -257,7 +252,7 @@ do_local_reply(const xmlNode *notify_src, pcmk__client_t *client, uint64_t get_stonith_flag(const char *name) { - if (pcmk__str_eq(name, T_STONITH_NOTIFY_FENCE, pcmk__str_casei)) { + if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_FENCE, pcmk__str_none)) { return st_callback_notify_fence; } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_ADD, pcmk__str_casei)) { @@ -266,10 +261,12 @@ get_stonith_flag(const char *name) } else if (pcmk__str_eq(name, STONITH_OP_DEVICE_DEL, pcmk__str_casei)) { return st_callback_device_del; - } else if (pcmk__str_eq(name, T_STONITH_NOTIFY_HISTORY, pcmk__str_casei)) { + } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY, + pcmk__str_none)) { return st_callback_notify_history; - } else if (pcmk__str_eq(name, T_STONITH_NOTIFY_HISTORY_SYNCED, pcmk__str_casei)) { + } else if (pcmk__str_eq(name, PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED, + pcmk__str_none)) { return st_callback_notify_history_synced; } @@ -287,7 +284,7 @@ stonith_notify_client(gpointer key, gpointer value, gpointer user_data) CRM_CHECK(client != NULL, return); CRM_CHECK(update_msg != NULL, return); - type = crm_element_value(update_msg, F_SUBTYPE); + type = crm_element_value(update_msg, PCMK__XA_SUBT); CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return); if (client->ipcs == NULL) { @@ -325,10 +322,10 @@ do_stonith_async_timeout_update(const char *client_id, const char *call_id, int return; } - notify_data = create_xml_node(NULL, T_STONITH_TIMEOUT_VALUE); - crm_xml_add(notify_data, F_TYPE, T_STONITH_TIMEOUT_VALUE); - crm_xml_add(notify_data, F_STONITH_CALLID, call_id); - crm_xml_add_int(notify_data, F_STONITH_TIMEOUT, timeout); + notify_data = pcmk__xe_create(NULL, PCMK__XE_ST_ASYNC_TIMEOUT_VALUE); + crm_xml_add(notify_data, PCMK__XA_T, PCMK__VALUE_ST_ASYNC_TIMEOUT_VALUE); + crm_xml_add(notify_data, PCMK__XA_ST_CALLID, call_id); + crm_xml_add_int(notify_data, PCMK__XA_ST_TIMEOUT, timeout); crm_trace("timeout update is %d for client %s and call id %s", timeout, client_id, call_id); @@ -352,17 +349,19 @@ fenced_send_notification(const char *type, const pcmk__action_result_t *result, xmlNode *data) { /* TODO: Standardize the contents of data */ - xmlNode *update_msg = create_xml_node(NULL, "notify"); + xmlNode *update_msg = pcmk__xe_create(NULL, PCMK__XE_NOTIFY); CRM_LOG_ASSERT(type != NULL); - crm_xml_add(update_msg, F_TYPE, T_STONITH_NOTIFY); - crm_xml_add(update_msg, F_SUBTYPE, type); - crm_xml_add(update_msg, F_STONITH_OPERATION, type); + crm_xml_add(update_msg, PCMK__XA_T, PCMK__VALUE_ST_NOTIFY); + crm_xml_add(update_msg, PCMK__XA_SUBT, type); + crm_xml_add(update_msg, PCMK__XA_ST_OP, type); stonith__xe_set_result(update_msg, result); if (data != NULL) { - add_message_xml(update_msg, F_STONITH_CALLDATA, data); + xmlNode *wrapper = pcmk__xe_create(update_msg, PCMK__XE_ST_CALLDATA); + + pcmk__xml_copy(wrapper, data); } crm_trace("Notifying clients"); @@ -375,60 +374,25 @@ fenced_send_notification(const char *type, const pcmk__action_result_t *result, * \internal * \brief Send notifications for a configuration change to subscribed clients * - * \param[in] op Notification type (STONITH_OP_DEVICE_ADD, - * STONITH_OP_DEVICE_DEL, STONITH_OP_LEVEL_ADD, or - * STONITH_OP_LEVEL_DEL) - * \param[in] result Operation result - * \param[in] desc Description of what changed - * \param[in] active Current number of devices or topologies in use - */ -static void -send_config_notification(const char *op, const pcmk__action_result_t *result, - const char *desc, int active) -{ - xmlNode *notify_data = create_xml_node(NULL, op); - - CRM_CHECK(notify_data != NULL, return); - - crm_xml_add(notify_data, F_STONITH_DEVICE, desc); - crm_xml_add_int(notify_data, F_STONITH_ACTIVE, active); - - fenced_send_notification(op, result, notify_data); - free_xml(notify_data); -} - -/*! - * \internal - * \brief Send notifications for a device change to subscribed clients - * - * \param[in] op Notification type (STONITH_OP_DEVICE_ADD or - * STONITH_OP_DEVICE_DEL) + * \param[in] op Notification type (\c STONITH_OP_DEVICE_ADD, + * \c STONITH_OP_DEVICE_DEL, \c STONITH_OP_LEVEL_ADD, or + * \c STONITH_OP_LEVEL_DEL) * \param[in] result Operation result - * \param[in] desc ID of device that changed + * \param[in] desc Description of what changed (either device ID or string + * representation of level + * (<tt><target>[<level_index>]</tt>)) */ void -fenced_send_device_notification(const char *op, +fenced_send_config_notification(const char *op, const pcmk__action_result_t *result, const char *desc) { - send_config_notification(op, result, desc, g_hash_table_size(device_list)); -} + xmlNode *notify_data = pcmk__xe_create(NULL, op); -/*! - * \internal - * \brief Send notifications for a topology level change to subscribed clients - * - * \param[in] op Notification type (STONITH_OP_LEVEL_ADD or - * STONITH_OP_LEVEL_DEL) - * \param[in] result Operation result - * \param[in] desc String representation of level (<target>[<level_index>]) - */ -void -fenced_send_level_notification(const char *op, - const pcmk__action_result_t *result, - const char *desc) -{ - send_config_notification(op, result, desc, g_hash_table_size(topology)); + crm_xml_add(notify_data, PCMK__XA_ST_DEVICE_ID, desc); + + fenced_send_notification(op, result, notify_data); + free_xml(notify_data); } /*! @@ -466,7 +430,7 @@ stonith_cleanup(void) qb_ipcs_destroy(ipcs); } - crm_peer_destroy(); + pcmk__cluster_destroy_node_caches(); pcmk__client_cleanup(); free_stonith_remote_op_list(); free_topology_list(); @@ -512,221 +476,34 @@ st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void * This is a hack until we can send to a nodeid and/or we fix node name lookups * These messages are ignored in stonith_peer_callback() */ - xmlNode *query = create_xml_node(NULL, "stonith_command"); + xmlNode *query = pcmk__xe_create(NULL, PCMK__XE_STONITH_COMMAND); - crm_xml_add(query, F_XML_TAGNAME, "stonith_command"); - crm_xml_add(query, F_TYPE, T_STONITH_NG); - crm_xml_add(query, F_STONITH_OPERATION, "poke"); + crm_xml_add(query, PCMK__XA_T, PCMK__VALUE_STONITH_NG); + crm_xml_add(query, PCMK__XA_ST_OP, STONITH_OP_POKE); crm_debug("Broadcasting our uname because of node %u", node->id); - send_cluster_message(NULL, crm_msg_stonith_ng, query, FALSE); + pcmk__cluster_send_message(NULL, crm_msg_stonith_ng, query); free_xml(query); } } -static pcmk__cluster_option_t fencer_options[] = { - /* name, old name, type, allowed values, - * default value, validator, - * short description, - * long description - */ - { - PCMK_STONITH_HOST_ARGUMENT, NULL, "string", NULL, "port", NULL, - N_("Advanced use only: An alternate parameter to supply instead of 'port'"), - N_("some devices do not support the " - "standard 'port' parameter or may provide additional ones. Use " - "this to specify an alternate, device-specific, parameter " - "that should indicate the machine to be fenced. A value of " - "none can be used to tell the cluster not to supply any " - "additional parameters.") - }, - { - PCMK_STONITH_HOST_MAP,NULL, "string", NULL, "", NULL, - N_("A mapping of host names to ports numbers for devices that do not support host names."), - N_("Eg. node1:1;node2:2,3 would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2") - }, - { - PCMK_STONITH_HOST_LIST,NULL, "string", NULL, "", NULL, - N_("Eg. node1,node2,node3"), - N_("A list of machines controlled by " - "this device (Optional unless pcmk_host_list=static-list)") - }, - { - PCMK_STONITH_HOST_CHECK,NULL, "string", NULL, "dynamic-list", NULL, - N_("How to determine which machines are controlled by the device."), - N_("Allowed values: dynamic-list " - "(query the device via the 'list' command), static-list " - "(check the pcmk_host_list attribute), status " - "(query the device via the 'status' command), " - "none (assume every device can fence every " - "machine)") - }, - { - PCMK_STONITH_DELAY_MAX,NULL, "time", NULL, "0s", NULL, - N_("Enable a base delay for fencing actions and specify base delay value."), - N_("Enable a delay of no more than the " - "time specified before executing fencing actions. Pacemaker " - "derives the overall delay by taking the value of " - "pcmk_delay_base and adding a random delay value such " - "that the sum is kept below this maximum.") - }, - { - PCMK_STONITH_DELAY_BASE,NULL, "string", NULL, "0s", NULL, - N_("Enable a base delay for " - "fencing actions and specify base delay value."), - N_("This enables a static delay for " - "fencing actions, which can help avoid \"death matches\" where " - "two nodes try to fence each other at the same time. If " - "pcmk_delay_max is also used, a random delay will be " - "added such that the total delay is kept below that value." - "This can be set to a single time value to apply to any node " - "targeted by this device (useful if a separate device is " - "configured for each target), or to a node map (for example, " - "\"node1:1s;node2:5\") to set a different value per target.") - }, - { - PCMK_STONITH_ACTION_LIMIT,NULL, "integer", NULL, "1", NULL, - N_("The maximum number of actions can be performed in parallel on this device"), - N_("Cluster property concurrent-fencing=true needs to be configured first." - "Then use this to specify the maximum number of actions can be performed in parallel on this device. -1 is unlimited.") - }, - { - "pcmk_reboot_action", NULL, "string", NULL, - PCMK_ACTION_REBOOT, NULL, - N_("Advanced use only: An alternate command to run instead of 'reboot'"), - N_("Some devices do not support the standard commands or may provide additional ones.\n" - "Use this to specify an alternate, device-specific, command that implements the \'reboot\' action.") - }, - { - "pcmk_reboot_timeout",NULL, "time", NULL, "60s", NULL, - N_("Advanced use only: Specify an alternate timeout to use for reboot actions instead of stonith-timeout"), - N_("Some devices need much more/less time to complete than normal." - "Use this to specify an alternate, device-specific, timeout for \'reboot\' actions.") - }, - { - "pcmk_reboot_retries",NULL, "integer", NULL, "2", NULL, - N_("Advanced use only: The maximum number of times to retry the 'reboot' command within the timeout period"), - N_("Some devices do not support multiple connections." - " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." - " Use this option to alter the number of times Pacemaker retries \'reboot\' actions before giving up.") - }, - { - "pcmk_off_action", NULL, "string", NULL, - PCMK_ACTION_OFF, NULL, - N_("Advanced use only: An alternate command to run instead of \'off\'"), - N_("Some devices do not support the standard commands or may provide additional ones." - "Use this to specify an alternate, device-specific, command that implements the \'off\' action.") - }, - { - "pcmk_off_timeout",NULL, "time", NULL, "60s", NULL, - N_("Advanced use only: Specify an alternate timeout to use for off actions instead of stonith-timeout"), - N_("Some devices need much more/less time to complete than normal." - "Use this to specify an alternate, device-specific, timeout for \'off\' actions.") - }, - { - "pcmk_off_retries",NULL, "integer", NULL, "2", NULL, - N_("Advanced use only: The maximum number of times to retry the 'off' command within the timeout period"), - N_("Some devices do not support multiple connections." - " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." - " Use this option to alter the number of times Pacemaker retries \'off\' actions before giving up.") - }, - { - "pcmk_on_action", NULL, "string", NULL, - PCMK_ACTION_ON, NULL, - N_("Advanced use only: An alternate command to run instead of 'on'"), - N_("Some devices do not support the standard commands or may provide additional ones." - "Use this to specify an alternate, device-specific, command that implements the \'on\' action.") - }, - { - "pcmk_on_timeout",NULL, "time", NULL, "60s", NULL, - N_("Advanced use only: Specify an alternate timeout to use for on actions instead of stonith-timeout"), - N_("Some devices need much more/less time to complete than normal." - "Use this to specify an alternate, device-specific, timeout for \'on\' actions.") - }, - { - "pcmk_on_retries",NULL, "integer", NULL, "2", NULL, - N_("Advanced use only: The maximum number of times to retry the 'on' command within the timeout period"), - N_("Some devices do not support multiple connections." - " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." - " Use this option to alter the number of times Pacemaker retries \'on\' actions before giving up.") - }, - { - "pcmk_list_action",NULL, "string", NULL, - PCMK_ACTION_LIST, NULL, - N_("Advanced use only: An alternate command to run instead of \'list\'"), - N_("Some devices do not support the standard commands or may provide additional ones." - "Use this to specify an alternate, device-specific, command that implements the \'list\' action.") - }, - { - "pcmk_list_timeout",NULL, "time", NULL, "60s", NULL, - N_("Advanced use only: Specify an alternate timeout to use for list actions instead of stonith-timeout"), - N_("Some devices need much more/less time to complete than normal." - "Use this to specify an alternate, device-specific, timeout for \'list\' actions.") - }, - { - "pcmk_list_retries",NULL, "integer", NULL, "2", NULL, - N_("Advanced use only: The maximum number of times to retry the \'list\' command within the timeout period"), - N_("Some devices do not support multiple connections." - " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." - " Use this option to alter the number of times Pacemaker retries \'list\' actions before giving up.") - }, - { - "pcmk_monitor_action", NULL, "string", NULL, - PCMK_ACTION_MONITOR, NULL, - N_("Advanced use only: An alternate command to run instead of \'monitor\'"), - N_("Some devices do not support the standard commands or may provide additional ones." - "Use this to specify an alternate, device-specific, command that implements the \'monitor\' action.") - }, - { - "pcmk_monitor_timeout",NULL, "time", NULL, "60s", NULL, - N_("Advanced use only: Specify an alternate timeout to use for monitor actions instead of stonith-timeout"), - N_("Some devices need much more/less time to complete than normal.\n" - "Use this to specify an alternate, device-specific, timeout for \'monitor\' actions.") - }, - { - "pcmk_monitor_retries",NULL, "integer", NULL, "2", NULL, - N_("Advanced use only: The maximum number of times to retry the \'monitor\' command within the timeout period"), - N_("Some devices do not support multiple connections." - " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." - " Use this option to alter the number of times Pacemaker retries \'monitor\' actions before giving up.") - }, - { - "pcmk_status_action", NULL, "string", NULL, - PCMK_ACTION_STATUS, NULL, - N_("Advanced use only: An alternate command to run instead of \'status\'"), - N_("Some devices do not support the standard commands or may provide additional ones." - "Use this to specify an alternate, device-specific, command that implements the \'status\' action.") - }, - { - "pcmk_status_timeout",NULL, "time", NULL, "60s", NULL, - N_("Advanced use only: Specify an alternate timeout to use for status actions instead of stonith-timeout"), - N_("Some devices need much more/less time to complete than normal." - "Use this to specify an alternate, device-specific, timeout for \'status\' actions.") - }, - { - "pcmk_status_retries",NULL, "integer", NULL, "2", NULL, - N_("Advanced use only: The maximum number of times to retry the \'status\' command within the timeout period"), - N_("Some devices do not support multiple connections." - " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." - " Use this option to alter the number of times Pacemaker retries \'status\' actions before giving up.") - }, -}; - -void +/* @COMPAT Deprecated since 2.1.8. Use pcmk_list_fence_attrs() or + * crm_resource --list-options=fencing instead of querying daemon metadata. + */ +static int fencer_metadata(void) { + const char *name = "pacemaker-fenced"; const char *desc_short = N_("Instance attributes available for all " - "\"stonith\"-class resources"); - const char *desc_long = N_("Instance attributes available for all \"stonith\"-" - "class resources and used by Pacemaker's fence " - "daemon, formerly known as stonithd"); - - gchar *s = pcmk__format_option_metadata("pacemaker-fenced", desc_short, - desc_long, fencer_options, - PCMK__NELEM(fencer_options)); - printf("%s", s); - g_free(s); + "\"stonith\"-class resources"); + const char *desc_long = N_("Instance attributes available for all " + "\"stonith\"-class resources and used by " + "Pacemaker's fence daemon, formerly known as " + "stonithd"); + + return pcmk__daemon_metadata(out, name, desc_short, desc_long, + pcmk__opt_fencing); } static GOptionEntry entries[] = { @@ -747,8 +524,7 @@ build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) { GOptionContext *context = NULL; - context = pcmk__build_arg_context(args, "text (default), xml", group, - "[metadata]"); + context = pcmk__build_arg_context(args, "text (default), xml", group, NULL); pcmk__add_main_args(context, entries); return context; } @@ -757,7 +533,7 @@ int main(int argc, char **argv) { int rc = pcmk_rc_ok; - crm_cluster_t *cluster = NULL; + pcmk_cluster_t *cluster = NULL; crm_ipc_t *old_instance = NULL; GError *error = NULL; @@ -791,7 +567,13 @@ main(int argc, char **argv) if ((g_strv_length(processed_args) >= 2) && pcmk__str_eq(processed_args[1], "metadata", pcmk__str_none)) { - fencer_metadata(); + + rc = fencer_metadata(); + if (rc != pcmk_rc_ok) { + exit_code = CRM_EX_FATAL; + g_set_error(&error, PCMK__EXITC_ERROR, exit_code, + "Unable to display metadata: %s", pcmk_rc_str(rc)); + } goto done; } @@ -826,7 +608,7 @@ main(int argc, char **argv) mainloop_add_signal(SIGTERM, stonith_shutdown); - crm_peer_init(); + pcmk__cluster_init_node_caches(); rc = fenced_scheduler_init(); if (rc != pcmk_rc_ok) { @@ -840,16 +622,16 @@ main(int argc, char **argv) if (!stand_alone) { #if SUPPORT_COROSYNC - if (is_corosync_cluster()) { - cluster->destroy = stonith_peer_cs_destroy; - cluster->cpg.cpg_deliver_fn = stonith_peer_ais_callback; - cluster->cpg.cpg_confchg_fn = pcmk_cpg_membership; + if (pcmk_get_cluster_layer() == pcmk_cluster_layer_corosync) { + pcmk_cluster_set_destroy_fn(cluster, stonith_peer_cs_destroy); + pcmk_cpg_set_deliver_fn(cluster, stonith_peer_ais_callback); + pcmk_cpg_set_confchg_fn(cluster, pcmk__cpg_confchg_cb); } #endif // SUPPORT_COROSYNC - crm_set_status_callback(&st_peer_update_callback); + pcmk__cluster_set_status_callback(&st_peer_update_callback); - if (crm_cluster_connect(cluster) == FALSE) { + if (pcmk_cluster_connect(cluster) != pcmk_rc_ok) { exit_code = CRM_EX_FATAL; crm_crit("Cannot sign in to the cluster... terminating"); goto done; diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h index 220978a..2d8047c 100644 --- a/daemons/fenced/pacemaker-fenced.h +++ b/daemons/fenced/pacemaker-fenced.h @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * This source code is licensed under the GNU General Public License version 2 * or later (GPLv2+) WITHOUT ANY WARRANTY. @@ -111,8 +111,8 @@ typedef struct remote_fencing_op_s { /*! * Fencing delay (in seconds) requested by API client (used by controller to - * implement priority-fencing-delay). A value of -1 means disable all - * configured delays. + * implement \c PCMK_OPT_PRIORITY_FENCING_DELAY). A value of -1 means + * disable all configured delays. */ int client_delay; @@ -253,12 +253,9 @@ void void fenced_send_notification(const char *type, const pcmk__action_result_t *result, xmlNode *data); -void fenced_send_device_notification(const char *op, +void fenced_send_config_notification(const char *op, const pcmk__action_result_t *result, const char *desc); -void fenced_send_level_notification(const char *op, - const pcmk__action_result_t *result, - const char *desc); remote_fencing_op_t *initiate_remote_stonith_op(const pcmk__client_t *client, xmlNode *request, @@ -281,7 +278,6 @@ void set_fencing_completed(remote_fencing_op_t * op); int fenced_handle_manual_confirmation(const pcmk__client_t *client, xmlNode *msg); -void fencer_metadata(void); const char *fenced_device_reboot_action(const char *device_id); bool fenced_device_supports_on(const char *device_id); @@ -327,7 +323,7 @@ extern char *stonith_our_uname; extern gboolean stand_alone; extern GHashTable *device_list; extern GHashTable *topology; -extern long stonith_watchdog_timeout_ms; +extern long long stonith_watchdog_timeout_ms; extern GList *stonith_watchdog_targets; extern GHashTable *stonith_remote_op_list; extern crm_exit_t exit_code; |