From 94a4c58f675d163085a055f59fd6c3a2c9f57c43 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 27 Feb 2017 14:17:01 -0600 Subject: [PATCH 01/10] Fix: libservices: ensure completed ops aren't on blocked ops list This refactors removal of a completed operation from the in-flight ops list into a new internal function services_untrack_op(), which allows the in-flight ops list and handle_blocked_ops() to be static to services.c. The new function also ensures the op isn't on the blocked ops list, which could otherwise result in a use-after-free bug. --- lib/services/services.c | 23 +++++++++++++++++++++-- lib/services/services_linux.c | 7 +------ lib/services/services_private.h | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/services/services.c b/lib/services/services.c index 0b535e6..90a2181 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -44,7 +44,9 @@ static GHashTable *recurring_actions = NULL; static GList *blocked_ops = NULL; /* ops currently active (in-flight) */ -GList *inflight_ops = NULL; +static GList *inflight_ops = NULL; + +static void handle_blocked_ops(void); svc_action_t * services_action_create(const char *name, const char *action, int interval, int timeout) @@ -605,6 +607,23 @@ services_add_inflight_op(svc_action_t * op) } } +/*! + * \internal + * \brief Stop tracking an operation that completed + * + * \param[in] op Operation to stop tracking + */ +void +services_untrack_op(svc_action_t *op) +{ + /* Op is no longer in-flight or blocked */ + inflight_ops = g_list_remove(inflight_ops, op); + blocked_ops = g_list_remove(blocked_ops, op); + + /* Op is no longer blocking other ops, so check if any need to run */ + handle_blocked_ops(); +} + gboolean services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *)) { @@ -649,7 +668,7 @@ is_op_blocked(const char *rsc) return FALSE; } -void +static void handle_blocked_ops(void) { GList *executed_ops = NULL; diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c index adfefaa..1fe3ec1 100644 --- a/lib/services/services_linux.c +++ b/lib/services/services_linux.c @@ -36,9 +36,6 @@ # include "crm/common/cib_secrets.h" #endif -/* ops currently active (in-flight) */ -extern GList *inflight_ops; - static inline void set_fd_opts(int fd, int opts) { @@ -248,9 +245,7 @@ operation_finalize(svc_action_t * op) op->pid = 0; - inflight_ops = g_list_remove(inflight_ops, op); - - handle_blocked_ops(); + services_untrack_op(op); if (!recurring && op->synchronous == FALSE) { /* diff --git a/lib/services/services_private.h b/lib/services/services_private.h index ec9e1c4..a949592 100644 --- a/lib/services/services_private.h +++ b/lib/services/services_private.h @@ -76,7 +76,7 @@ G_GNUC_INTERNAL void services_add_inflight_op(svc_action_t *op); G_GNUC_INTERNAL -void handle_blocked_ops(void); +void services_untrack_op(svc_action_t *op); G_GNUC_INTERNAL gboolean is_op_blocked(const char *rsc); -- 1.8.3.1 From b938c47740a456d0057438e4f5e6029d0e084587 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 27 Feb 2017 14:20:05 -0600 Subject: [PATCH 02/10] Refactor: libservices: dynamically allocate operation key reduces code duplication, and avoids memory over-allocation --- lib/services/services.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/services/services.c b/lib/services/services.c index 90a2181..4020b7d 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -149,10 +149,7 @@ resources_action_create(const char *name, const char *standard, const char *prov op->agent = strdup(agent); op->sequence = ++operations; op->flags = flags; - - if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) { - goto return_error; - } + op->id = generate_op_key(name, action, interval); if (strcasecmp(op->standard, "service") == 0) { const char *expanded = resources_find_service_class(op->agent); @@ -467,11 +464,10 @@ gboolean services_action_cancel(const char *name, const char *action, int interval) { svc_action_t *op = NULL; - char id[512]; - - snprintf(id, sizeof(id), "%s_%s_%d", name, action, interval); + char *id = generate_op_key(name, action, interval); if (!(op = g_hash_table_lookup(recurring_actions, id))) { + free(id); return FALSE; } @@ -494,10 +490,12 @@ services_action_cancel(const char *name, const char *action, int interval) /* even though the early termination failed, * the op will be marked as cancelled once it completes. */ crm_err("Termination of %s (pid=%d) failed", id, op->pid); + free(id); return FALSE; } } + free(id); return TRUE; } @@ -505,11 +503,7 @@ gboolean services_action_kick(const char *name, const char *action, int interval /* ms */) { svc_action_t * op = NULL; - char *id = NULL; - - if (asprintf(&id, "%s_%s_%d", name, action, interval) == -1) { - return FALSE; - } + char *id = generate_op_key(name, action, interval); op = g_hash_table_lookup(recurring_actions, id); free(id); -- 1.8.3.1 From 933d46ef20591757301784773a37e06b78906584 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 27 Feb 2017 14:28:36 -0600 Subject: [PATCH 03/10] Fix: libservices: prevent use-after-free when freeing an operation --- lib/services/services.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/services/services.c b/lib/services/services.c index 4020b7d..78a0781 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -410,6 +410,16 @@ services_action_free(svc_action_t * op) return; } + /* The operation should be removed from all tracking lists by this point. + * If it's not, we have a bug somewhere, so bail. That may lead to a + * memory leak, but it's better than a use-after-free segmentation fault. + */ + CRM_CHECK(g_list_find(inflight_ops, op) == NULL, return); + CRM_CHECK(g_list_find(blocked_ops, op) == NULL, return); + CRM_CHECK((recurring_actions == NULL) + || (g_hash_table_lookup(recurring_actions, op->id) == NULL), + return); + services_action_cleanup(op); if (op->opaque->repeat_timer) { -- 1.8.3.1 From dc36d4375c049024a6f9e4d2277a3e6444fad05b Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 28 Feb 2017 15:41:10 -0600 Subject: [PATCH 04/10] Refactor: libservices: handle in-flight case first when cancelling an operation will make next bugfix easier --- lib/services/services.c | 65 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/lib/services/services.c b/lib/services/services.c index 78a0781..dba4e66 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -470,43 +470,62 @@ cancel_recurring_action(svc_action_t * op) return TRUE; } +/*! + * \brief Cancel a recurring action + * + * \param[in] name Name of resource that operation is for + * \param[in] action Name of operation to cancel + * \param[in] interval Interval of operation to cancel + * + * \return TRUE if action was successfully cancelled, FALSE otherwise + */ gboolean services_action_cancel(const char *name, const char *action, int interval) { - svc_action_t *op = NULL; + gboolean cancelled = FALSE; char *id = generate_op_key(name, action, interval); + svc_action_t *op = g_hash_table_lookup(recurring_actions, id); - if (!(op = g_hash_table_lookup(recurring_actions, id))) { - free(id); - return FALSE; + /* We can only cancel a recurring action */ + if (op == NULL) { + goto done; } - /* Always kill the recurring timer */ + /* Tell operation_finalize() not to reschedule the operation */ + op->cancel = TRUE; + + /* Stop tracking it as a recurring operation, and stop its timer */ cancel_recurring_action(op); - if (op->pid == 0) { - op->status = PCMK_LRM_OP_CANCELLED; - if (op->opaque->callback) { - op->opaque->callback(op); + /* If the op has a PID, it's an in-flight child process, so kill it. + * + * Whether the kill succeeds or fails, the main loop will send the op to + * operation_finished() (and thus operation_finalize()) when the process + * goes away. + */ + if (op->pid != 0) { + crm_info("Terminating in-flight op %s (pid %d) early because it was cancelled", + id, op->pid); + cancelled = mainloop_child_kill(op->pid); + if (cancelled == FALSE) { + crm_err("Termination of %s (pid %d) failed", id, op->pid); } + goto done; + } - blocked_ops = g_list_remove(blocked_ops, op); - services_action_free(op); - - } else { - crm_info("Cancelling in-flight op: performing early termination of %s (pid=%d)", id, op->pid); - op->cancel = 1; - if (mainloop_child_kill(op->pid) == FALSE) { - /* even though the early termination failed, - * the op will be marked as cancelled once it completes. */ - crm_err("Termination of %s (pid=%d) failed", id, op->pid); - free(id); - return FALSE; - } + /* Otherwise, operation is not in-flight, just report as cancelled */ + op->status = PCMK_LRM_OP_CANCELLED; + if (op->opaque->callback) { + op->opaque->callback(op); } + blocked_ops = g_list_remove(blocked_ops, op); + services_action_free(op); + cancelled = TRUE; + +done: free(id); - return TRUE; + return cancelled; } gboolean -- 1.8.3.1 From deabcc5a6aa93dadf0b20364715b559a5b9848ac Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 28 Feb 2017 15:48:11 -0600 Subject: [PATCH 05/10] Fix: libservices: properly cancel in-flight systemd/upstart op --- lib/services/services.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/services/services.c b/lib/services/services.c index dba4e66..4aa4c01 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -89,6 +89,21 @@ resources_find_service_class(const char *agent) return NULL; } +/*! + * \internal + * \brief Check whether op is in-flight systemd or upstart op + * + * \param[in] op Operation to check + * + * \return TRUE if op is in-flight systemd or upstart op + */ +static inline gboolean +inflight_systemd_or_upstart(svc_action_t *op) +{ + return (safe_str_eq(op->standard, "systemd") + || safe_str_eq(op->standard, "upstart")) + && (g_list_find(inflight_ops, op) != NULL); +} svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, @@ -513,6 +528,18 @@ services_action_cancel(const char *name, const char *action, int interval) goto done; } + /* In-flight systemd and upstart ops don't have a pid. The relevant handlers + * will call operation_finalize() when the operation completes. + * @TODO: Can we request early termination, maybe using + * dbus_pending_call_cancel()? + */ + if (inflight_systemd_or_upstart(op)) { + crm_info("Will cancel %s op %s when in-flight instance completes", + op->standard, op->id); + cancelled = FALSE; + goto done; + } + /* Otherwise, operation is not in-flight, just report as cancelled */ op->status = PCMK_LRM_OP_CANCELLED; if (op->opaque->callback) { -- 1.8.3.1 From b85037b75255061a41d0ec3fd9b64f271351b43e Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 28 Feb 2017 16:43:52 -0600 Subject: [PATCH 06/10] Fix: libservices: properly detect in-flight systemd/upstart ops when kicking --- lib/services/services.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/services.c b/lib/services/services.c index 4aa4c01..b41517d 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -568,7 +568,8 @@ services_action_kick(const char *name, const char *action, int interval /* ms */ return FALSE; } - if (op->pid) { + + if (op->pid || inflight_systemd_or_upstart(op)) { return TRUE; } else { if (op->opaque->repeat_timer) { -- 1.8.3.1 From 55be77356d9253c46a1ddebefd6f403366209281 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 28 Feb 2017 18:37:23 -0600 Subject: [PATCH 07/10] Log: libservices: improve error messages when creating operation --- lib/services/services.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/services/services.c b/lib/services/services.c index b41517d..e089717 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -118,27 +118,27 @@ resources_action_create(const char *name, const char *standard, const char *prov */ if (crm_strlen_zero(name)) { - crm_err("A service or resource action must have a name."); + crm_err("Cannot create operation without resource name"); goto return_error; } if (crm_strlen_zero(standard)) { - crm_err("A service action must have a valid standard."); + crm_err("Cannot create operation for %s without resource class", name); goto return_error; } if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) { - crm_err("An OCF resource action must have a provider."); + crm_err("Cannot create OCF operation for %s without provider", name); goto return_error; } if (crm_strlen_zero(agent)) { - crm_err("A service or resource action must have an agent."); + crm_err("Cannot create operation for %s without agent name", name); goto return_error; } if (crm_strlen_zero(action)) { - crm_err("A service or resource action must specify an action."); + crm_err("Cannot create operation for %s without operation name", name); goto return_error; } @@ -170,12 +170,13 @@ resources_action_create(const char *name, const char *standard, const char *prov const char *expanded = resources_find_service_class(op->agent); if(expanded) { - crm_debug("Found a %s agent for %s/%s", expanded, op->rsc, op->agent); + crm_debug("Found %s agent %s for %s", expanded, op->agent, op->rsc); free(op->standard); op->standard = strdup(expanded); } else { - crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent); + crm_info("Assuming resource class lsb for agent %s for %s", + op->agent, op->rsc); free(op->standard); op->standard = strdup("lsb"); } @@ -226,7 +227,7 @@ resources_action_create(const char *name, const char *standard, const char *prov /* The "heartbeat" agent class only has positional arguments, * which we keyed by their decimal position number. */ param_num = 1; - for (index = 1; index <= MAX_ARGC - 3; index++ ) { + for (index = 1; index <= MAX_ARGC - 3; index++ ) { snprintf(buf_tmp, sizeof(buf_tmp), "%d", index); value_tmp = g_hash_table_lookup(params, buf_tmp); if (value_tmp == NULL) { @@ -237,8 +238,8 @@ resources_action_create(const char *name, const char *standard, const char *prov op->opaque->args[param_num++] = strdup(value_tmp); } - /* Add operation code as the last argument, */ - /* and the teminating NULL pointer */ + /* Add operation code as the last argument, */ + /* and the teminating NULL pointer */ op->opaque->args[param_num++] = strdup(op->action); op->opaque->args[param_num] = NULL; #endif -- 1.8.3.1 From 121a3f219ff5a9ea07e271cb03d9c55af2d2ad1f Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 28 Feb 2017 18:55:11 -0600 Subject: [PATCH 08/10] Refactor: libservices: functionize expanding resource class, and remove dead code --- include/crm/services.h | 1 + lib/services/services.c | 75 ++++++++++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/include/crm/services.h b/include/crm/services.h index 05c8ebf..28bb76a 100644 --- a/include/crm/services.h +++ b/include/crm/services.h @@ -47,6 +47,7 @@ extern "C" { # define SYSTEMCTL "/bin/systemctl" # endif +/* Deprecated and unused by Pacemaker, kept for API backward compatibility */ # ifndef SERVICE_SCRIPT # define SERVICE_SCRIPT "/sbin/service" # endif diff --git a/lib/services/services.c b/lib/services/services.c index e089717..3ffaeb6 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -105,6 +105,41 @@ inflight_systemd_or_upstart(svc_action_t *op) && (g_list_find(inflight_ops, op) != NULL); } +/*! + * \internal + * \brief Expand "service" alias to an actual resource class + * + * \param[in] rsc Resource name (for logging only) + * \param[in] standard Resource class as configured + * \param[in] agent Agent name to look for + * + * \return Newly allocated string with actual resource class + * + * \note The caller is responsible for calling free() on the result. + */ +static char * +expand_resource_class(const char *rsc, const char *standard, const char *agent) +{ + char *expanded_class = NULL; + + if (strcasecmp(standard, "service") == 0) { + const char *found_class = resources_find_service_class(agent); + + if (found_class) { + crm_debug("Found %s agent %s for %s", found_class, agent, rsc); + expanded_class = strdup(found_class); + } else { + crm_info("Assuming resource class lsb for agent %s for %s", + agent, rsc); + expanded_class = strdup("lsb"); + } + } else { + expanded_class = strdup(standard); + } + CRM_ASSERT(expanded_class); + return expanded_class; +} + svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, int interval, int timeout, @@ -142,14 +177,6 @@ resources_action_create(const char *name, const char *standard, const char *prov goto return_error; } - if (safe_str_eq(action, "monitor") && ( -#if SUPPORT_HEARTBEAT - safe_str_eq(standard, "heartbeat") || -#endif - safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) { - action = "status"; - } - /* * Sanity checks passed, proceed! */ @@ -157,31 +184,22 @@ resources_action_create(const char *name, const char *standard, const char *prov op = calloc(1, sizeof(svc_action_t)); op->opaque = calloc(1, sizeof(svc_action_private_t)); op->rsc = strdup(name); - op->action = strdup(action); op->interval = interval; op->timeout = timeout; - op->standard = strdup(standard); + op->standard = expand_resource_class(name, standard, agent); op->agent = strdup(agent); op->sequence = ++operations; op->flags = flags; op->id = generate_op_key(name, action, interval); - if (strcasecmp(op->standard, "service") == 0) { - const char *expanded = resources_find_service_class(op->agent); - - if(expanded) { - crm_debug("Found %s agent %s for %s", expanded, op->agent, op->rsc); - free(op->standard); - op->standard = strdup(expanded); - - } else { - crm_info("Assuming resource class lsb for agent %s for %s", - op->agent, op->rsc); - free(op->standard); - op->standard = strdup("lsb"); - } - CRM_ASSERT(op->standard); + if (safe_str_eq(action, "monitor") && ( +#if SUPPORT_HEARTBEAT + safe_str_eq(op->standard, "heartbeat") || +#endif + safe_str_eq(op->standard, "lsb"))) { + action = "status"; } + op->action = strdup(action); if (strcasecmp(op->standard, "ocf") == 0) { op->provider = strdup(provider); @@ -251,12 +269,6 @@ resources_action_create(const char *name, const char *standard, const char *prov } else if (strcasecmp(op->standard, "upstart") == 0) { op->opaque->exec = strdup("upstart-dbus"); #endif - } else if (strcasecmp(op->standard, "service") == 0) { - op->opaque->exec = strdup(SERVICE_SCRIPT); - op->opaque->args[0] = strdup(SERVICE_SCRIPT); - op->opaque->args[1] = strdup(agent); - op->opaque->args[2] = strdup(action); - #if SUPPORT_NAGIOS } else if (strcasecmp(op->standard, "nagios") == 0) { int index = 0; @@ -308,7 +320,6 @@ resources_action_create(const char *name, const char *standard, const char *prov } op->opaque->args[index] = NULL; #endif - } else { crm_err("Unknown resource standard: %s", op->standard); services_action_free(op); -- 1.8.3.1 From 46c07e23d48806140cf12393b7867063630cdf30 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Tue, 28 Feb 2017 19:30:16 -0600 Subject: [PATCH 09/10] Refactor: various: use defined constants for resource classes ensures a typo won't compile --- crmd/remote_lrmd_ra.c | 2 +- fencing/main.c | 6 ++-- include/crm/services.h | 9 +++++ lib/lrmd/lrmd_client.c | 23 +++++++------ lib/pengine/complex.c | 2 +- lib/pengine/native.c | 8 ++--- lib/pengine/remote.c | 3 +- lib/pengine/unpack.c | 2 +- lib/services/services.c | 79 ++++++++++++++++++++++++------------------- lib/services/services_linux.c | 9 +++-- lrmd/lrmd.c | 44 +++++++++++++----------- pengine/native.c | 2 +- tools/crm_resource_print.c | 2 +- tools/crm_resource_runtime.c | 2 +- tools/fake_transition.c | 17 +++++----- 15 files changed, 119 insertions(+), 91 deletions(-) diff --git a/crmd/remote_lrmd_ra.c b/crmd/remote_lrmd_ra.c index eb995ea..e68d784 100644 --- a/crmd/remote_lrmd_ra.c +++ b/crmd/remote_lrmd_ra.c @@ -841,7 +841,7 @@ remote_ra_get_rsc_info(lrm_state_t * lrm_state, const char *rsc_id) info->id = strdup(rsc_id); info->type = strdup(REMOTE_LRMD_RA); - info->class = strdup("ocf"); + info->class = strdup(PCMK_RESOURCE_CLASS_OCF); info->provider = strdup("pacemaker"); } diff --git a/fencing/main.c b/fencing/main.c index 95a1408..e6eb087 100644 --- a/fencing/main.c +++ b/fencing/main.c @@ -455,7 +455,7 @@ remove_cib_device(xmlXPathObjectPtr xpathObj) standard = crm_element_value(match, XML_AGENT_ATTR_CLASS); } - if (safe_str_neq(standard, "stonith")) { + if (safe_str_neq(standard, PCMK_RESOURCE_CLASS_STONITH)) { continue; } @@ -630,7 +630,7 @@ static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set) /* We only care about STONITH resources. */ rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if(safe_str_neq(rclass, "stonith")) { + if (safe_str_neq(rclass, PCMK_RESOURCE_CLASS_STONITH)) { return; } @@ -848,7 +848,7 @@ update_cib_stonith_devices_v1(const char *event, xmlNode * msg) rsc_id = crm_element_value(match, XML_ATTR_ID); standard = crm_element_value(match, XML_AGENT_ATTR_CLASS); - if (safe_str_neq(standard, "stonith")) { + if (safe_str_neq(standard, PCMK_RESOURCE_CLASS_STONITH)) { continue; } diff --git a/include/crm/services.h b/include/crm/services.h index 28bb76a..e1fae9b 100644 --- a/include/crm/services.h +++ b/include/crm/services.h @@ -52,6 +52,15 @@ extern "C" { # define SERVICE_SCRIPT "/sbin/service" # endif +/* Known resource classes */ +#define PCMK_RESOURCE_CLASS_OCF "ocf" +#define PCMK_RESOURCE_CLASS_SERVICE "service" +#define PCMK_RESOURCE_CLASS_LSB "lsb" +#define PCMK_RESOURCE_CLASS_SYSTEMD "systemd" +#define PCMK_RESOURCE_CLASS_UPSTART "upstart" +#define PCMK_RESOURCE_CLASS_HB "heartbeat" +#define PCMK_RESOURCE_CLASS_NAGIOS "nagios" +#define PCMK_RESOURCE_CLASS_STONITH "stonith" /* This is the string passed in the OCF_EXIT_REASON_PREFIX * environment variable. The stderr output that occurs diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index e009078..64b66b1 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -1438,7 +1438,7 @@ lrmd_api_register_rsc(lrmd_t * lrmd, if (!class || !type || !rsc_id) { return -EINVAL; } - if (safe_str_eq(class, "ocf") && !provider) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF) && !provider) { return -EINVAL; } @@ -1525,7 +1525,7 @@ lrmd_api_get_rsc_info(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options if (!class || !type) { free_xml(output); return NULL; - } else if (safe_str_eq(class, "ocf") && !provider) { + } else if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF) && !provider) { free_xml(output); return NULL; } @@ -1969,20 +1969,20 @@ lrmd_api_get_metadata(lrmd_t * lrmd, return -EINVAL; } - if (safe_str_eq(class, "service")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_SERVICE)) { class = resources_find_service_class(type); } - if (safe_str_eq(class, "stonith")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_STONITH)) { return stonith_get_metadata(provider, type, output); - } else if (safe_str_eq(class, "lsb")) { + } else if (safe_str_eq(class, PCMK_RESOURCE_CLASS_LSB)) { return lsb_get_metadata(type, output); #if SUPPORT_NAGIOS - } else if (safe_str_eq(class, "nagios")) { + } else if (safe_str_eq(class, PCMK_RESOURCE_CLASS_NAGIOS)) { return nagios_get_metadata(type, output); #endif #if SUPPORT_HEARTBEAT - } else if (safe_str_eq(class, "heartbeat")) { + } else if (safe_str_eq(class, PCMK_RESOURCE_CLASS_HB)) { return heartbeat_get_metadata(type, output); #endif } @@ -2073,7 +2073,7 @@ lrmd_api_list_agents(lrmd_t * lrmd, lrmd_list_t ** resources, const char *class, { int rc = 0; - if (safe_str_eq(class, "stonith")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_STONITH)) { rc += list_stonith_agents(resources); } else { @@ -2124,11 +2124,12 @@ lrmd_api_list_ocf_providers(lrmd_t * lrmd, const char *agent, lrmd_list_t ** pro GList *ocf_providers = NULL; GListPtr gIter = NULL; - ocf_providers = resources_list_providers("ocf"); + ocf_providers = resources_list_providers(PCMK_RESOURCE_CLASS_OCF); for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) { provider = gIter->data; - if (!agent || does_provider_have_agent(agent, provider, "ocf")) { + if (!agent || does_provider_have_agent(agent, provider, + PCMK_RESOURCE_CLASS_OCF)) { *providers = lrmd_list_add(*providers, (const char *)gIter->data); rc++; } @@ -2153,7 +2154,7 @@ lrmd_api_list_standards(lrmd_t * lrmd, lrmd_list_t ** supported) } if (list_stonith_agents(NULL) > 0) { - *supported = lrmd_list_add(*supported, "stonith"); + *supported = lrmd_list_add(*supported, PCMK_RESOURCE_CLASS_STONITH); rc++; } diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index 7fe622f..a83929d 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.c @@ -651,7 +651,7 @@ common_unpack(xmlNode * xml_obj, resource_t ** rsc, } } - if (safe_str_eq(rclass, "stonith")) { + if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH)) { set_bit(data_set->flags, pe_flag_have_stonith_resource); set_bit((*rsc)->flags, pe_rsc_fence_device); } diff --git a/lib/pengine/native.c b/lib/pengine/native.c index 11febf4..5f3cfc3 100644 --- a/lib/pengine/native.c +++ b/lib/pengine/native.c @@ -136,14 +136,14 @@ native_unpack(resource_t * rsc, pe_working_set_t * data_set) if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) { - if (safe_str_eq(class, "lsb")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_LSB)) { resource_t *top = uber_parent(rsc); force_non_unique_clone(top, rsc->id, data_set); } } - if (safe_str_eq(class, "ocf") == FALSE) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF) == FALSE) { const char *stateful = g_hash_table_lookup(parent->meta, "stateful"); if (safe_str_eq(stateful, XML_BOOLEAN_TRUE)) { @@ -533,7 +533,7 @@ native_print(resource_t * rsc, const char *pre_text, long options, void *print_d } offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_printable_id(rsc)); offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class); - if (safe_str_eq(class, "ocf")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF)) { const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov); } @@ -799,7 +799,7 @@ get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_ta } offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class); - if (safe_str_eq(class, "ocf")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF)) { const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov); } diff --git a/lib/pengine/remote.c b/lib/pengine/remote.c index e8d9bab..c5a3eec 100644 --- a/lib/pengine/remote.c +++ b/lib/pengine/remote.c @@ -94,7 +94,8 @@ xml_contains_remote_node(xmlNode *xml) const char *provider = crm_element_value(xml, XML_AGENT_ATTR_PROVIDER); const char *agent = crm_element_value(xml, XML_ATTR_TYPE); - if (safe_str_eq(agent, "remote") && safe_str_eq(provider, "pacemaker") && safe_str_eq(class, "ocf")) { + if (safe_str_eq(agent, "remote") && safe_str_eq(provider, "pacemaker") + && safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF)) { return TRUE; } return FALSE; diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index e0a3452..e6a8f58 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -422,7 +422,7 @@ expand_remote_rsc_meta(xmlNode *xml_obj, xmlNode *parent, GHashTable **rsc_name_ xml_rsc = create_xml_node(parent, XML_CIB_TAG_RESOURCE); crm_xml_add(xml_rsc, XML_ATTR_ID, remote_name); - crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, "ocf"); + crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, PCMK_RESOURCE_CLASS_OCF); crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, "pacemaker"); crm_xml_add(xml_rsc, XML_ATTR_TYPE, "remote"); diff --git a/lib/services/services.c b/lib/services/services.c index 3ffaeb6..52d3b55 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -51,7 +51,8 @@ static void handle_blocked_ops(void); svc_action_t * services_action_create(const char *name, const char *action, int interval, int timeout) { - return resources_action_create(name, "lsb", NULL, name, action, interval, timeout, NULL, 0); + return resources_action_create(name, PCMK_RESOURCE_CLASS_LSB, NULL, name, + action, interval, timeout, NULL, 0); } const char * @@ -70,20 +71,20 @@ resources_find_service_class(const char *agent) rc = asprintf(&path, "%s/%s", LSB_ROOT_DIR, agent); if (rc > 0 && stat(path, &st) == 0) { free(path); - return "lsb"; + return PCMK_RESOURCE_CLASS_LSB; } free(path); #endif #if SUPPORT_SYSTEMD if (systemd_unit_exists(agent)) { - return "systemd"; + return PCMK_RESOURCE_CLASS_SYSTEMD; } #endif #if SUPPORT_UPSTART if (upstart_job_exists(agent)) { - return "upstart"; + return PCMK_RESOURCE_CLASS_UPSTART; } #endif return NULL; @@ -100,8 +101,8 @@ resources_find_service_class(const char *agent) static inline gboolean inflight_systemd_or_upstart(svc_action_t *op) { - return (safe_str_eq(op->standard, "systemd") - || safe_str_eq(op->standard, "upstart")) + return (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_SYSTEMD) + || safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_UPSTART)) && (g_list_find(inflight_ops, op) != NULL); } @@ -122,7 +123,7 @@ expand_resource_class(const char *rsc, const char *standard, const char *agent) { char *expanded_class = NULL; - if (strcasecmp(standard, "service") == 0) { + if (strcasecmp(standard, PCMK_RESOURCE_CLASS_SERVICE) == 0) { const char *found_class = resources_find_service_class(agent); if (found_class) { @@ -131,7 +132,7 @@ expand_resource_class(const char *rsc, const char *standard, const char *agent) } else { crm_info("Assuming resource class lsb for agent %s for %s", agent, rsc); - expanded_class = strdup("lsb"); + expanded_class = strdup(PCMK_RESOURCE_CLASS_LSB); } } else { expanded_class = strdup(standard); @@ -162,7 +163,8 @@ resources_action_create(const char *name, const char *standard, const char *prov goto return_error; } - if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) { + if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_OCF) + && crm_strlen_zero(provider)) { crm_err("Cannot create OCF operation for %s without provider", name); goto return_error; } @@ -194,14 +196,14 @@ resources_action_create(const char *name, const char *standard, const char *prov if (safe_str_eq(action, "monitor") && ( #if SUPPORT_HEARTBEAT - safe_str_eq(op->standard, "heartbeat") || + safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_HB) || #endif - safe_str_eq(op->standard, "lsb"))) { + safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB))) { action = "status"; } op->action = strdup(action); - if (strcasecmp(op->standard, "ocf") == 0) { + if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_OCF) == 0) { op->provider = strdup(provider); op->params = params; params = NULL; @@ -213,7 +215,7 @@ resources_action_create(const char *name, const char *standard, const char *prov op->opaque->args[0] = strdup(op->opaque->exec); op->opaque->args[1] = strdup(action); - } else if (strcasecmp(op->standard, "lsb") == 0) { + } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_LSB) == 0) { if (op->agent[0] == '/') { /* if given an absolute path, use that instead * of tacking on the LSB_ROOT_DIR path to the front */ @@ -226,7 +228,7 @@ resources_action_create(const char *name, const char *standard, const char *prov op->opaque->args[1] = strdup(op->action); op->opaque->args[2] = NULL; #if SUPPORT_HEARTBEAT - } else if (strcasecmp(op->standard, "heartbeat") == 0) { + } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_HB) == 0) { int index; int param_num; char buf_tmp[20]; @@ -262,15 +264,15 @@ resources_action_create(const char *name, const char *standard, const char *prov op->opaque->args[param_num] = NULL; #endif #if SUPPORT_SYSTEMD - } else if (strcasecmp(op->standard, "systemd") == 0) { + } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_SYSTEMD) == 0) { op->opaque->exec = strdup("systemd-dbus"); #endif #if SUPPORT_UPSTART - } else if (strcasecmp(op->standard, "upstart") == 0) { + } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_UPSTART) == 0) { op->opaque->exec = strdup("upstart-dbus"); #endif #if SUPPORT_NAGIOS - } else if (strcasecmp(op->standard, "nagios") == 0) { + } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_NAGIOS) == 0) { int index = 0; if (op->agent[0] == '/') { @@ -637,11 +639,13 @@ inline static gboolean action_exec_helper(svc_action_t * op) { /* Whether a/synchronous must be decided (op->synchronous) beforehand. */ - if (op->standard && strcasecmp(op->standard, "upstart") == 0) { + if (op->standard + && (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_UPSTART) == 0)) { #if SUPPORT_UPSTART return upstart_job_exec(op); #endif - } else if (op->standard && strcasecmp(op->standard, "systemd") == 0) { + } else if (op->standard && strcasecmp(op->standard, + PCMK_RESOURCE_CLASS_SYSTEMD) == 0) { #if SUPPORT_SYSTEMD return systemd_unit_exec(op); #endif @@ -803,7 +807,7 @@ get_directory_list(const char *root, gboolean files, gboolean executable) GList * services_list(void) { - return resources_list_agents("lsb", NULL); + return resources_list_agents(PCMK_RESOURCE_CLASS_LSB, NULL); } #if SUPPORT_HEARTBEAT @@ -820,14 +824,15 @@ resources_list_standards(void) GList *standards = NULL; GList *agents = NULL; - standards = g_list_append(standards, strdup("ocf")); - standards = g_list_append(standards, strdup("lsb")); - standards = g_list_append(standards, strdup("service")); + standards = g_list_append(standards, strdup(PCMK_RESOURCE_CLASS_OCF)); + standards = g_list_append(standards, strdup(PCMK_RESOURCE_CLASS_LSB)); + standards = g_list_append(standards, strdup(PCMK_RESOURCE_CLASS_SERVICE)); #if SUPPORT_SYSTEMD agents = systemd_unit_listall(); if (agents) { - standards = g_list_append(standards, strdup("systemd")); + standards = g_list_append(standards, + strdup(PCMK_RESOURCE_CLASS_SYSTEMD)); g_list_free_full(agents, free); } #endif @@ -835,7 +840,8 @@ resources_list_standards(void) #if SUPPORT_UPSTART agents = upstart_job_listall(); if (agents) { - standards = g_list_append(standards, strdup("upstart")); + standards = g_list_append(standards, + strdup(PCMK_RESOURCE_CLASS_UPSTART)); g_list_free_full(agents, free); } #endif @@ -843,13 +849,14 @@ resources_list_standards(void) #if SUPPORT_NAGIOS agents = resources_os_list_nagios_agents(); if (agents) { - standards = g_list_append(standards, strdup("nagios")); + standards = g_list_append(standards, + strdup(PCMK_RESOURCE_CLASS_NAGIOS)); g_list_free_full(agents, free); } #endif #if SUPPORT_HEARTBEAT - standards = g_list_append(standards, strdup("heartbeat")); + standards = g_list_append(standards, strdup(PCMK_RESOURCE_CLASS_HB)); #endif return standards; @@ -858,7 +865,7 @@ resources_list_standards(void) GList * resources_list_providers(const char *standard) { - if (strcasecmp(standard, "ocf") == 0) { + if (strcasecmp(standard, PCMK_RESOURCE_CLASS_OCF) == 0) { return resources_os_list_ocf_providers(); } @@ -868,7 +875,9 @@ resources_list_providers(const char *standard) GList * resources_list_agents(const char *standard, const char *provider) { - if (standard == NULL || strcasecmp(standard, "service") == 0) { + if ((standard == NULL) + || (strcasecmp(standard, PCMK_RESOURCE_CLASS_SERVICE) == 0)) { + GList *tmp1; GList *tmp2; GList *result = resources_os_list_lsb_agents(); @@ -898,24 +907,24 @@ resources_list_agents(const char *standard, const char *provider) return result; - } else if (strcasecmp(standard, "ocf") == 0) { + } else if (strcasecmp(standard, PCMK_RESOURCE_CLASS_OCF) == 0) { return resources_os_list_ocf_agents(provider); - } else if (strcasecmp(standard, "lsb") == 0) { + } else if (strcasecmp(standard, PCMK_RESOURCE_CLASS_LSB) == 0) { return resources_os_list_lsb_agents(); #if SUPPORT_HEARTBEAT - } else if (strcasecmp(standard, "heartbeat") == 0) { + } else if (strcasecmp(standard, PCMK_RESOURCE_CLASS_HB) == 0) { return resources_os_list_hb_agents(); #endif #if SUPPORT_SYSTEMD - } else if (strcasecmp(standard, "systemd") == 0) { + } else if (strcasecmp(standard, PCMK_RESOURCE_CLASS_SYSTEMD) == 0) { return systemd_unit_listall(); #endif #if SUPPORT_UPSTART - } else if (strcasecmp(standard, "upstart") == 0) { + } else if (strcasecmp(standard, PCMK_RESOURCE_CLASS_UPSTART) == 0) { return upstart_job_listall(); #endif #if SUPPORT_NAGIOS - } else if (strcasecmp(standard, "nagios") == 0) { + } else if (strcasecmp(standard, PCMK_RESOURCE_CLASS_NAGIOS) == 0) { return resources_os_list_nagios_agents(); #endif } diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c index 1fe3ec1..c2ac43d 100644 --- a/lib/services/services_linux.c +++ b/lib/services/services_linux.c @@ -177,7 +177,8 @@ set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data) static void add_OCF_env_vars(svc_action_t * op) { - if (!op->standard || strcasecmp("ocf", op->standard) != 0) { + if ((op->standard == NULL) + || (strcasecmp(PCMK_RESOURCE_CLASS_OCF, op->standard) != 0)) { return; } @@ -338,13 +339,15 @@ services_handle_exec_error(svc_action_t * op, int error) int rc_not_installed, rc_insufficient_priv, rc_exec_error; /* Mimic the return codes for each standard as that's what we'll convert back from in get_uniform_rc() */ - if (safe_str_eq(op->standard, "lsb") && safe_str_eq(op->action, "status")) { + if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB) + && safe_str_eq(op->action, "status")) { + rc_not_installed = PCMK_LSB_STATUS_NOT_INSTALLED; rc_insufficient_priv = PCMK_LSB_STATUS_INSUFFICIENT_PRIV; rc_exec_error = PCMK_LSB_STATUS_UNKNOWN; #if SUPPORT_NAGIOS - } else if (safe_str_eq(op->standard, "nagios")) { + } else if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_NAGIOS)) { rc_not_installed = NAGIOS_NOT_INSTALLED; rc_insufficient_priv = NAGIOS_INSUFFICIENT_PRIV; rc_exec_error = PCMK_OCF_EXEC_ERROR; diff --git a/lrmd/lrmd.c b/lrmd/lrmd.c index 724edb7..5669d34 100644 --- a/lrmd/lrmd.c +++ b/lrmd/lrmd.c @@ -139,8 +139,9 @@ static const char * normalize_action_name(lrmd_rsc_t * rsc, const char *action) { if (safe_str_eq(action, "monitor") && - (safe_str_eq(rsc->class, "lsb") || - safe_str_eq(rsc->class, "service") || safe_str_eq(rsc->class, "systemd"))) { + (safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_LSB) || + safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_SERVICE) + || safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_SYSTEMD))) { return "status"; } return action; @@ -435,7 +436,7 @@ merge_dup: cmd->userdata_str = NULL; dup->call_id = cmd->call_id; - if (safe_str_eq(rsc->class, "stonith")) { + if (safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_STONITH)) { /* if we are waiting for the next interval, kick it off now */ if (dup_pending == TRUE) { g_source_remove(cmd->stonith_recurring_id); @@ -854,16 +855,16 @@ nagios2uniform_rc(const char *action, int rc) static int get_uniform_rc(const char *standard, const char *action, int rc) { - if (safe_str_eq(standard, "ocf")) { + if (safe_str_eq(standard, PCMK_RESOURCE_CLASS_OCF)) { return ocf2uniform_rc(rc); - } else if (safe_str_eq(standard, "stonith")) { + } else if (safe_str_eq(standard, PCMK_RESOURCE_CLASS_STONITH)) { return stonith2uniform_rc(action, rc); - } else if (safe_str_eq(standard, "systemd")) { + } else if (safe_str_eq(standard, PCMK_RESOURCE_CLASS_SYSTEMD)) { return rc; - } else if (safe_str_eq(standard, "upstart")) { + } else if (safe_str_eq(standard, PCMK_RESOURCE_CLASS_UPSTART)) { return rc; #if SUPPORT_NAGIOS - } else if (safe_str_eq(standard, "nagios")) { + } else if (safe_str_eq(standard, PCMK_RESOURCE_CLASS_NAGIOS)) { return nagios2uniform_rc(action, rc); #endif } else { @@ -876,7 +877,7 @@ action_get_uniform_rc(svc_action_t * action) { lrmd_cmd_t *cmd = action->cb_data; #if SUPPORT_HEARTBEAT - if (safe_str_eq(action->standard, "heartbeat")) { + if (safe_str_eq(action->standard, PCMK_RESOURCE_CLASS_HB)) { return hb2uniform_rc(cmd->action, action->rc, action->stdout_data); } #endif @@ -991,13 +992,13 @@ action_complete(svc_action_t * action) cmd->lrmd_op_status = action->status; rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; - if(rsc && safe_str_eq(rsc->class, "service")) { + if (rsc && safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_SERVICE)) { rclass = resources_find_service_class(rsc->class); } else if(rsc) { rclass = rsc->class; } - if (safe_str_eq(rclass, "systemd")) { + if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_SYSTEMD)) { if(cmd->exec_rc == PCMK_OCF_OK && safe_str_eq(cmd->action, "start")) { /* systemd I curse thee! * @@ -1042,7 +1043,7 @@ action_complete(svc_action_t * action) } #if SUPPORT_NAGIOS - if (rsc && safe_str_eq(rsc->class, "nagios")) { + if (rsc && safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_NAGIOS)) { if (safe_str_eq(cmd->action, "monitor") && cmd->interval == 0 && cmd->exec_rc == PCMK_OCF_OK) { /* Successfully executed --version for the nagios plugin */ @@ -1123,7 +1124,7 @@ stonith_action_complete(lrmd_cmd_t * cmd, int rc) int recurring = cmd->interval; lrmd_rsc_t *rsc = NULL; - cmd->exec_rc = get_uniform_rc("stonith", cmd->action, rc); + cmd->exec_rc = get_uniform_rc(PCMK_RESOURCE_CLASS_STONITH, cmd->action, rc); rsc = g_hash_table_lookup(rsc_list, cmd->rsc_id); @@ -1184,7 +1185,7 @@ stonith_connection_failed(void) g_hash_table_iter_init(&iter, rsc_list); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & rsc)) { - if (safe_str_eq(rsc->class, "stonith")) { + if (safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_STONITH)) { if (rsc->active) { cmd_list = g_list_append(cmd_list, rsc->active); } @@ -1219,7 +1220,8 @@ lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) stonith_t *stonith_api = get_stonith_connection(); if (!stonith_api) { - cmd->exec_rc = get_uniform_rc("stonith", cmd->action, -ENOTCONN); + cmd->exec_rc = get_uniform_rc(PCMK_RESOURCE_CLASS_STONITH, cmd->action, + -ENOTCONN); cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; cmd_finalize(cmd, rsc); return -EUNATCH; @@ -1302,7 +1304,9 @@ lrmd_rsc_execute_service_lib(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) #if SUPPORT_NAGIOS /* Recurring operations are cancelled anyway for a stop operation */ - if (safe_str_eq(rsc->class, "nagios") && safe_str_eq(cmd->action, "stop")) { + if (safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_NAGIOS) + && safe_str_eq(cmd->action, "stop")) { + cmd->exec_rc = PCMK_OCF_OK; goto exec_done; } @@ -1320,7 +1324,7 @@ lrmd_rsc_execute_service_lib(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) if (cmd->isolation_wrapper) { g_hash_table_remove(params_copy, "CRM_meta_isolation_wrapper"); action = resources_action_create(rsc->rsc_id, - "ocf", + PCMK_RESOURCE_CLASS_OCF, LRMD_ISOLATION_PROVIDER, cmd->isolation_wrapper, cmd->action, /*action will be normalized in wrapper*/ @@ -1417,7 +1421,7 @@ lrmd_rsc_execute(lrmd_rsc_t * rsc) log_execute(cmd); - if (safe_str_eq(rsc->class, "stonith")) { + if (safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_STONITH)) { lrmd_rsc_execute_stonith(rsc, cmd); } else { lrmd_rsc_execute_service_lib(rsc, cmd); @@ -1437,7 +1441,7 @@ free_rsc(gpointer data) { GListPtr gIter = NULL; lrmd_rsc_t *rsc = data; - int is_stonith = safe_str_eq(rsc->class, "stonith"); + int is_stonith = safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_STONITH); gIter = rsc->pending_ops; while (gIter != NULL) { @@ -1679,7 +1683,7 @@ cancel_op(const char *rsc_id, const char *action, int interval) } } - if (safe_str_eq(rsc->class, "stonith")) { + if (safe_str_eq(rsc->class, PCMK_RESOURCE_CLASS_STONITH)) { /* The service library does not handle stonith operations. * We have to handle recurring stonith operations ourselves. */ for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { diff --git a/pengine/native.c b/pengine/native.c index 0c972ea..52eba4f 100644 --- a/pengine/native.c +++ b/pengine/native.c @@ -2701,7 +2701,7 @@ native_create_probe(resource_t * rsc, node_t * node, action_t * complete, if (is_remote_node(node)) { const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if (safe_str_eq(class, "stonith")) { + if (safe_str_eq(class, PCMK_RESOURCE_CLASS_STONITH)) { pe_rsc_trace(rsc, "Skipping probe for %s on node %s, remote-nodes do not run stonith agents.", rsc->id, node->details->id); return FALSE; } else if (rsc_contains_remote_node(data_set, rsc)) { diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c index 5e84723..65841e5 100644 --- a/tools/crm_resource_print.c +++ b/tools/crm_resource_print.c @@ -69,7 +69,7 @@ cli_resource_print_cts(resource_t * rsc) const char *rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); const char *rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if (safe_str_eq(rclass, "stonith")) { + if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH)) { xmlNode *op = NULL; needs_quorum = FALSE; diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index 7a64bc9..61aabe9 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -1496,7 +1496,7 @@ cli_resource_execute(const char *rsc_id, const char *rsc_action, GHashTable *ove rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE); - if(safe_str_eq(rclass, "stonith")){ + if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH)) { CMD_ERR("Sorry, --%s doesn't support %s resources yet", rsc_action, rclass); crm_exit(EOPNOTSUPP); } diff --git a/tools/fake_transition.c b/tools/fake_transition.c index c45349f..6448c14 100644 --- a/tools/fake_transition.c +++ b/tools/fake_transition.c @@ -298,17 +298,18 @@ inject_resource(xmlNode * cib_node, const char *resource, const char *rclass, co " Please supply the class and type to continue\n", resource, ID(cib_node)); return NULL; - } else if (safe_str_neq(rclass, "ocf") - && safe_str_neq(rclass, "stonith") - && safe_str_neq(rclass, "heartbeat") - && safe_str_neq(rclass, "service") - && safe_str_neq(rclass, "upstart") - && safe_str_neq(rclass, "systemd") - && safe_str_neq(rclass, "lsb")) { + } else if (safe_str_neq(rclass, PCMK_RESOURCE_CLASS_OCF) + && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_STONITH) + && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_HB) + && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_SERVICE) + && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_UPSTART) + && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_SYSTEMD) + && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_LSB)) { fprintf(stderr, "Invalid class for %s: %s\n", resource, rclass); return NULL; - } else if (safe_str_eq(rclass, "ocf") && rprovider == NULL) { + } else if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_OCF) + && rprovider == NULL) { fprintf(stderr, "Please specify the provider for resource %s\n", resource); return NULL; } -- 1.8.3.1 From 1c534b5a773df5b62aeb8a46842d1e2d4d2266ef Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Wed, 1 Mar 2017 15:04:35 -0600 Subject: [PATCH 10/10] Fix: libservices: ensure recurring actions table is created before using --- lib/services/services.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/services/services.c b/lib/services/services.c index 52d3b55..679f8e7 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -90,6 +90,15 @@ resources_find_service_class(const char *agent) return NULL; } +static inline void +init_recurring_actions(void) +{ + if (recurring_actions == NULL) { + recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + NULL); + } +} + /*! * \internal * \brief Check whether op is in-flight systemd or upstart op @@ -513,9 +522,11 @@ services_action_cancel(const char *name, const char *action, int interval) { gboolean cancelled = FALSE; char *id = generate_op_key(name, action, interval); - svc_action_t *op = g_hash_table_lookup(recurring_actions, id); + svc_action_t *op = NULL; /* We can only cancel a recurring action */ + init_recurring_actions(); + op = g_hash_table_lookup(recurring_actions, id); if (op == NULL) { goto done; } @@ -575,6 +586,7 @@ services_action_kick(const char *name, const char *action, int interval /* ms */ svc_action_t * op = NULL; char *id = generate_op_key(name, action, interval); + init_recurring_actions(); op = g_hash_table_lookup(recurring_actions, id); free(id); @@ -604,11 +616,6 @@ handle_duplicate_recurring(svc_action_t * op, void (*action_callback) (svc_actio { svc_action_t * dup = NULL; - if (recurring_actions == NULL) { - recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - return FALSE; - } - /* check for duplicates */ dup = g_hash_table_lookup(recurring_actions, op->id); @@ -700,6 +707,7 @@ services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t * } if (op->interval > 0) { + init_recurring_actions(); if (handle_duplicate_recurring(op, action_callback) == TRUE) { /* entry rescheduled, dup freed */ /* exit early */ -- 1.8.3.1