Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624135
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/crmd/crmd_fsa.h b/crm/crmd/crmd_fsa.h
index 925bc43a5d..7904cb1d50 100644
--- a/crm/crmd/crmd_fsa.h
+++ b/crm/crmd/crmd_fsa.h
@@ -1,132 +1,134 @@
-/* $Id: crmd_fsa.h,v 1.18 2004/05/18 14:28:04 andrew Exp $ */
+/* $Id: crmd_fsa.h,v 1.19 2004/05/28 07:55:28 andrew Exp $ */
/*
* 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef XML_CRM_FSA__H
#define XML_CRM_FSA__H
#include <fsa_defines.h>
#include <ocf/oc_event.h>
#include <clplumbing/ipc.h>
#include <hb_api.h>
#include <libxml/tree.h>
#include <lrm/lrm_api.h>
+#include <crm/crm.h>
struct ccm_data
{
const oc_ev_membership_t *oc;
oc_ed_t *event;
};
struct oc_node_list_s
{
int members_size;
GHashTable *members; // contents: oc_node_t *
int new_members_size;
GHashTable *new_members; // contents: oc_node_t *
int dead_members_size;
GHashTable *dead_members; // contents: oc_node_t *
};
/* copy from struct client_child in heartbeat.h
*
* Plus a couple of other things
*/
typedef struct oc_node_list_s oc_node_list_t;
struct crm_subsystem_s {
pid_t pid; /* Process id of child process */
int respawn; /* Respawn it if it dies? */
int respawncount; /* Last time we respawned this command */
int shortrcount; /* How many times has it respawned too fast? */
const char* command; /* What command to run? */
const char* path; /* Path (argv[0])? */
/* extras */
const char* name;
IPC_Channel *ipc; /* How can we communicate with it */
long long flag; /* */
};
typedef struct fsa_timer_s fsa_timer_t;
struct fsa_timer_s
{
guint source_id; /* timer source id */
uint period_ms; /* timer period */
enum crmd_fsa_input fsa_input;
gboolean (*callback)(gpointer data);
};
extern enum crmd_fsa_state s_crmd_fsa(enum crmd_fsa_cause cause,
enum crmd_fsa_input initial_input,
void *data);
extern long long clear_flags(long long actions,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input cur_input);
/* Utilities */
extern long long toggle_bit (long long action_list, long long action);
extern long long clear_bit (long long action_list, long long action);
extern long long set_bit (long long action_list, long long action);
extern void toggle_bit_inplace(long long *action_list, long long action);
extern void clear_bit_inplace (long long *action_list, long long action);
extern void set_bit_inplace (long long *action_list, long long action);
extern gboolean is_set(long long action_list, long long action);
extern gboolean startTimer(fsa_timer_t *timer);
extern gboolean stopTimer(fsa_timer_t *timer);
extern gboolean timer_popped(gpointer data);
extern gboolean do_dc_heartbeat(gpointer data);
/* Global FSA stuff */
extern enum crmd_fsa_state fsa_state;
extern oc_node_list_t *fsa_membership_copy;
extern ll_cluster_t *fsa_cluster_conn;
extern ll_lrm_t *fsa_lrm_conn;
extern long long fsa_input_register;
extern const char *fsa_our_uname;
extern char *fsa_pe_ref; // the last invocation of the PE
+extern const char *fsa_our_dc;
extern fsa_timer_t *election_trigger; /* */
extern fsa_timer_t *election_timeout; /* */
extern fsa_timer_t *shutdown_escalation_timmer; /* */
extern fsa_timer_t *dc_heartbeat;
extern fsa_timer_t *integration_timer;
extern struct crm_subsystem_s *cib_subsystem;
extern struct crm_subsystem_s *te_subsystem;
extern struct crm_subsystem_s *pe_subsystem;
extern void cleanup_subsystem(struct crm_subsystem_s *the_subsystem);
extern enum crmd_fsa_input send_cib_status_update(xmlNodePtr update);
extern xmlNodePtr create_node_state(const char *node, const char *state,
const char *exp_state, xmlNodePtr lrm_data);
extern xmlNodePtr do_update_cib_nodes(xmlNodePtr updates);
#define AM_I_DC is_set(fsa_input_register, R_THE_DC)
#define AM_I_OPERATIONAL (is_set(fsa_input_register, R_STARTING)==FALSE)
#include <fsa_proto.h>
#endif
diff --git a/crm/crmd/election.c b/crm/crmd/election.c
index b8e522bef4..758905d552 100644
--- a/crm/crmd/election.c
+++ b/crm/crmd/election.c
@@ -1,677 +1,732 @@
/*
* 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <portability.h>
#include <crm/crm.h>
#include <crmd_fsa.h>
#include <libxml/tree.h>
#include <crm/msg_xml.h>
#include <crm/common/xmlutils.h>
#include <crm/common/ipcutils.h>
#include <crm/common/msgutils.h>
#include <crm/cib.h>
#include <string.h>
#include <crmd_messages.h>
#include <crm/dmalloc_wrapper.h>
GHashTable *joined_nodes = NULL;
void ghash_count_vote(gpointer key, gpointer value, gpointer user_data);
void ghash_send_welcome(gpointer key, gpointer value, gpointer user_data);
/* A_ELECTION_VOTE */
enum crmd_fsa_input
do_election_vote(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input election_result = I_NULL;
FNIN();
/* dont vote if we're in one of these states or wanting to shut down */
switch(cur_state) {
case S_RECOVERY:
case S_RECOVERY_DC:
case S_STOPPING:
case S_RELEASE_DC:
case S_TERMINATE:
FNRET(I_NULL);
// log warning
break;
default:
if(is_set(fsa_input_register, R_SHUTDOWN)) {
FNRET(I_NULL);
// log warning
}
break;
}
send_request(NULL, NULL, CRM_OPERATION_VOTE, NULL, CRM_SYSTEM_CRMD, NULL);
FNRET(election_result);
}
gboolean
timer_popped(gpointer data)
{
fsa_timer_t *timer = (fsa_timer_t *)data;
cl_log(LOG_INFO, "#!!#!!# Timer %s just popped!",
fsa_input2string(timer->fsa_input));
stopTimer(timer); // dont make it go off again
s_crmd_fsa(C_TIMER_POPPED, timer->fsa_input, NULL);
return TRUE;
}
gboolean
do_dc_heartbeat(gpointer data)
{
fsa_timer_t *timer = (fsa_timer_t *)data;
// cl_log(LOG_DEBUG, "#!!#!!# Heartbeat timer just popped!");
gboolean was_sent = send_request(NULL, NULL, CRM_OPERATION_HBEAT,
NULL, CRM_SYSTEM_CRMD, NULL);
if(was_sent == FALSE) {
// this is bad
stopTimer(timer); // dont make it go off again
s_crmd_fsa(C_HEARTBEAT_FAILED, I_SHUTDOWN, NULL);
}
return TRUE;
}
struct election_data_s
{
const char *winning_uname;
unsigned int winning_bornon;
};
/* A_ELECTION_COUNT */
enum crmd_fsa_input
do_election_count_vote(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
gboolean we_loose = FALSE;
xmlNodePtr vote = (xmlNodePtr)data;
enum crmd_fsa_input election_result = I_NULL;
const char *vote_from = xmlGetProp(vote, XML_ATTR_HOSTFROM);
FNIN();
if(vote_from == NULL || strcmp(vote_from, fsa_our_uname) == 0) {
// dont count our own vote
FNRET(election_result);
}
if(fsa_membership_copy->members_size < 1) {
// if even we are not in the cluster then we should not vote
FNRET(I_FAIL);
}
oc_node_t *our_node = (oc_node_t*)
g_hash_table_lookup(fsa_membership_copy->members, fsa_our_uname);
oc_node_t *your_node = (oc_node_t*)
g_hash_table_lookup(fsa_membership_copy->members, vote_from);
#if 0
cl_log(LOG_DEBUG, "%s (bornon=%d), our bornon (%d)",
vote_from, our_node->born, my_born);
cl_log(LOG_DEBUG, "%s %s %s",
fsa_our_uname,
strcmp(fsa_our_uname, vote_from) < 0?"<":">=",
vote_from);
#endif
if(is_set(fsa_input_register, R_SHUTDOWN)) {
cl_log(LOG_DEBUG,
"Election fail: we are shutting down");
we_loose = TRUE;
} else if(our_node == NULL) {
cl_log(LOG_DEBUG,
"Election fail: we dont exist in the CCM list");
we_loose = TRUE;
} else if(your_node == NULL) {
cl_log(LOG_ERR, "The other side doesnt exist in the CCM list");
} else if(your_node->node_born_on < our_node->node_born_on) {
cl_log(LOG_DEBUG, "Election fail: born_on");
we_loose = TRUE;
} else if(your_node->node_born_on == our_node->node_born_on
&& strcmp(fsa_our_uname, vote_from) > 0) {
cl_log(LOG_DEBUG, "Election fail: uname");
we_loose = TRUE;
} else {
struct election_data_s election_data;
election_data.winning_uname = NULL;
election_data.winning_bornon = -1; // maximum integer
CRM_DEBUG("We might win... we should vote (possibly again)");
election_result = I_DC_TIMEOUT; // new "default"
g_hash_table_foreach(fsa_membership_copy->members,
ghash_count_vote, &election_data);
cl_log(LOG_DEBUG, "Election winner should be %s (born_on=%d)",
election_data.winning_uname, election_data.winning_bornon);
if(safe_str_eq(election_data.winning_uname, fsa_our_uname)){
cl_log(LOG_DEBUG, "Election win: lowest born_on and uname");
election_result = I_ELECTION_DC;
}
}
if(we_loose) {
if(fsa_input_register & R_THE_DC) {
cl_log(LOG_DEBUG, "Give up the DC");
election_result = I_RELEASE_DC;
} else {
cl_log(LOG_DEBUG, "We werent the DC anyway");
election_result = I_NOT_DC;
}
}
if(we_loose || election_result == I_ELECTION_DC) {
// cancel timer, its been decided
stopTimer(election_timeout);
}
FNRET(election_result);
}
/* A_ELECT_TIMER_START, A_ELECTION_TIMEOUT */
// we won
enum crmd_fsa_input
do_election_timer_ctrl(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
if(action & A_ELECT_TIMER_START) {
CRM_DEBUG("Starting the election timer...");
startTimer(election_timeout);
} else if(action & A_ELECT_TIMER_STOP || action & A_ELECTION_TIMEOUT) {
CRM_DEBUG("Stopping the election timer...");
stopTimer(election_timeout);
} else {
cl_log(LOG_ERR, "unexpected action %s",
fsa_action2string(action));
}
if(action & A_ELECTION_TIMEOUT) {
CRM_DEBUG("The election timer went off, we win!");
FNRET(I_ELECTION_DC);
}
FNRET(I_NULL);
}
/* A_DC_TIMER_STOP, A_DC_TIMER_START */
enum crmd_fsa_input
do_dc_timer_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
gboolean timer_op_ok = TRUE;
FNIN();
if(action & A_DC_TIMER_STOP) {
timer_op_ok = stopTimer(election_trigger);
}
/* dont start a timer that wasnt already running */
if(action & A_DC_TIMER_START && timer_op_ok) {
startTimer(election_trigger);
}
FNRET(I_NULL);
}
/* A_DC_TAKEOVER */
enum crmd_fsa_input
do_dc_takeover(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
CRM_DEBUG("################## Taking over the DC ##################");
set_bit_inplace(&fsa_input_register, R_THE_DC);
CRM_DEBUG("Am I the DC? %s", AM_I_DC?"yes":"no");
+ fsa_our_dc = NULL;
set_bit_inplace(&fsa_input_register, R_JOIN_OK);
set_bit_inplace(&fsa_input_register, R_INVOKE_PE);
clear_bit_inplace(&fsa_input_register, R_CIB_DONE);
clear_bit_inplace(&fsa_input_register, R_HAVE_CIB);
startTimer(dc_heartbeat);
FNRET(I_NULL);
}
/* A_DC_RELEASE */
enum crmd_fsa_input
do_dc_release(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input result = I_NULL;
FNIN();
CRM_DEBUG("################## Releasing the DC ##################");
stopTimer(dc_heartbeat);
if(action & A_DC_RELEASE) {
clear_bit_inplace(&fsa_input_register, R_THE_DC);
/* get a new CIB from the new DC */
clear_bit_inplace(&fsa_input_register, R_HAVE_CIB);
} else if (action & A_DC_RELEASED) {
if(cur_state == S_STOPPING) {
result = I_SHUTDOWN; // necessary?
result = I_RELEASE_SUCCESS;
}
#if 0
else if( are there errors ) {
// we cant stay up if not healthy
// or perhaps I_ERROR and go to S_RECOVER?
result = I_SHUTDOWN;
}
#endif
else
result = I_RELEASE_SUCCESS;
} else {
cl_log(LOG_ERR, "Warning, do_dc_release invoked for action %s",
fsa_action2string(action));
}
CRM_DEBUG("Am I still the DC? %s", AM_I_DC?"yes":"no");
FNRET(result);
}
/* A_JOIN_WELCOME, A_JOIN_WELCOME_ALL */
enum crmd_fsa_input
do_send_welcome(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
int num_sent = 0;
FNIN();
if(action & A_JOIN_WELCOME && data == NULL) {
cl_log(LOG_ERR,
"Attempt to send welcome message "
"without a message to reply to!");
FNRET(I_NULL);
} else if(action & A_JOIN_WELCOME) {
xmlNodePtr welcome = (xmlNodePtr)data;
const char *join_to = xmlGetProp(welcome, XML_ATTR_HOSTFROM);
if(join_to != NULL) {
/*
xmlNodePtr update =
create_node_state(new_node, "active", "active", NULL);
xmlNodePtr tmp1 = create_cib_fragment(update, NULL);
send_request(NULL, tmp1, "update", NULL, CRM_SYSTEM_DCIB);
*/
send_request(NULL, NULL, CRM_OPERATION_WELCOME,
join_to, CRM_SYSTEM_CRMD, NULL);
} else {
cl_log(LOG_ERR, "No recipient for welcome message");
}
FNRET(I_NULL);
}
// welcome everyone...
/* Give everyone a chance to join before invoking the PolicyEngine */
stopTimer(integration_timer);
startTimer(integration_timer);
if(joined_nodes != NULL) {
g_hash_table_destroy(joined_nodes);
joined_nodes = g_hash_table_new(&g_str_hash, &g_str_equal);
}
// reset everyones status back to down or in_ccm in the CIB
xmlNodePtr update = NULL;
xmlNodePtr cib_copy = get_cib_copy();
xmlNodePtr tmp1 = get_object_root(XML_CIB_TAG_STATUS, cib_copy);
xmlNodePtr node_entry = tmp1->children;
-
// catch any nodes that are active in the CIB but not in the CCM list
while(node_entry != NULL){
const char *state = "down";
const char *node_id = xmlGetProp(node_entry, "id");
gpointer a_node =
- g_hash_table_lookup(fsa_membership_copy->members, node_id);
+ g_hash_table_lookup(fsa_membership_copy->members,
+ node_id);
node_entry = node_entry->next;
- if(a_node != NULL || (safe_str_eq(fsa_our_uname, node_id))) {
+ if(safe_str_eq(fsa_our_uname, node_id)) {
+ continue;
+
+ } else if(a_node != NULL) {
// handled by do_update_cib_nodes()
continue;
}
tmp1 = create_node_state(node_id, state, NULL, NULL);
if(update == NULL) {
update = tmp1;
} else {
update = xmlAddSibling(update, tmp1);
}
}
// now process the CCM data
free_xml(do_update_cib_nodes(update));
free_xml(cib_copy);
-
+
+ /* Avoid ordered message delays caused when the CRMd proc
+ * isnt running yet (ie. send as a broadcast msg which are never
+ * sent ordered.
+ */
+ send_request(NULL, NULL, CRM_OPERATION_WELCOME,
+ NULL, CRM_SYSTEM_CRMD, NULL);
+
g_hash_table_foreach(fsa_membership_copy->members,
ghash_send_welcome, &num_sent);
/* No point hanging around in S_INTEGRATION if we're the only ones here! */
if(num_sent == 0) {
// that was the last outstanding join ack)
cl_log(LOG_INFO,"That was the last outstanding join ack");
FNRET(I_SUCCESS);
+
} else {
cl_log(LOG_DEBUG,
"Still waiting on %d outstanding join acks",
num_sent);
//dont waste time by invoking the pe yet;
}
FNRET(I_NULL);
}
xmlNodePtr
create_node_state(const char *node, const char *state,
const char *exp_state, xmlNodePtr lrm_data)
{
xmlNodePtr node_state = create_xml_node(NULL, XML_CIB_TAG_STATE);
set_xml_property_copy(node_state, XML_ATTR_ID, node);
set_xml_property_copy(node_state, "state", state);
if(exp_state != NULL) {
set_xml_property_copy(node_state, "exp_state", exp_state);
}
if(lrm_data != NULL) {
// set_xml_property_copy(data, "replace_lrm", "true");
add_node_copy(node_state, lrm_data);
}
xml_message_debug(node_state, "created");
return node_state;
}
/* A_JOIN_ACK */
enum crmd_fsa_input
do_ack_welcome(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
xmlNodePtr welcome = (xmlNodePtr)data;
xmlNodePtr cib_copy;
xmlNodePtr tmp1;
xmlNodePtr tmp2;
FNIN();
#if 0
if(we are sick) {
log error ;
FNRET(I_NULL);
}
#endif
-
+ fsa_our_dc = xmlGetProp(welcome, XML_ATTR_HOSTFROM);
+
+ if(fsa_our_dc == NULL) {
+ cl_log(LOG_ERR, "Failed to determin our DC");
+ FNRET(I_FAIL);
+ }
+
+ /* send our status section to the DC */
cib_copy = get_cib_copy();
tmp1 = get_object_root(XML_CIB_TAG_STATUS, cib_copy);
tmp2 = create_cib_fragment(tmp1, NULL);
send_ha_reply(fsa_cluster_conn, welcome, tmp2);
free_xml(tmp2);
free_xml(cib_copy);
FNRET(I_NULL);
}
/* A_ANNOUNCE */
enum crmd_fsa_input
do_announce(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
+ xmlNodePtr msg = (xmlNodePtr)data;
FNIN();
/* Once we hear from the DC, we can stop the timer
*
* This timer was started either on startup or when a node
* left the CCM list
*/
/* dont announce if we're in one of these states */
switch(cur_state) {
case S_RECOVERY:
case S_RECOVERY_DC:
case S_RELEASE_DC:
case S_TERMINATE:
cl_log(LOG_WARNING,
"Do not announce ourselves in state %s",
fsa_state2string(cur_state));
FNRET(I_NULL);
break;
default:
break;
}
if(AM_I_OPERATIONAL) {
+ const char *from = xmlGetProp(msg, XML_ATTR_HOSTFROM);
+
+ if(from == NULL) {
+ cl_log(LOG_ERR, "Failed to origin of ping message");
+ FNRET(I_FAIL);
+ }
+
send_request(NULL, NULL, CRM_OPERATION_ANNOUNCE,
- NULL, CRM_SYSTEM_DC, NULL);
+ from, CRM_SYSTEM_DC, NULL);
} else {
/* Delay announce until we have finished local startup */
cl_log(LOG_WARNING,
"Delaying announce until local startup is complete");
FNRET(I_NULL);
}
FNRET(I_NULL);
}
/* A_JOIN_PROCESS_ACK */
enum crmd_fsa_input
do_process_welcome_ack(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
xmlNodePtr tmp1;
+ xmlNodePtr tmp2;
xmlNodePtr cib_fragment;
+ xmlNodePtr msg_cib;
xmlNodePtr join_ack = (xmlNodePtr)data;
int size = 0;
gboolean is_a_member = FALSE;
const char *join_from = xmlGetProp(join_ack, XML_ATTR_HOSTFROM);
const char *ref = xmlGetProp(join_ack, XML_ATTR_REFERENCE);
FNIN();
gpointer join_node =
g_hash_table_lookup(fsa_membership_copy->members, join_from);
if(join_node != NULL) {
is_a_member = TRUE;
}
cib_fragment = find_xml_node(join_ack, XML_TAG_FRAGMENT);
if(is_a_member == FALSE) {
cl_log(LOG_ERR, "Node %s is not known to us (ref %s)",
join_from, ref);
/* make sure any information from this node is discarded,
* it is invalid
*/
free_xml(cib_fragment);
FNRET(I_FAIL);
}
cl_log(LOG_DEBUG, "Welcoming node %s after ACK (ref %s)",
join_from, ref);
- // add them to our list of "active" nodes
+ /* add them to our list of "active" nodes
+ TODO: still used?
+ */
g_hash_table_insert(joined_nodes, strdup(join_from),strdup(join_from));
-
if(cib_fragment == NULL) {
cl_log(LOG_ERR,
"No status information was part of the"
" Welcome ACK from %s",
join_from);
FNRET(I_NULL);
}
-
- /* TODO: check the fragment is only for the status section
- = get_xml_attr(cib_fragment, NULL,
- XML_ATTR_FILTER_TYPE, TRUE); */
+
+ /* allow both node and status changes to be made */
+ msg_cib = find_xml_node(cib_fragment, XML_TAG_CIB);
+ set_xml_property_copy(msg_cib, XML_ATTR_FILTER_TYPE, "all");
+
+ tmp1 = get_object_root(XML_CIB_TAG_STATUS, msg_cib);
+ tmp2 = get_object_root(XML_CIB_TAG_NODES, msg_cib);
/* Make changes so that state=active for this node when the update
* is processed by A_CIB_INVOKE
*/
- tmp1 = find_xml_node(cib_fragment, XML_TAG_CIB);
- tmp1 = get_object_root(XML_CIB_TAG_STATUS, tmp1);
tmp1 = find_entity(tmp1, XML_CIB_TAG_STATE, join_from, FALSE);
-
set_xml_property_copy(tmp1, "state", "active");
+
+ /* make sure a node entry exists for the new node
+ *
+ * this will add anyone except the first ever node in the cluster
+ * since it will also be the DC which doesnt go through the
+ * join process (with itself). We can include a special case
+ * later if desired.
+ */
+ if(tmp2 == NULL) {
+ cl_log(LOG_ERR, "Couldnt find NODES sections in fragment");
+ } else {
+ tmp2 = create_xml_node(tmp2, XML_CIB_TAG_NODE);
+ set_xml_property_copy(tmp2, XML_ATTR_ID, join_from);
+ set_xml_property_copy(tmp2, "uname", join_from);
+ set_xml_property_copy(tmp2, XML_CIB_ATTR_NODETYPE, "node");
+ }
if(g_hash_table_size(joined_nodes)
== fsa_membership_copy->members_size) {
- // that was the last outstanding join ack)
cl_log(LOG_INFO,"That was the last outstanding join ack");
FNRET(I_SUCCESS);
+ /* The update isnt lost, the A_CIB_OP action is part of the
+ * matrix for S_INTEGRATION + I_SUCCESS.
+ */
+
} else {
cl_log(LOG_DEBUG,
"Still waiting on %d outstanding join acks",
size);
- //dont waste time by invoking the pe yet;
+ /* dont waste time by invoking the pe yet */
}
FNRET(I_CIB_OP);
}
void
ghash_send_welcome(gpointer key, gpointer value, gpointer user_data)
{
int *num_sent = (int*)user_data;
const char *node_uname = (const char*)key;
if(strcmp(fsa_our_uname, node_uname) == 0) {
// dont send one to ourselves
return;
}
+#if 0
if(send_request(NULL, NULL, CRM_OPERATION_WELCOME,
node_uname, CRM_SYSTEM_CRMD, NULL)) {
*num_sent++;
CRM_DEBUG("Sent welcome message to %s", node_uname);
} else {
cl_log(LOG_ERR, "Couldnt send welcome message to %s", node_uname);
-
}
+#else
+ /* Avoid ordered message delays caused when the CRMd proc
+ * isnt running yet, for now we just want the counter...
+ */
+ *num_sent++;
+#endif
}
void
ghash_count_vote(gpointer key, gpointer value, gpointer user_data)
{
struct election_data_s *election_data =
(struct election_data_s *)user_data;
oc_node_t *cur_node = (oc_node_t*)value;
const char *node_uname = (const char*)key;
if(election_data->winning_bornon > cur_node->node_born_on) {
election_data->winning_uname = node_uname;
election_data->winning_bornon = cur_node->node_born_on;
} else if(election_data->winning_bornon == cur_node->node_born_on
&& (election_data->winning_uname == NULL
|| strcmp(election_data->winning_uname, node_uname) > 0)) {
election_data->winning_uname = node_uname;
election_data->winning_bornon = cur_node->node_born_on;
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 5:59 PM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002424
Default Alt Text
(24 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment