summaryrefslogtreecommitdiffstats
path: root/daemons/controld/controld_utils.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:53:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:53:20 +0000
commite5a812082ae033afb1eed82c0f2df3d0f6bdc93f (patch)
treea6716c9275b4b413f6c9194798b34b91affb3cc7 /daemons/controld/controld_utils.c
parentInitial commit. (diff)
downloadpacemaker-e5a812082ae033afb1eed82c0f2df3d0f6bdc93f.tar.xz
pacemaker-e5a812082ae033afb1eed82c0f2df3d0f6bdc93f.zip
Adding upstream version 2.1.6.upstream/2.1.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'daemons/controld/controld_utils.c')
-rw-r--r--daemons/controld/controld_utils.c837
1 files changed, 837 insertions, 0 deletions
diff --git a/daemons/controld/controld_utils.c b/daemons/controld/controld_utils.c
new file mode 100644
index 0000000..4ce09d9
--- /dev/null
+++ b/daemons/controld/controld_utils.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright 2004-2023 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <stdlib.h>
+#include <stdint.h> // uint64_t
+
+#include <crm/crm.h>
+#include <crm/cib.h>
+#include <crm/msg_xml.h>
+#include <crm/common/xml.h>
+
+#include <pacemaker-controld.h>
+
+const char *
+fsa_input2string(enum crmd_fsa_input input)
+{
+ const char *inputAsText = NULL;
+
+ switch (input) {
+ case I_NULL:
+ inputAsText = "I_NULL";
+ break;
+ case I_CIB_OP:
+ inputAsText = "I_CIB_OP (unused)";
+ break;
+ case I_CIB_UPDATE:
+ inputAsText = "I_CIB_UPDATE";
+ break;
+ case I_DC_TIMEOUT:
+ inputAsText = "I_DC_TIMEOUT";
+ break;
+ case I_ELECTION:
+ inputAsText = "I_ELECTION";
+ break;
+ case I_PE_CALC:
+ inputAsText = "I_PE_CALC";
+ break;
+ case I_RELEASE_DC:
+ inputAsText = "I_RELEASE_DC";
+ break;
+ case I_ELECTION_DC:
+ inputAsText = "I_ELECTION_DC";
+ break;
+ case I_ERROR:
+ inputAsText = "I_ERROR";
+ break;
+ case I_FAIL:
+ inputAsText = "I_FAIL";
+ break;
+ case I_INTEGRATED:
+ inputAsText = "I_INTEGRATED";
+ break;
+ case I_FINALIZED:
+ inputAsText = "I_FINALIZED";
+ break;
+ case I_NODE_JOIN:
+ inputAsText = "I_NODE_JOIN";
+ break;
+ case I_JOIN_OFFER:
+ inputAsText = "I_JOIN_OFFER";
+ break;
+ case I_JOIN_REQUEST:
+ inputAsText = "I_JOIN_REQUEST";
+ break;
+ case I_JOIN_RESULT:
+ inputAsText = "I_JOIN_RESULT";
+ break;
+ case I_NOT_DC:
+ inputAsText = "I_NOT_DC";
+ break;
+ case I_RECOVERED:
+ inputAsText = "I_RECOVERED";
+ break;
+ case I_RELEASE_FAIL:
+ inputAsText = "I_RELEASE_FAIL";
+ break;
+ case I_RELEASE_SUCCESS:
+ inputAsText = "I_RELEASE_SUCCESS";
+ break;
+ case I_RESTART:
+ inputAsText = "I_RESTART";
+ break;
+ case I_PE_SUCCESS:
+ inputAsText = "I_PE_SUCCESS";
+ break;
+ case I_ROUTER:
+ inputAsText = "I_ROUTER";
+ break;
+ case I_SHUTDOWN:
+ inputAsText = "I_SHUTDOWN";
+ break;
+ case I_STARTUP:
+ inputAsText = "I_STARTUP";
+ break;
+ case I_TE_SUCCESS:
+ inputAsText = "I_TE_SUCCESS";
+ break;
+ case I_STOP:
+ inputAsText = "I_STOP";
+ break;
+ case I_DC_HEARTBEAT:
+ inputAsText = "I_DC_HEARTBEAT";
+ break;
+ case I_WAIT_FOR_EVENT:
+ inputAsText = "I_WAIT_FOR_EVENT";
+ break;
+ case I_LRM_EVENT:
+ inputAsText = "I_LRM_EVENT";
+ break;
+ case I_PENDING:
+ inputAsText = "I_PENDING";
+ break;
+ case I_HALT:
+ inputAsText = "I_HALT";
+ break;
+ case I_TERMINATE:
+ inputAsText = "I_TERMINATE";
+ break;
+ case I_ILLEGAL:
+ inputAsText = "I_ILLEGAL";
+ break;
+ }
+
+ if (inputAsText == NULL) {
+ crm_err("Input %d is unknown", input);
+ inputAsText = "<UNKNOWN_INPUT>";
+ }
+
+ return inputAsText;
+}
+
+const char *
+fsa_state2string(enum crmd_fsa_state state)
+{
+ const char *stateAsText = NULL;
+
+ switch (state) {
+ case S_IDLE:
+ stateAsText = "S_IDLE";
+ break;
+ case S_ELECTION:
+ stateAsText = "S_ELECTION";
+ break;
+ case S_INTEGRATION:
+ stateAsText = "S_INTEGRATION";
+ break;
+ case S_FINALIZE_JOIN:
+ stateAsText = "S_FINALIZE_JOIN";
+ break;
+ case S_NOT_DC:
+ stateAsText = "S_NOT_DC";
+ break;
+ case S_POLICY_ENGINE:
+ stateAsText = "S_POLICY_ENGINE";
+ break;
+ case S_RECOVERY:
+ stateAsText = "S_RECOVERY";
+ break;
+ case S_RELEASE_DC:
+ stateAsText = "S_RELEASE_DC";
+ break;
+ case S_PENDING:
+ stateAsText = "S_PENDING";
+ break;
+ case S_STOPPING:
+ stateAsText = "S_STOPPING";
+ break;
+ case S_TERMINATE:
+ stateAsText = "S_TERMINATE";
+ break;
+ case S_TRANSITION_ENGINE:
+ stateAsText = "S_TRANSITION_ENGINE";
+ break;
+ case S_STARTING:
+ stateAsText = "S_STARTING";
+ break;
+ case S_HALT:
+ stateAsText = "S_HALT";
+ break;
+ case S_ILLEGAL:
+ stateAsText = "S_ILLEGAL";
+ break;
+ }
+
+ if (stateAsText == NULL) {
+ crm_err("State %d is unknown", state);
+ stateAsText = "<UNKNOWN_STATE>";
+ }
+
+ return stateAsText;
+}
+
+const char *
+fsa_cause2string(enum crmd_fsa_cause cause)
+{
+ const char *causeAsText = NULL;
+
+ switch (cause) {
+ case C_UNKNOWN:
+ causeAsText = "C_UNKNOWN";
+ break;
+ case C_STARTUP:
+ causeAsText = "C_STARTUP";
+ break;
+ case C_IPC_MESSAGE:
+ causeAsText = "C_IPC_MESSAGE";
+ break;
+ case C_HA_MESSAGE:
+ causeAsText = "C_HA_MESSAGE";
+ break;
+ case C_TIMER_POPPED:
+ causeAsText = "C_TIMER_POPPED";
+ break;
+ case C_SHUTDOWN:
+ causeAsText = "C_SHUTDOWN";
+ break;
+ case C_LRM_OP_CALLBACK:
+ causeAsText = "C_LRM_OP_CALLBACK";
+ break;
+ case C_CRMD_STATUS_CALLBACK:
+ causeAsText = "C_CRMD_STATUS_CALLBACK";
+ break;
+ case C_FSA_INTERNAL:
+ causeAsText = "C_FSA_INTERNAL";
+ break;
+ }
+
+ if (causeAsText == NULL) {
+ crm_err("Cause %d is unknown", cause);
+ causeAsText = "<UNKNOWN_CAUSE>";
+ }
+
+ return causeAsText;
+}
+
+const char *
+fsa_action2string(long long action)
+{
+ const char *actionAsText = NULL;
+
+ switch (action) {
+
+ case A_NOTHING:
+ actionAsText = "A_NOTHING";
+ break;
+ case A_ELECTION_START:
+ actionAsText = "A_ELECTION_START";
+ break;
+ case A_DC_JOIN_FINAL:
+ actionAsText = "A_DC_JOIN_FINAL";
+ break;
+ case A_READCONFIG:
+ actionAsText = "A_READCONFIG";
+ break;
+ case O_RELEASE:
+ actionAsText = "O_RELEASE";
+ break;
+ case A_STARTUP:
+ actionAsText = "A_STARTUP";
+ break;
+ case A_STARTED:
+ actionAsText = "A_STARTED";
+ break;
+ case A_HA_CONNECT:
+ actionAsText = "A_HA_CONNECT";
+ break;
+ case A_HA_DISCONNECT:
+ actionAsText = "A_HA_DISCONNECT";
+ break;
+ case A_LRM_CONNECT:
+ actionAsText = "A_LRM_CONNECT";
+ break;
+ case A_LRM_EVENT:
+ actionAsText = "A_LRM_EVENT";
+ break;
+ case A_LRM_INVOKE:
+ actionAsText = "A_LRM_INVOKE";
+ break;
+ case A_LRM_DISCONNECT:
+ actionAsText = "A_LRM_DISCONNECT";
+ break;
+ case O_LRM_RECONNECT:
+ actionAsText = "O_LRM_RECONNECT";
+ break;
+ case A_CL_JOIN_QUERY:
+ actionAsText = "A_CL_JOIN_QUERY";
+ break;
+ case A_DC_TIMER_STOP:
+ actionAsText = "A_DC_TIMER_STOP";
+ break;
+ case A_DC_TIMER_START:
+ actionAsText = "A_DC_TIMER_START";
+ break;
+ case A_INTEGRATE_TIMER_START:
+ actionAsText = "A_INTEGRATE_TIMER_START";
+ break;
+ case A_INTEGRATE_TIMER_STOP:
+ actionAsText = "A_INTEGRATE_TIMER_STOP";
+ break;
+ case A_FINALIZE_TIMER_START:
+ actionAsText = "A_FINALIZE_TIMER_START";
+ break;
+ case A_FINALIZE_TIMER_STOP:
+ actionAsText = "A_FINALIZE_TIMER_STOP";
+ break;
+ case A_ELECTION_COUNT:
+ actionAsText = "A_ELECTION_COUNT";
+ break;
+ case A_ELECTION_VOTE:
+ actionAsText = "A_ELECTION_VOTE";
+ break;
+ case A_ELECTION_CHECK:
+ actionAsText = "A_ELECTION_CHECK";
+ break;
+ case A_CL_JOIN_ANNOUNCE:
+ actionAsText = "A_CL_JOIN_ANNOUNCE";
+ break;
+ case A_CL_JOIN_REQUEST:
+ actionAsText = "A_CL_JOIN_REQUEST";
+ break;
+ case A_CL_JOIN_RESULT:
+ actionAsText = "A_CL_JOIN_RESULT";
+ break;
+ case A_DC_JOIN_OFFER_ALL:
+ actionAsText = "A_DC_JOIN_OFFER_ALL";
+ break;
+ case A_DC_JOIN_OFFER_ONE:
+ actionAsText = "A_DC_JOIN_OFFER_ONE";
+ break;
+ case A_DC_JOIN_PROCESS_REQ:
+ actionAsText = "A_DC_JOIN_PROCESS_REQ";
+ break;
+ case A_DC_JOIN_PROCESS_ACK:
+ actionAsText = "A_DC_JOIN_PROCESS_ACK";
+ break;
+ case A_DC_JOIN_FINALIZE:
+ actionAsText = "A_DC_JOIN_FINALIZE";
+ break;
+ case A_MSG_PROCESS:
+ actionAsText = "A_MSG_PROCESS";
+ break;
+ case A_MSG_ROUTE:
+ actionAsText = "A_MSG_ROUTE";
+ break;
+ case A_RECOVER:
+ actionAsText = "A_RECOVER";
+ break;
+ case A_DC_RELEASE:
+ actionAsText = "A_DC_RELEASE";
+ break;
+ case A_DC_RELEASED:
+ actionAsText = "A_DC_RELEASED";
+ break;
+ case A_DC_TAKEOVER:
+ actionAsText = "A_DC_TAKEOVER";
+ break;
+ case A_SHUTDOWN:
+ actionAsText = "A_SHUTDOWN";
+ break;
+ case A_SHUTDOWN_REQ:
+ actionAsText = "A_SHUTDOWN_REQ";
+ break;
+ case A_STOP:
+ actionAsText = "A_STOP ";
+ break;
+ case A_EXIT_0:
+ actionAsText = "A_EXIT_0";
+ break;
+ case A_EXIT_1:
+ actionAsText = "A_EXIT_1";
+ break;
+ case O_CIB_RESTART:
+ actionAsText = "O_CIB_RESTART";
+ break;
+ case A_CIB_START:
+ actionAsText = "A_CIB_START";
+ break;
+ case A_CIB_STOP:
+ actionAsText = "A_CIB_STOP";
+ break;
+ case A_TE_INVOKE:
+ actionAsText = "A_TE_INVOKE";
+ break;
+ case O_TE_RESTART:
+ actionAsText = "O_TE_RESTART";
+ break;
+ case A_TE_START:
+ actionAsText = "A_TE_START";
+ break;
+ case A_TE_STOP:
+ actionAsText = "A_TE_STOP";
+ break;
+ case A_TE_HALT:
+ actionAsText = "A_TE_HALT";
+ break;
+ case A_TE_CANCEL:
+ actionAsText = "A_TE_CANCEL";
+ break;
+ case A_PE_INVOKE:
+ actionAsText = "A_PE_INVOKE";
+ break;
+ case O_PE_RESTART:
+ actionAsText = "O_PE_RESTART";
+ break;
+ case A_PE_START:
+ actionAsText = "A_PE_START";
+ break;
+ case A_PE_STOP:
+ actionAsText = "A_PE_STOP";
+ break;
+ case A_NODE_BLOCK:
+ actionAsText = "A_NODE_BLOCK";
+ break;
+ case A_UPDATE_NODESTATUS:
+ actionAsText = "A_UPDATE_NODESTATUS";
+ break;
+ case A_LOG:
+ actionAsText = "A_LOG ";
+ break;
+ case A_ERROR:
+ actionAsText = "A_ERROR ";
+ break;
+ case A_WARN:
+ actionAsText = "A_WARN ";
+ break;
+ /* Composite actions */
+ case A_DC_TIMER_START | A_CL_JOIN_QUERY:
+ actionAsText = "A_DC_TIMER_START|A_CL_JOIN_QUERY";
+ break;
+ }
+
+ if (actionAsText == NULL) {
+ crm_err("Action %.16llx is unknown", action);
+ actionAsText = "<UNKNOWN_ACTION>";
+ }
+
+ return actionAsText;
+}
+
+void
+fsa_dump_inputs(int log_level, const char *text, long long input_register)
+{
+ if (input_register == A_NOTHING) {
+ return;
+ }
+ if (text == NULL) {
+ text = "Input register contents:";
+ }
+
+ if (pcmk_is_set(input_register, R_THE_DC)) {
+ crm_trace("%s %.16llx (R_THE_DC)", text, R_THE_DC);
+ }
+ if (pcmk_is_set(input_register, R_STARTING)) {
+ crm_trace("%s %.16llx (R_STARTING)", text, R_STARTING);
+ }
+ if (pcmk_is_set(input_register, R_SHUTDOWN)) {
+ crm_trace("%s %.16llx (R_SHUTDOWN)", text, R_SHUTDOWN);
+ }
+ if (pcmk_is_set(input_register, R_STAYDOWN)) {
+ crm_trace("%s %.16llx (R_STAYDOWN)", text, R_STAYDOWN);
+ }
+ if (pcmk_is_set(input_register, R_JOIN_OK)) {
+ crm_trace("%s %.16llx (R_JOIN_OK)", text, R_JOIN_OK);
+ }
+ if (pcmk_is_set(input_register, R_READ_CONFIG)) {
+ crm_trace("%s %.16llx (R_READ_CONFIG)", text, R_READ_CONFIG);
+ }
+ if (pcmk_is_set(input_register, R_INVOKE_PE)) {
+ crm_trace("%s %.16llx (R_INVOKE_PE)", text, R_INVOKE_PE);
+ }
+ if (pcmk_is_set(input_register, R_CIB_CONNECTED)) {
+ crm_trace("%s %.16llx (R_CIB_CONNECTED)", text, R_CIB_CONNECTED);
+ }
+ if (pcmk_is_set(input_register, R_PE_CONNECTED)) {
+ crm_trace("%s %.16llx (R_PE_CONNECTED)", text, R_PE_CONNECTED);
+ }
+ if (pcmk_is_set(input_register, R_TE_CONNECTED)) {
+ crm_trace("%s %.16llx (R_TE_CONNECTED)", text, R_TE_CONNECTED);
+ }
+ if (pcmk_is_set(input_register, R_LRM_CONNECTED)) {
+ crm_trace("%s %.16llx (R_LRM_CONNECTED)", text, R_LRM_CONNECTED);
+ }
+ if (pcmk_is_set(input_register, R_CIB_REQUIRED)) {
+ crm_trace("%s %.16llx (R_CIB_REQUIRED)", text, R_CIB_REQUIRED);
+ }
+ if (pcmk_is_set(input_register, R_PE_REQUIRED)) {
+ crm_trace("%s %.16llx (R_PE_REQUIRED)", text, R_PE_REQUIRED);
+ }
+ if (pcmk_is_set(input_register, R_TE_REQUIRED)) {
+ crm_trace("%s %.16llx (R_TE_REQUIRED)", text, R_TE_REQUIRED);
+ }
+ if (pcmk_is_set(input_register, R_REQ_PEND)) {
+ crm_trace("%s %.16llx (R_REQ_PEND)", text, R_REQ_PEND);
+ }
+ if (pcmk_is_set(input_register, R_PE_PEND)) {
+ crm_trace("%s %.16llx (R_PE_PEND)", text, R_PE_PEND);
+ }
+ if (pcmk_is_set(input_register, R_TE_PEND)) {
+ crm_trace("%s %.16llx (R_TE_PEND)", text, R_TE_PEND);
+ }
+ if (pcmk_is_set(input_register, R_RESP_PEND)) {
+ crm_trace("%s %.16llx (R_RESP_PEND)", text, R_RESP_PEND);
+ }
+ if (pcmk_is_set(input_register, R_CIB_DONE)) {
+ crm_trace("%s %.16llx (R_CIB_DONE)", text, R_CIB_DONE);
+ }
+ if (pcmk_is_set(input_register, R_HAVE_CIB)) {
+ crm_trace("%s %.16llx (R_HAVE_CIB)", text, R_HAVE_CIB);
+ }
+ if (pcmk_is_set(input_register, R_MEMBERSHIP)) {
+ crm_trace("%s %.16llx (R_MEMBERSHIP)", text, R_MEMBERSHIP);
+ }
+ if (pcmk_is_set(input_register, R_PEER_DATA)) {
+ crm_trace("%s %.16llx (R_PEER_DATA)", text, R_PEER_DATA);
+ }
+ if (pcmk_is_set(input_register, R_IN_RECOVERY)) {
+ crm_trace("%s %.16llx (R_IN_RECOVERY)", text, R_IN_RECOVERY);
+ }
+}
+
+void
+fsa_dump_actions(uint64_t action, const char *text)
+{
+ if (pcmk_is_set(action, A_READCONFIG)) {
+ crm_trace("Action %.16llx (A_READCONFIG) %s", A_READCONFIG, text);
+ }
+ if (pcmk_is_set(action, A_STARTUP)) {
+ crm_trace("Action %.16llx (A_STARTUP) %s", A_STARTUP, text);
+ }
+ if (pcmk_is_set(action, A_STARTED)) {
+ crm_trace("Action %.16llx (A_STARTED) %s", A_STARTED, text);
+ }
+ if (pcmk_is_set(action, A_HA_CONNECT)) {
+ crm_trace("Action %.16llx (A_CONNECT) %s", A_HA_CONNECT, text);
+ }
+ if (pcmk_is_set(action, A_HA_DISCONNECT)) {
+ crm_trace("Action %.16llx (A_DISCONNECT) %s", A_HA_DISCONNECT, text);
+ }
+ if (pcmk_is_set(action, A_LRM_CONNECT)) {
+ crm_trace("Action %.16llx (A_LRM_CONNECT) %s", A_LRM_CONNECT, text);
+ }
+ if (pcmk_is_set(action, A_LRM_EVENT)) {
+ crm_trace("Action %.16llx (A_LRM_EVENT) %s", A_LRM_EVENT, text);
+ }
+ if (pcmk_is_set(action, A_LRM_INVOKE)) {
+ crm_trace("Action %.16llx (A_LRM_INVOKE) %s", A_LRM_INVOKE, text);
+ }
+ if (pcmk_is_set(action, A_LRM_DISCONNECT)) {
+ crm_trace("Action %.16llx (A_LRM_DISCONNECT) %s", A_LRM_DISCONNECT, text);
+ }
+ if (pcmk_is_set(action, A_DC_TIMER_STOP)) {
+ crm_trace("Action %.16llx (A_DC_TIMER_STOP) %s", A_DC_TIMER_STOP, text);
+ }
+ if (pcmk_is_set(action, A_DC_TIMER_START)) {
+ crm_trace("Action %.16llx (A_DC_TIMER_START) %s", A_DC_TIMER_START, text);
+ }
+ if (pcmk_is_set(action, A_INTEGRATE_TIMER_START)) {
+ crm_trace("Action %.16llx (A_INTEGRATE_TIMER_START) %s", A_INTEGRATE_TIMER_START, text);
+ }
+ if (pcmk_is_set(action, A_INTEGRATE_TIMER_STOP)) {
+ crm_trace("Action %.16llx (A_INTEGRATE_TIMER_STOP) %s", A_INTEGRATE_TIMER_STOP, text);
+ }
+ if (pcmk_is_set(action, A_FINALIZE_TIMER_START)) {
+ crm_trace("Action %.16llx (A_FINALIZE_TIMER_START) %s", A_FINALIZE_TIMER_START, text);
+ }
+ if (pcmk_is_set(action, A_FINALIZE_TIMER_STOP)) {
+ crm_trace("Action %.16llx (A_FINALIZE_TIMER_STOP) %s", A_FINALIZE_TIMER_STOP, text);
+ }
+ if (pcmk_is_set(action, A_ELECTION_COUNT)) {
+ crm_trace("Action %.16llx (A_ELECTION_COUNT) %s", A_ELECTION_COUNT, text);
+ }
+ if (pcmk_is_set(action, A_ELECTION_VOTE)) {
+ crm_trace("Action %.16llx (A_ELECTION_VOTE) %s", A_ELECTION_VOTE, text);
+ }
+ if (pcmk_is_set(action, A_ELECTION_CHECK)) {
+ crm_trace("Action %.16llx (A_ELECTION_CHECK) %s", A_ELECTION_CHECK, text);
+ }
+ if (pcmk_is_set(action, A_CL_JOIN_ANNOUNCE)) {
+ crm_trace("Action %.16llx (A_CL_JOIN_ANNOUNCE) %s", A_CL_JOIN_ANNOUNCE, text);
+ }
+ if (pcmk_is_set(action, A_CL_JOIN_REQUEST)) {
+ crm_trace("Action %.16llx (A_CL_JOIN_REQUEST) %s", A_CL_JOIN_REQUEST, text);
+ }
+ if (pcmk_is_set(action, A_CL_JOIN_RESULT)) {
+ crm_trace("Action %.16llx (A_CL_JOIN_RESULT) %s", A_CL_JOIN_RESULT, text);
+ }
+ if (pcmk_is_set(action, A_DC_JOIN_OFFER_ALL)) {
+ crm_trace("Action %.16llx (A_DC_JOIN_OFFER_ALL) %s", A_DC_JOIN_OFFER_ALL, text);
+ }
+ if (pcmk_is_set(action, A_DC_JOIN_OFFER_ONE)) {
+ crm_trace("Action %.16llx (A_DC_JOIN_OFFER_ONE) %s", A_DC_JOIN_OFFER_ONE, text);
+ }
+ if (pcmk_is_set(action, A_DC_JOIN_PROCESS_REQ)) {
+ crm_trace("Action %.16llx (A_DC_JOIN_PROCESS_REQ) %s", A_DC_JOIN_PROCESS_REQ, text);
+ }
+ if (pcmk_is_set(action, A_DC_JOIN_PROCESS_ACK)) {
+ crm_trace("Action %.16llx (A_DC_JOIN_PROCESS_ACK) %s", A_DC_JOIN_PROCESS_ACK, text);
+ }
+ if (pcmk_is_set(action, A_DC_JOIN_FINALIZE)) {
+ crm_trace("Action %.16llx (A_DC_JOIN_FINALIZE) %s", A_DC_JOIN_FINALIZE, text);
+ }
+ if (pcmk_is_set(action, A_MSG_PROCESS)) {
+ crm_trace("Action %.16llx (A_MSG_PROCESS) %s", A_MSG_PROCESS, text);
+ }
+ if (pcmk_is_set(action, A_MSG_ROUTE)) {
+ crm_trace("Action %.16llx (A_MSG_ROUTE) %s", A_MSG_ROUTE, text);
+ }
+ if (pcmk_is_set(action, A_RECOVER)) {
+ crm_trace("Action %.16llx (A_RECOVER) %s", A_RECOVER, text);
+ }
+ if (pcmk_is_set(action, A_DC_RELEASE)) {
+ crm_trace("Action %.16llx (A_DC_RELEASE) %s", A_DC_RELEASE, text);
+ }
+ if (pcmk_is_set(action, A_DC_RELEASED)) {
+ crm_trace("Action %.16llx (A_DC_RELEASED) %s", A_DC_RELEASED, text);
+ }
+ if (pcmk_is_set(action, A_DC_TAKEOVER)) {
+ crm_trace("Action %.16llx (A_DC_TAKEOVER) %s", A_DC_TAKEOVER, text);
+ }
+ if (pcmk_is_set(action, A_SHUTDOWN)) {
+ crm_trace("Action %.16llx (A_SHUTDOWN) %s", A_SHUTDOWN, text);
+ }
+ if (pcmk_is_set(action, A_SHUTDOWN_REQ)) {
+ crm_trace("Action %.16llx (A_SHUTDOWN_REQ) %s", A_SHUTDOWN_REQ, text);
+ }
+ if (pcmk_is_set(action, A_STOP)) {
+ crm_trace("Action %.16llx (A_STOP ) %s", A_STOP, text);
+ }
+ if (pcmk_is_set(action, A_EXIT_0)) {
+ crm_trace("Action %.16llx (A_EXIT_0) %s", A_EXIT_0, text);
+ }
+ if (pcmk_is_set(action, A_EXIT_1)) {
+ crm_trace("Action %.16llx (A_EXIT_1) %s", A_EXIT_1, text);
+ }
+ if (pcmk_is_set(action, A_CIB_START)) {
+ crm_trace("Action %.16llx (A_CIB_START) %s", A_CIB_START, text);
+ }
+ if (pcmk_is_set(action, A_CIB_STOP)) {
+ crm_trace("Action %.16llx (A_CIB_STOP) %s", A_CIB_STOP, text);
+ }
+ if (pcmk_is_set(action, A_TE_INVOKE)) {
+ crm_trace("Action %.16llx (A_TE_INVOKE) %s", A_TE_INVOKE, text);
+ }
+ if (pcmk_is_set(action, A_TE_START)) {
+ crm_trace("Action %.16llx (A_TE_START) %s", A_TE_START, text);
+ }
+ if (pcmk_is_set(action, A_TE_STOP)) {
+ crm_trace("Action %.16llx (A_TE_STOP) %s", A_TE_STOP, text);
+ }
+ if (pcmk_is_set(action, A_TE_CANCEL)) {
+ crm_trace("Action %.16llx (A_TE_CANCEL) %s", A_TE_CANCEL, text);
+ }
+ if (pcmk_is_set(action, A_PE_INVOKE)) {
+ crm_trace("Action %.16llx (A_PE_INVOKE) %s", A_PE_INVOKE, text);
+ }
+ if (pcmk_is_set(action, A_PE_START)) {
+ crm_trace("Action %.16llx (A_PE_START) %s", A_PE_START, text);
+ }
+ if (pcmk_is_set(action, A_PE_STOP)) {
+ crm_trace("Action %.16llx (A_PE_STOP) %s", A_PE_STOP, text);
+ }
+ if (pcmk_is_set(action, A_NODE_BLOCK)) {
+ crm_trace("Action %.16llx (A_NODE_BLOCK) %s", A_NODE_BLOCK, text);
+ }
+ if (pcmk_is_set(action, A_UPDATE_NODESTATUS)) {
+ crm_trace("Action %.16llx (A_UPDATE_NODESTATUS) %s", A_UPDATE_NODESTATUS, text);
+ }
+ if (pcmk_is_set(action, A_LOG)) {
+ crm_trace("Action %.16llx (A_LOG ) %s", A_LOG, text);
+ }
+ if (pcmk_is_set(action, A_ERROR)) {
+ crm_trace("Action %.16llx (A_ERROR ) %s", A_ERROR, text);
+ }
+ if (pcmk_is_set(action, A_WARN)) {
+ crm_trace("Action %.16llx (A_WARN ) %s", A_WARN, text);
+ }
+}
+
+gboolean
+update_dc(xmlNode * msg)
+{
+ char *last_dc = controld_globals.dc_name;
+ const char *dc_version = NULL;
+ const char *welcome_from = NULL;
+
+ if (msg != NULL) {
+ gboolean invalid = FALSE;
+
+ dc_version = crm_element_value(msg, F_CRM_VERSION);
+ welcome_from = crm_element_value(msg, F_CRM_HOST_FROM);
+
+ CRM_CHECK(dc_version != NULL, return FALSE);
+ CRM_CHECK(welcome_from != NULL, return FALSE);
+
+ if (AM_I_DC
+ && !pcmk__str_eq(welcome_from, controld_globals.our_nodename,
+ pcmk__str_casei)) {
+ invalid = TRUE;
+
+ } else if ((controld_globals.dc_name != NULL)
+ && !pcmk__str_eq(welcome_from, controld_globals.dc_name,
+ pcmk__str_casei)) {
+ invalid = TRUE;
+ }
+
+ if (invalid) {
+ if (AM_I_DC) {
+ crm_err("Not updating DC to %s (%s): we are also a DC",
+ welcome_from, dc_version);
+ } else {
+ crm_warn("New DC %s is not %s",
+ welcome_from, controld_globals.dc_name);
+ }
+
+ controld_set_fsa_action_flags(A_CL_JOIN_QUERY | A_DC_TIMER_START);
+ controld_trigger_fsa();
+ return FALSE;
+ }
+ }
+
+ controld_globals.dc_name = NULL; // freed as last_dc
+ pcmk__str_update(&(controld_globals.dc_name), welcome_from);
+ pcmk__str_update(&(controld_globals.dc_version), dc_version);
+
+ if (pcmk__str_eq(controld_globals.dc_name, last_dc, pcmk__str_casei)) {
+ /* do nothing */
+
+ } else if (controld_globals.dc_name != NULL) {
+ crm_node_t *dc_node = crm_get_peer(0, controld_globals.dc_name);
+
+ crm_info("Set DC to %s (%s)",
+ controld_globals.dc_name,
+ pcmk__s(controld_globals.dc_version, "unknown version"));
+ pcmk__update_peer_expected(__func__, dc_node, CRMD_JOINSTATE_MEMBER);
+
+ } else if (last_dc != NULL) {
+ crm_info("Unset DC (was %s)", last_dc);
+ }
+
+ free(last_dc);
+ return TRUE;
+}
+
+void crmd_peer_down(crm_node_t *peer, bool full)
+{
+ if(full && peer->state == NULL) {
+ pcmk__update_peer_state(__func__, peer, CRM_NODE_LOST, 0);
+ crm_update_peer_proc(__func__, peer, crm_proc_none, NULL);
+ }
+ crm_update_peer_join(__func__, peer, crm_join_none);
+ pcmk__update_peer_expected(__func__, peer, CRMD_JOINSTATE_DOWN);
+}
+
+/*!
+ * \internal
+ * \brief Check feature set compatibility of DC and joining node
+ *
+ * Return true if a joining node's CRM feature set is compatible with the
+ * current DC's. The feature sets are compatible if they have the same major
+ * version number, and the DC's minor version number is the same or older than
+ * the joining node's. The minor-minor version is intended solely to allow
+ * resource agents to detect feature support, and so is ignored.
+ *
+ * \param[in] dc_version DC's feature set
+ * \param[in] join_version Joining node's version
+ */
+bool
+feature_set_compatible(const char *dc_version, const char *join_version)
+{
+ char *dc_minor = NULL;
+ char *join_minor = NULL;
+ long dc_v = 0;
+ long join_v = 0;
+
+ // Get DC's major version
+ errno = 0;
+ dc_v = strtol(dc_version, &dc_minor, 10);
+ if (errno) {
+ return FALSE;
+ }
+
+ // Get joining node's major version
+ errno = 0;
+ join_v = strtol(join_version, &join_minor, 10);
+ if (errno) {
+ return FALSE;
+ }
+
+ // Major version component must be identical
+ if (dc_v != join_v) {
+ return FALSE;
+ }
+
+ // Get DC's minor version
+ if (*dc_minor == '.') {
+ ++dc_minor;
+ }
+ errno = 0;
+ dc_v = strtol(dc_minor, NULL, 10);
+ if (errno) {
+ return FALSE;
+ }
+
+ // Get joining node's minor version
+ if (*join_minor == '.') {
+ ++join_minor;
+ }
+ errno = 0;
+ join_v = strtol(join_minor, NULL, 10);
+ if (errno) {
+ return FALSE;
+ }
+
+ // DC's minor version must be the same or older
+ return dc_v <= join_v;
+}
+
+const char *
+get_node_id(xmlNode *lrm_rsc_op)
+{
+ xmlNode *node = lrm_rsc_op;
+
+ while (node != NULL && !pcmk__str_eq(XML_CIB_TAG_STATE, TYPE(node), pcmk__str_casei)) {
+ node = node->parent;
+ }
+
+ CRM_CHECK(node != NULL, return NULL);
+ return ID(node);
+}