Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4639405
cib.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
cib.c
View Options
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <unistd.h> /* sleep */
#include <crm/common/alerts_internal.h>
#include <crm/common/xml.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crmd.h>
#include <crmd_callbacks.h> /* crmd_cib_connection_destroy */
#include <crmd_fsa.h>
#include <crmd_messages.h>
struct crm_subsystem_s *cib_subsystem = NULL;
int cib_retries = 0;
static void
do_cib_updated(const char *event, xmlNode * msg)
{
if (crm_patchset_contains_alert(msg, TRUE)) {
mainloop_set_trigger(config_read);
}
}
static void
revision_check_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
int cmp = -1;
xmlNode *generation = NULL;
const char *revision = NULL;
if (rc != pcmk_ok) {
fsa_data_t *msg_data = NULL;
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
return;
}
generation = output;
CRM_CHECK(safe_str_eq(crm_element_name(generation), XML_TAG_CIB),
crm_log_xml_err(output, __FUNCTION__); return);
crm_trace("Checking our feature revision %s is allowed", CRM_FEATURE_SET);
revision = crm_element_value(generation, XML_ATTR_CRM_VERSION);
cmp = compare_version(revision, CRM_FEATURE_SET);
if (cmp > 0) {
crm_err("Shutting down because the current configuration is not supported by this version "
CRM_XS " build=%s supported=%s current=%s",
PACEMAKER_VERSION, CRM_FEATURE_SET, revision);
/* go into a stall state */
register_fsa_error_adv(C_FSA_INTERNAL, I_SHUTDOWN, NULL, NULL, __FUNCTION__);
return;
}
}
static void
do_cib_replaced(const char *event, xmlNode * msg)
{
crm_debug("Updating the CIB after a replace: DC=%s", AM_I_DC ? "true" : "false");
if (AM_I_DC == FALSE) {
return;
} else if (fsa_state == S_FINALIZE_JOIN && is_set(fsa_input_register, R_CIB_ASKED)) {
/* no need to restart the join - we asked for this replace op */
return;
}
/* start the join process again so we get everyone's LRM status */
populate_cib_nodes(node_update_quick|node_update_all, __FUNCTION__);
register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
}
/* A_CIB_STOP, A_CIB_START, O_CIB_RESTART */
void
do_cib_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input, fsa_data_t * msg_data)
{
CRM_ASSERT(fsa_cib_conn != NULL);
if (action & A_CIB_STOP) {
if (fsa_cib_conn->state != cib_disconnected && last_resource_update != 0) {
crm_info("Waiting for resource update %d to complete", last_resource_update);
crmd_fsa_stall(FALSE);
return;
}
crm_info("Disconnecting CIB");
clear_bit(fsa_input_register, R_CIB_CONNECTED);
fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated);
if (fsa_cib_conn->state != cib_disconnected) {
fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local);
fsa_cib_conn->cmds->signoff(fsa_cib_conn);
}
crm_notice("Disconnected from the CIB");
}
if (action & A_CIB_START) {
int rc = pcmk_ok;
if (cur_state == S_STOPPING) {
crm_err("Ignoring request to start the CIB after shutdown");
return;
}
rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
if (rc != pcmk_ok) {
/* a short wait that usually avoids stalling the FSA */
sleep(1);
rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
}
if (rc != pcmk_ok) {
crm_info("Could not connect to the CIB service: %s", pcmk_strerror(rc));
} else if (pcmk_ok !=
fsa_cib_conn->cmds->set_connection_dnotify(fsa_cib_conn,
crmd_cib_connection_destroy)) {
crm_err("Could not set dnotify callback");
} else if (pcmk_ok !=
fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY,
do_cib_replaced)) {
crm_err("Could not set CIB notification callback (replace)");
} else if (pcmk_ok !=
fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY,
do_cib_updated)) {
crm_err("Could not set CIB notification callback (update)");
} else {
set_bit(fsa_input_register, R_CIB_CONNECTED);
}
if (is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) {
cib_retries++;
crm_warn("Couldn't complete CIB registration %d"
" times... pause and retry", cib_retries);
if (cib_retries < 30) {
crm_timer_start(wait_timer);
crmd_fsa_stall(FALSE);
} else {
crm_err("Could not complete CIB"
" registration %d times..." " hard error", cib_retries);
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
}
} else {
int call_id = 0;
crm_info("CIB connection established");
call_id = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local);
fsa_register_cib_callback(call_id, FALSE, NULL, revision_check_callback);
cib_retries = 0;
}
}
}
/*!
* \internal
* \brief Get CIB call options to use local scope if master unavailable
*
* \return CIB call options
*/
int crmd_cib_smart_opt()
{
int call_opt = cib_quorum_override;
if (fsa_state == S_ELECTION || fsa_state == S_PENDING) {
crm_info("Sending update to local CIB in state: %s", fsa_state2string(fsa_state));
call_opt |= cib_scope_local;
}
return call_opt;
}
/*!
* \internal
* \brief Check whether an action type should be recorded in the CIB
*
* \param[in] action Action type
*
* \return TRUE if action should be recorded, FALSE otherwise
*/
bool
controld_action_is_recordable(const char *action)
{
if (safe_str_eq(action, CRMD_ACTION_CANCEL)
|| safe_str_eq(action, CRMD_ACTION_DELETE)
|| safe_str_eq(action, CRMD_ACTION_NOTIFY)
|| safe_str_eq(action, CRMD_ACTION_METADATA)) {
return FALSE;
}
return TRUE;
}
static void
cib_delete_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
void *user_data)
{
char *desc = user_data;
if (rc == 0) {
crm_debug("Deletion of %s (via CIB call %d) succeeded", desc, call_id);
} else {
crm_warn("Deletion of %s (via CIB call %d) failed: %s " CRM_XS " rc=%d",
desc, call_id, pcmk_strerror(rc), rc);
}
}
// Searches for various portions of node_state to delete
// Match a particular node's node_state (takes node name 1x)
#define XPATH_NODE_STATE "//" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']"
// Node's lrm section (name 1x)
#define XPATH_NODE_LRM XPATH_NODE_STATE "/" XML_CIB_TAG_LRM
// Node's transient_attributes section (name 1x)
#define XPATH_NODE_ATTRS XPATH_NODE_STATE "/" XML_TAG_TRANSIENT_NODEATTRS
// Everything under node_state (name 1x)
#define XPATH_NODE_ALL XPATH_NODE_STATE "/*"
/*!
* \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)
{
char *xpath = NULL;
char *desc = NULL;
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);
break;
case controld_section_attrs:
xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
desc = crm_strdup_printf("transient attributes for node %s", uname);
break;
case controld_section_all:
xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
desc = crm_strdup_printf("all state for node %s", uname);
break;
}
if (fsa_cib_conn == NULL) {
crm_warn("Unable to delete %s: no CIB connection", desc);
free(desc);
} else {
int call_id;
options |= cib_quorum_override|cib_xpath;
call_id = fsa_cib_conn->cmds->delete(fsa_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, FALSE, desc, cib_delete_callback);
// CIB library handles freeing desc
}
free(xpath);
}
// Takes node name and resource ID
#define XPATH_RESOURCE_HISTORY "//" XML_CIB_TAG_STATE \
"[@" XML_ATTR_UNAME "='%s'] /" \
XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES \
"/" XML_LRM_TAG_RESOURCE \
"[@" XML_ATTR_ID "='%s']"
// @TODO could add "and @XML_CONFIG_ATTR_SHUTDOWN_LOCK" to limit to locks
/*!
* \internal
* \brief Clear resource history from CIB for a given resource and node
*
* \param[in] rsc_id ID of resource to be cleared
* \param[in] node Node whose resource history should be cleared
* \param[in] user_name ACL user name to use
* \param[in] call_options CIB call options
*
* \return Standard Pacemaker return code
*/
int
controld_delete_resource_history(const char *rsc_id, const char *node,
const char *user_name, int call_options)
{
char *desc = NULL;
char *xpath = NULL;
int rc = pcmk_rc_ok;
CRM_CHECK((rsc_id != NULL) && (node != NULL), return EINVAL);
desc = crm_strdup_printf("resource history for %s on %s", rsc_id, node);
if (fsa_cib_conn == NULL) {
crm_err("Unable to clear %s: no CIB connection", desc);
free(desc);
return ENOTCONN;
}
// Ask CIB to delete the entry
xpath = crm_strdup_printf(XPATH_RESOURCE_HISTORY, node, rsc_id);
rc = cib_internal_op(fsa_cib_conn, CIB_OP_DELETE, NULL, xpath, NULL,
NULL, call_options|cib_xpath, user_name);
if (rc < 0) {
rc = pcmk_legacy2rc(rc);
crm_err("Could not delete resource status of %s on %s%s%s: %s "
CRM_XS " rc=%d", rsc_id, node,
(user_name? " for user " : ""), (user_name? user_name : ""),
pcmk_rc_str(rc), rc);
free(desc);
free(xpath);
return rc;
}
if (is_set(call_options, cib_sync_call)) {
if (is_set(call_options, cib_dryrun)) {
crm_debug("Deletion of %s would succeed", desc);
} else {
crm_debug("Deletion of %s succeeded", desc);
}
free(desc);
} else {
crm_info("Clearing %s (via CIB call %d) " CRM_XS " xpath=%s",
desc, rc, xpath);
fsa_register_cib_callback(rc, FALSE, desc, cib_delete_callback);
// CIB library handles freeing desc
}
free(xpath);
return pcmk_rc_ok;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Jul 10, 2:55 AM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1981022
Default Alt Text
cib.c (12 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment