summaryrefslogtreecommitdiffstats
path: root/daemons/controld/controld_cib.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--daemons/controld/controld_cib.c298
1 files changed, 115 insertions, 183 deletions
diff --git a/daemons/controld/controld_cib.c b/daemons/controld/controld_cib.c
index 94b99dd..865e41f 100644
--- a/daemons/controld/controld_cib.c
+++ b/daemons/controld/controld_cib.c
@@ -22,90 +22,6 @@
// Call ID of the most recent in-progress CIB resource update (or 0 if none)
static int pending_rsc_update = 0;
-// Call IDs of requested CIB replacements that won't trigger a new election
-// (used as a set of gint values)
-static GHashTable *cib_replacements = NULL;
-
-/*!
- * \internal
- * \brief Store the call ID of a CIB replacement that the controller requested
- *
- * The \p do_cib_replaced() callback function will avoid triggering a new
- * election when we're notified of one of these expected replacements.
- *
- * \param[in] call_id CIB call ID (or 0 for a synchronous call)
- *
- * \note This function should be called after making any asynchronous CIB
- * request (or before making any synchronous CIB request) that may replace
- * part of the nodes or status section. This may include CIB sync calls.
- */
-void
-controld_record_cib_replace_call(int call_id)
-{
- CRM_CHECK(call_id >= 0, return);
-
- if (cib_replacements == NULL) {
- cib_replacements = g_hash_table_new(NULL, NULL);
- }
-
- /* If the call ID is already present in the table, then it's old. We may not
- * be removing them properly, and we could improperly ignore replacement
- * notifications if cib_t:call_id wraps around.
- */
- CRM_LOG_ASSERT(g_hash_table_add(cib_replacements,
- GINT_TO_POINTER((gint) call_id)));
-}
-
-/*!
- * \internal
- * \brief Remove the call ID of a CIB replacement from the replacements table
- *
- * \param[in] call_id CIB call ID (or 0 for a synchronous call)
- *
- * \return \p true if \p call_id was found in the table, or \p false otherwise
- *
- * \note CIB notifications run before CIB callbacks. If this function is called
- * from within a callback, \p do_cib_replaced() will have removed
- * \p call_id from the table first if relevant changes triggered a
- * notification.
- */
-bool
-controld_forget_cib_replace_call(int call_id)
-{
- CRM_CHECK(call_id >= 0, return false);
-
- if (cib_replacements == NULL) {
- return false;
- }
- return g_hash_table_remove(cib_replacements,
- GINT_TO_POINTER((gint) call_id));
-}
-
-/*!
- * \internal
- * \brief Empty the hash table containing call IDs of CIB replacement requests
- */
-void
-controld_forget_all_cib_replace_calls(void)
-{
- if (cib_replacements != NULL) {
- g_hash_table_remove_all(cib_replacements);
- }
-}
-
-/*!
- * \internal
- * \brief Free the hash table containing call IDs of CIB replacement requests
- */
-void
-controld_destroy_cib_replacements_table(void)
-{
- if (cib_replacements != NULL) {
- g_hash_table_destroy(cib_replacements);
- cib_replacements = NULL;
- }
-}
-
/*!
* \internal
* \brief Respond to a dropped CIB connection
@@ -127,54 +43,54 @@ handle_cib_disconnect(gpointer user_data)
controld_clear_fsa_input_flags(R_CIB_CONNECTED);
} else { // Expected
- crm_info("Connection to the CIB manager terminated");
+ crm_info("Disconnected from the CIB manager");
}
}
static void
do_cib_updated(const char *event, xmlNode * msg)
{
- if (pcmk__alert_in_patchset(msg, TRUE)) {
- controld_trigger_config();
+ const xmlNode *patchset = NULL;
+ const char *client_name = NULL;
+
+ crm_debug("Received CIB diff notification: DC=%s", pcmk__btoa(AM_I_DC));
+
+ if (cib__get_notify_patchset(msg, &patchset) != pcmk_rc_ok) {
+ return;
}
-}
-static void
-do_cib_replaced(const char *event, xmlNode * msg)
-{
- int call_id = 0;
- const char *client_id = crm_element_value(msg, F_CIB_CLIENTID);
- uint32_t change_section = cib_change_section_nodes
- |cib_change_section_status;
- long long value = 0;
+ if (cib__element_in_patchset(patchset, XML_CIB_TAG_ALERTS)
+ || cib__element_in_patchset(patchset, XML_CIB_TAG_CRMCONFIG)) {
+
+ controld_trigger_config();
+ }
- crm_debug("Updating the CIB after a replace: DC=%s", pcmk__btoa(AM_I_DC));
if (!AM_I_DC) {
+ // We're not in control of the join sequence
return;
}
- if ((crm_element_value_int(msg, F_CIB_CALLID, &call_id) == 0)
- && pcmk__str_eq(client_id, controld_globals.cib_client_id,
- pcmk__str_none)
- && controld_forget_cib_replace_call(call_id)) {
- // We requested this replace op. No need to restart the join.
+ client_name = crm_element_value(msg, F_CIB_CLIENTNAME);
+ if (!cib__client_triggers_refresh(client_name)) {
+ // The CIB is still accurate
return;
}
- if ((crm_element_value_ll(msg, F_CIB_CHANGE_SECTION, &value) < 0)
- || (value < 0) || (value > UINT32_MAX)) {
+ if (cib__element_in_patchset(patchset, XML_CIB_TAG_NODES)
+ || cib__element_in_patchset(patchset, XML_CIB_TAG_STATUS)) {
- crm_trace("Couldn't parse '%s' from message", F_CIB_CHANGE_SECTION);
- } else {
- change_section = (uint32_t) value;
- }
-
- if (pcmk_any_flags_set(change_section, cib_change_section_nodes
- |cib_change_section_status)) {
+ /* An unsafe client modified the nodes or status section. Ensure the
+ * node list is up-to-date, and start the join process again so we get
+ * everyone's current resource history.
+ */
+ if (client_name == NULL) {
+ client_name = crm_element_value(msg, F_CIB_CLIENTID);
+ }
+ crm_notice("Populating nodes and starting an election after %s event "
+ "triggered by %s",
+ event, pcmk__s(client_name, "(unidentified client)"));
- /* start the join process again so we get everyone's LRM status */
populate_cib_nodes(node_update_quick|node_update_all, __func__);
-
register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
}
}
@@ -186,12 +102,10 @@ controld_disconnect_cib_manager(void)
CRM_ASSERT(cib_conn != NULL);
- crm_info("Disconnecting from the CIB manager");
+ crm_debug("Disconnecting from the CIB manager");
controld_clear_fsa_input_flags(R_CIB_CONNECTED);
- cib_conn->cmds->del_notify_callback(cib_conn, T_CIB_REPLACE_NOTIFY,
- do_cib_replaced);
cib_conn->cmds->del_notify_callback(cib_conn, T_CIB_DIFF_NOTIFY,
do_cib_updated);
cib_free_callbacks(cib_conn);
@@ -201,8 +115,6 @@ controld_disconnect_cib_manager(void)
cib_scope_local|cib_discard_reply);
cib_conn->cmds->signoff(cib_conn);
}
-
- crm_notice("Disconnected from the CIB manager");
}
/* A_CIB_STOP, A_CIB_START, O_CIB_RESTART */
@@ -217,7 +129,6 @@ do_cib_control(long long action,
cib_t *cib_conn = controld_globals.cib_conn;
void (*dnotify_fn) (gpointer user_data) = handle_cib_disconnect;
- void (*replace_cb) (const char *event, xmlNodePtr msg) = do_cib_replaced;
void (*update_cb) (const char *event, xmlNodePtr msg) = do_cib_updated;
int rc = pcmk_ok;
@@ -264,11 +175,6 @@ do_cib_control(long long action,
crm_err("Could not set dnotify callback");
} else if (cib_conn->cmds->add_notify_callback(cib_conn,
- T_CIB_REPLACE_NOTIFY,
- replace_cb) != pcmk_ok) {
- crm_err("Could not set CIB notification callback (replace)");
-
- } else if (cib_conn->cmds->add_notify_callback(cib_conn,
T_CIB_DIFF_NOTIFY,
update_cb) != pcmk_ok) {
crm_err("Could not set CIB notification callback (update)");
@@ -276,8 +182,6 @@ do_cib_control(long long action,
} else {
controld_set_fsa_input_flags(R_CIB_CONNECTED);
cib_retries = 0;
- cib_conn->cmds->client_id(cib_conn, &controld_globals.cib_client_id,
- NULL);
}
if (!pcmk_is_set(controld_globals.fsa_input_register, R_CIB_CONNECTED)) {
@@ -310,11 +214,12 @@ do_cib_control(long long action,
unsigned int
cib_op_timeout(void)
{
+ // @COMPAT: Drop env_timeout at 3.0.0
static int env_timeout = -1;
unsigned int calculated_timeout = 0;
if (env_timeout == -1) {
- const char *env = getenv("PCMK_cib_timeout");
+ const char *env = pcmk__env_option(PCMK__ENV_CIB_TIMEOUT);
pcmk__scan_min_int(env, &env_timeout, MIN_CIB_OP_TIMEOUT);
crm_trace("Minimum CIB op timeout: %ds (environment: %s)",
@@ -401,67 +306,87 @@ cib_delete_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
/*!
* \internal
- * \brief Delete subsection of a node's CIB node_state
+ * \brief Get the XPath and description of a node state section to be deleted
*
- * \param[in] uname Desired node
- * \param[in] section Subsection of node_state to delete
- * \param[in] options CIB call options to use
+ * \param[in] uname Desired node
+ * \param[in] section Subsection of node_state to be deleted
+ * \param[out] xpath Where to store XPath of \p section
+ * \param[out] desc If not \c NULL, where to store description of \p section
*/
void
-controld_delete_node_state(const char *uname, enum controld_section_e section,
- int options)
+controld_node_state_deletion_strings(const char *uname,
+ enum controld_section_e section,
+ char **xpath, char **desc)
{
- cib_t *cib_conn = controld_globals.cib_conn;
-
- char *xpath = NULL;
- char *desc = NULL;
+ const char *desc_pre = NULL;
// Shutdown locks that started before this time are expired
long long expire = (long long) time(NULL)
- controld_globals.shutdown_lock_limit;
- CRM_CHECK(uname != NULL, return);
switch (section) {
case controld_section_lrm:
- xpath = crm_strdup_printf(XPATH_NODE_LRM, uname);
- desc = crm_strdup_printf("resource history for node %s", uname);
+ *xpath = crm_strdup_printf(XPATH_NODE_LRM, uname);
+ desc_pre = "resource history";
break;
case controld_section_lrm_unlocked:
- xpath = crm_strdup_printf(XPATH_NODE_LRM_UNLOCKED,
- uname, uname, expire);
- desc = crm_strdup_printf("resource history (other than shutdown "
- "locks) for node %s", uname);
+ *xpath = crm_strdup_printf(XPATH_NODE_LRM_UNLOCKED,
+ uname, uname, expire);
+ desc_pre = "resource history (other than shutdown locks)";
break;
case controld_section_attrs:
- xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
- desc = crm_strdup_printf("transient attributes for node %s", uname);
+ *xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
+ desc_pre = "transient attributes";
break;
case controld_section_all:
- xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
- desc = crm_strdup_printf("all state for node %s", uname);
+ *xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
+ desc_pre = "all state";
break;
case controld_section_all_unlocked:
- xpath = crm_strdup_printf(XPATH_NODE_ALL_UNLOCKED,
- uname, uname, expire, uname);
- desc = crm_strdup_printf("all state (other than shutdown locks) "
- "for node %s", uname);
+ *xpath = crm_strdup_printf(XPATH_NODE_ALL_UNLOCKED,
+ uname, uname, expire, uname);
+ desc_pre = "all state (other than shutdown locks)";
+ break;
+ default:
+ // We called this function incorrectly
+ CRM_ASSERT(false);
break;
}
- if (cib_conn == NULL) {
- crm_warn("Unable to delete %s: no CIB connection", desc);
- free(desc);
- } else {
- int call_id;
-
- cib__set_call_options(options, "node state deletion",
- cib_xpath|cib_multiple);
- call_id = cib_conn->cmds->remove(cib_conn, xpath, NULL, options);
- crm_info("Deleting %s (via CIB call %d) " CRM_XS " xpath=%s",
- desc, call_id, xpath);
- fsa_register_cib_callback(call_id, desc, cib_delete_callback);
- // CIB library handles freeing desc
+ if (desc != NULL) {
+ *desc = crm_strdup_printf("%s for node %s", desc_pre, uname);
}
+}
+
+/*!
+ * \internal
+ * \brief Delete subsection of a node's CIB node_state
+ *
+ * \param[in] uname Desired node
+ * \param[in] section Subsection of node_state to delete
+ * \param[in] options CIB call options to use
+ */
+void
+controld_delete_node_state(const char *uname, enum controld_section_e section,
+ int options)
+{
+ cib_t *cib = controld_globals.cib_conn;
+ char *xpath = NULL;
+ char *desc = NULL;
+ int cib_rc = pcmk_ok;
+
+ CRM_ASSERT((uname != NULL) && (cib != NULL));
+
+ controld_node_state_deletion_strings(uname, section, &xpath, &desc);
+
+ cib__set_call_options(options, "node state deletion",
+ cib_xpath|cib_multiple);
+ cib_rc = cib->cmds->remove(cib, xpath, NULL, options);
+ fsa_register_cib_callback(cib_rc, desc, cib_delete_callback);
+ crm_info("Deleting %s (via CIB call %d) " CRM_XS " xpath=%s",
+ desc, cib_rc, xpath);
+
+ // CIB library handles freeing desc
free(xpath);
}
@@ -491,11 +416,12 @@ controld_delete_resource_history(const char *rsc_id, const char *node,
char *desc = NULL;
char *xpath = NULL;
int rc = pcmk_rc_ok;
+ cib_t *cib = controld_globals.cib_conn;
CRM_CHECK((rsc_id != NULL) && (node != NULL), return EINVAL);
desc = crm_strdup_printf("resource history for %s on %s", rsc_id, node);
- if (controld_globals.cib_conn == NULL) {
+ if (cib == NULL) {
crm_err("Unable to clear %s: no CIB connection", desc);
free(desc);
return ENOTCONN;
@@ -503,9 +429,10 @@ controld_delete_resource_history(const char *rsc_id, const char *node,
// Ask CIB to delete the entry
xpath = crm_strdup_printf(XPATH_RESOURCE_HISTORY, node, rsc_id);
- rc = cib_internal_op(controld_globals.cib_conn, PCMK__CIB_REQUEST_DELETE,
- NULL, xpath, NULL, NULL, call_options|cib_xpath,
- user_name);
+
+ cib->cmds->set_user(cib, user_name);
+ rc = cib->cmds->remove(cib, xpath, NULL, call_options|cib_xpath);
+ cib->cmds->set_user(cib, NULL);
if (rc < 0) {
rc = pcmk_legacy2rc(rc);
@@ -841,10 +768,17 @@ cib_rsc_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *use
case pcmk_ok:
case -pcmk_err_diff_failed:
case -pcmk_err_diff_resync:
- crm_trace("Resource update %d complete: rc=%d", call_id, rc);
+ crm_trace("Resource history update completed (call=%d rc=%d)",
+ call_id, rc);
break;
default:
- crm_warn("Resource update %d failed: (rc=%d) %s", call_id, rc, pcmk_strerror(rc));
+ if (call_id > 0) {
+ crm_warn("Resource history update %d failed: %s "
+ CRM_XS " rc=%d", call_id, pcmk_strerror(rc), rc);
+ } else {
+ crm_warn("Resource history update failed: %s " CRM_XS " rc=%d",
+ pcmk_strerror(rc), rc);
+ }
}
if (call_id == pending_rsc_update) {
@@ -863,10 +797,11 @@ should_preserve_lock(lrmd_event_data_t *op)
if (!pcmk_is_set(controld_globals.flags, controld_shutdown_lock_enabled)) {
return false;
}
- if (!strcmp(op->op_type, RSC_STOP) && (op->rc == PCMK_OCF_OK)) {
+ if (!strcmp(op->op_type, PCMK_ACTION_STOP) && (op->rc == PCMK_OCF_OK)) {
return true;
}
- if (!strcmp(op->op_type, RSC_STATUS) && (op->rc == PCMK_OCF_NOT_RUNNING)) {
+ if (!strcmp(op->op_type, PCMK_ACTION_MONITOR)
+ && (op->rc == PCMK_OCF_NOT_RUNNING)) {
return true;
}
return false;
@@ -876,10 +811,10 @@ should_preserve_lock(lrmd_event_data_t *op)
* \internal
* \brief Request a CIB update
*
- * \param[in] section Section of CIB to update
- * \param[in,out] data New XML of CIB section to update
- * \param[in] options CIB call options
- * \param[in] callback If not NULL, set this as the operation callback
+ * \param[in] section Section of CIB to update
+ * \param[in] data New XML of CIB section to update
+ * \param[in] options CIB call options
+ * \param[in] callback If not \c NULL, set this as the operation callback
*
* \return Standard Pacemaker return code
*
@@ -890,14 +825,13 @@ int
controld_update_cib(const char *section, xmlNode *data, int options,
void (*callback)(xmlNode *, int, int, xmlNode *, void *))
{
+ cib_t *cib = controld_globals.cib_conn;
int cib_rc = -ENOTCONN;
CRM_ASSERT(data != NULL);
- if (controld_globals.cib_conn != NULL) {
- cib_rc = cib_internal_op(controld_globals.cib_conn,
- PCMK__CIB_REQUEST_MODIFY, NULL, section,
- data, NULL, options, NULL);
+ if (cib != NULL) {
+ cib_rc = cib->cmds->modify(cib, section, data, options);
if (cib_rc >= 0) {
crm_debug("Submitted CIB update %d for %s section",
cib_rc, section);
@@ -1047,7 +981,6 @@ controld_delete_action_history(const lrmd_event_data_t *op)
controld_globals.cib_conn->cmds->remove(controld_globals.cib_conn,
XML_CIB_TAG_STATUS, xml_top,
cib_none);
-
crm_log_xml_trace(xml_top, "op:cancel");
free_xml(xml_top);
}
@@ -1087,7 +1020,6 @@ controld_cib_delete_last_failure(const char *rsc_id, const char *node,
{
char *xpath = NULL;
char *last_failure_key = NULL;
-
CRM_CHECK((rsc_id != NULL) && (node != NULL), return);
// Generate XPath to match desired entry