diff --git a/attrd/attrd_common.c b/attrd/attrd_common.c index 3a1ee33ded7..2437c017c6d 100644 --- a/attrd/attrd_common.c +++ b/attrd/attrd_common.c @@ -248,13 +248,16 @@ attrd_expand_value(const char *value, const char *old_value) * * \param[out] regex Where to store created regular expression * \param[in] rsc Name of resource to clear (or NULL for all) + * \param[in] op Operation to clear if rsc is specified (or NULL for all) + * \param[in] interval Interval of operation to clear if op is specified * * \return pcmk_ok on success, -EINVAL if arguments are invalid * * \note The caller is responsible for freeing the result with regfree(). */ int -attrd_failure_regex(regex_t *regex, const char *rsc) +attrd_failure_regex(regex_t *regex, const char *rsc, const char *op, + int interval) { char *pattern = NULL; int rc; @@ -263,8 +266,11 @@ attrd_failure_regex(regex_t *regex, const char *rsc) if (rsc == NULL) { pattern = strdup(ATTRD_RE_CLEAR_ALL); - } else { + } else if (op == NULL) { pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc); + } else { + pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP, + rsc, op, interval); } /* Compile pattern into regular expression */ diff --git a/attrd/attrd_common.h b/attrd/attrd_common.h index 4c8fd90604e..d535bb0bf1d 100644 --- a/attrd/attrd_common.h +++ b/attrd/attrd_common.h @@ -27,7 +27,7 @@ int attrd_expand_value(const char *value, const char *old_value); #define ATTRD_RE_CLEAR_ALL \ "^(" CRM_FAIL_COUNT_PREFIX "|" CRM_LAST_FAILURE_PREFIX ")-" -/* regular expression to clear failure of one resource +/* regular expression to clear failure of all operations for one resource * (format takes resource name) * * @COMPAT attributes set < 1.1.17: @@ -35,6 +35,15 @@ int attrd_expand_value(const char *value, const char *old_value); */ #define ATTRD_RE_CLEAR_ONE ATTRD_RE_CLEAR_ALL "%s(#.+_[0-9]+)?$" -int attrd_failure_regex(regex_t *regex, const char *rsc); +/* regular expression to clear failure of one operation for one resource + * (format takes resource name, operation name, and interval) + * + * @COMPAT attributes set < 1.1.17: + * also match older attributes that do not have the operation part + */ +#define ATTRD_RE_CLEAR_OP ATTRD_RE_CLEAR_ALL "%s(#%s_%d)?$" + +int attrd_failure_regex(regex_t *regex, const char *rsc, const char *op, + int interval); #endif /* PCMK_ATTRD_COMMON__H */ diff --git a/attrd/commands.c b/attrd/commands.c index 332732393ae..486efb66496 100644 --- a/attrd/commands.c +++ b/attrd/commands.c @@ -333,13 +333,26 @@ attrd_client_clear_failure(xmlNode *xml) #endif const char *rsc = crm_element_value(xml, F_ATTRD_RESOURCE); + const char *op = crm_element_value(xml, F_ATTRD_OPERATION); + const char *interval_s = crm_element_value(xml, F_ATTRD_INTERVAL); - /* Map this to an update that uses a regular expression */ + /* Map this to an update */ crm_xml_add(xml, F_ATTRD_TASK, ATTRD_OP_UPDATE); - /* Add expression matching one or all resources as appropriate */ + /* Add regular expression matching desired attributes */ + if (rsc) { - char *pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc); + char *pattern; + + if (op == NULL) { + pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc); + + } else { + int interval = crm_get_interval(interval_s); + + pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP, + rsc, op, interval); + } crm_xml_add(xml, F_ATTRD_REGEX, pattern); free(pattern); @@ -508,11 +521,14 @@ attrd_peer_clear_failure(crm_node_t *peer, xmlNode *xml) { const char *rsc = crm_element_value(xml, F_ATTRD_RESOURCE); const char *host = crm_element_value(xml, F_ATTRD_HOST); + const char *op = crm_element_value(xml, F_ATTRD_OPERATION); + const char *interval_s = crm_element_value(xml, F_ATTRD_INTERVAL); + int interval = crm_get_interval(interval_s); char *attr = NULL; GHashTableIter iter; regex_t regex; - if (attrd_failure_regex(®ex, rsc) != pcmk_ok) { + if (attrd_failure_regex(®ex, rsc, op, interval) != pcmk_ok) { crm_info("Ignoring invalid request to clear failures for %s", (rsc? rsc : "all resources")); return; diff --git a/attrd/legacy.c b/attrd/legacy.c index f7c235363c8..64fef6e0204 100644 --- a/attrd/legacy.c +++ b/attrd/legacy.c @@ -239,11 +239,14 @@ local_clear_failure(xmlNode *xml) { const char *rsc = crm_element_value(xml, F_ATTRD_RESOURCE); const char *what = rsc? rsc : "all resources"; + const char *op = crm_element_value(xml, F_ATTRD_OPERATION); + const char *interval_s = crm_element_value(xml, F_ATTRD_INTERVAL); + int interval = crm_get_interval(interval_s); regex_t regex; GHashTableIter iter; attr_hash_entry_t *hash_entry = NULL; - if (attrd_failure_regex(®ex, rsc) != pcmk_ok) { + if (attrd_failure_regex(®ex, rsc, op, interval) != pcmk_ok) { crm_info("Ignoring invalid request to clear %s", (rsc? rsc : "all resources")); return; @@ -298,8 +301,10 @@ remote_clear_callback(xmlNode *msg, int call_id, int rc, xmlNode *output, "[" XPATH_NAME_START(CRM_FAIL_COUNT_PREFIX "-") \ " or " XPATH_NAME_START(CRM_LAST_FAILURE_PREFIX "-") "]" -/* xpath ending to clear one resource (format takes resource name x 4) */ -/* @COMPAT attributes set < 1.1.17: +/* xpath ending to clear all operations for one resource + * (format takes resource name x 4) + * + * @COMPAT attributes set < 1.1.17: * also match older attributes that do not have the operation part */ #define XPATH_CLEAR_ONE \ @@ -308,6 +313,18 @@ remote_clear_callback(xmlNode *msg, int call_id, int rc, xmlNode *output, " or " XPATH_NAME_START(CRM_FAIL_COUNT_PREFIX "-%s#") \ " or " XPATH_NAME_START(CRM_LAST_FAILURE_PREFIX "-%s#") "]" +/* xpath ending to clear one operation for one resource + * (format takes resource name x 2, resource name + operation + interval x 2) + * + * @COMPAT attributes set < 1.1.17: + * also match older attributes that do not have the operation part + */ +#define XPATH_CLEAR_OP \ + "[" XPATH_NAME_IS(CRM_FAIL_COUNT_PREFIX "-%s") \ + " or " XPATH_NAME_IS(CRM_LAST_FAILURE_PREFIX "-%s") \ + " or " XPATH_NAME_IS(CRM_FAIL_COUNT_PREFIX "-%s#%s_%d") \ + " or " XPATH_NAME_IS(CRM_LAST_FAILURE_PREFIX "-%s#%s_%d") "]" + /*! * \internal * \brief Clear failure-related attributes for Pacemaker Remote node(s) @@ -319,6 +336,7 @@ remote_clear_failure(xmlNode *xml) { const char *rsc = crm_element_value(xml, F_ATTRD_RESOURCE); const char *host = crm_element_value(xml, F_ATTRD_HOST); + const char *op = crm_element_value(xml, F_ATTRD_OPERATION); int rc = pcmk_ok; char *xpath; @@ -329,18 +347,44 @@ remote_clear_failure(xmlNode *xml) return; } - if ((rsc == NULL) && (host == NULL)) { - xpath = crm_strdup_printf(XPATH_REMOTE_ATTR("") XPATH_CLEAR_ALL); + /* Build an xpath to clear appropriate attributes */ + + if (rsc == NULL) { + /* No resource specified, clear all resources */ + + if (host == NULL) { + xpath = crm_strdup_printf(XPATH_REMOTE_ATTR("") XPATH_CLEAR_ALL); + } else { + xpath = crm_strdup_printf(XPATH_REMOTE_ATTR(XPATH_ID) XPATH_CLEAR_ALL, + host); + } + + } else if (op == NULL) { + /* Resource but no operation specified, clear all operations */ + + if (host == NULL) { + xpath = crm_strdup_printf(XPATH_REMOTE_ATTR("") XPATH_CLEAR_ONE, + rsc, rsc, rsc, rsc); + } else { + xpath = crm_strdup_printf(XPATH_REMOTE_ATTR(XPATH_ID) XPATH_CLEAR_ONE, + host, rsc, rsc, rsc, rsc); + } - } else if (rsc == NULL) { - xpath = crm_strdup_printf(XPATH_REMOTE_ATTR(XPATH_ID) XPATH_CLEAR_ALL, - host); - } else if (host == NULL) { - xpath = crm_strdup_printf(XPATH_REMOTE_ATTR("") XPATH_CLEAR_ONE, - rsc, rsc, rsc, rsc); } else { - xpath = crm_strdup_printf(XPATH_REMOTE_ATTR(XPATH_ID) XPATH_CLEAR_ONE, - host, rsc, rsc, rsc, rsc); + /* Resource and operation specified */ + + const char *interval_s = crm_element_value(xml, F_ATTRD_INTERVAL); + int interval = crm_get_interval(interval_s); + + if (host == NULL) { + xpath = crm_strdup_printf(XPATH_REMOTE_ATTR("") XPATH_CLEAR_OP, + rsc, rsc, rsc, op, interval, + rsc, op, interval); + } else { + xpath = crm_strdup_printf(XPATH_REMOTE_ATTR(XPATH_ID) XPATH_CLEAR_OP, + host, rsc, rsc, rsc, op, interval, + rsc, op, interval); + } } crm_trace("Clearing attributes matching %s", xpath); diff --git a/crmd/attrd.c b/crmd/attrd.c index 7467a3c6293..ae38a111180 100644 --- a/crmd/attrd.c +++ b/crmd/attrd.c @@ -83,7 +83,7 @@ update_attrd_helper(const char *host, const char *name, const char *value, XML_CIB_TAG_STATUS, NULL, NULL, user_name, attrd_opts); } else { - rc = attrd_clear_delegate(attrd_ipc, host, name, + rc = attrd_clear_delegate(attrd_ipc, host, name, NULL, NULL, user_name, attrd_opts); } diff --git a/include/crm/attrd.h b/include/crm/attrd.h index 43b3a2ae4e2..e294838eb89 100644 --- a/include/crm/attrd.h +++ b/include/crm/attrd.h @@ -28,6 +28,7 @@ int attrd_update_delegate(crm_ipc_t * ipc, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen, const char *user_name, int options); int attrd_clear_delegate(crm_ipc_t *ipc, const char *host, const char *resource, + const char *operation, const char *interval, const char *user_name, int options); #endif diff --git a/include/crm_internal.h b/include/crm_internal.h index 060902d6c9b..a498bcbbdb4 100644 --- a/include/crm_internal.h +++ b/include/crm_internal.h @@ -276,6 +276,8 @@ long crm_read_pidfile(const char *filename); # define F_ATTRD_WRITER "attr_writer" # define F_ATTRD_VERSION "attr_version" # define F_ATTRD_RESOURCE "attr_resource" +# define F_ATTRD_OPERATION "attr_clear_operation" +# define F_ATTRD_INTERVAL "attr_clear_interval" /* attrd operations */ # define ATTRD_OP_PEER_REMOVE "peer-remove" diff --git a/lib/common/attrd_client.c b/lib/common/attrd_client.c index 511fb6a81b7..f594c125b83 100644 --- a/lib/common/attrd_client.c +++ b/lib/common/attrd_client.c @@ -234,6 +234,7 @@ attrd_update_delegate(crm_ipc_t *ipc, char command, const char *host, */ int attrd_clear_delegate(crm_ipc_t *ipc, const char *host, const char *resource, + const char *operation, const char *interval, const char *user_name, int options) { int rc = pcmk_ok; @@ -242,12 +243,16 @@ attrd_clear_delegate(crm_ipc_t *ipc, const char *host, const char *resource, crm_xml_add(clear_op, F_ATTRD_TASK, ATTRD_OP_CLEAR_FAILURE); crm_xml_add(clear_op, F_ATTRD_HOST, host); crm_xml_add(clear_op, F_ATTRD_RESOURCE, resource); + crm_xml_add(clear_op, F_ATTRD_OPERATION, operation); + crm_xml_add(clear_op, F_ATTRD_INTERVAL, interval); crm_xml_add_int(clear_op, F_ATTRD_IS_REMOTE, is_set(options, attrd_opt_remote)); rc = send_attrd_op(ipc, clear_op); free_xml(clear_op); - crm_debug("Asked attrd to clear failure of %s on %s: %s (%d)", + crm_debug("Asked attrd to clear failure of %s (interval %s) for %s on %s: %s (%d)", + (operation? operation : "all operations"), + (interval? interval : "0"), (resource? resource : "all resources"), (host? host : "all nodes"), pcmk_strerror(rc), rc); return rc; diff --git a/tools/crm_resource.c b/tools/crm_resource.c index 4184ba800de..f17bca363c0 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -999,7 +999,8 @@ main(int argc, char **argv) crm_debug("Re-checking the state of all resources on %s", host_uname?host_uname:"all nodes"); - rc = attrd_clear_delegate(NULL, host_uname, NULL, NULL, attr_options); + rc = attrd_clear_delegate(NULL, host_uname, NULL, NULL, NULL, NULL, + attr_options); if (crm_ipc_send(crmd_channel, cmd, 0, 0, NULL) > 0) { start_mainloop(); diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index e4aed5133c9..4deab2beaa4 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -667,7 +667,8 @@ cli_resource_delete(cib_t *cib_conn, crm_ipc_t * crmd_channel, const char *host_ if (is_remote_node(node)) { attr_options |= attrd_opt_remote; } - rc = attrd_clear_delegate(NULL, host_uname, rsc_name, NULL, attr_options); + rc = attrd_clear_delegate(NULL, host_uname, rsc_name, NULL, NULL, + NULL, attr_options); if (rc != pcmk_ok) { printf("Cleaned %s history on %s, but unable to clear failures: %s\n", rsc->id, host_uname, pcmk_strerror(rc));