root/daemons/controld/controld_corosync.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. crmd_cs_dispatch
  2. crmd_quorum_callback
  3. crmd_cs_destroy
  4. cpg_membership_callback
  5. crm_connect_corosync

   1 /*
   2  * Copyright 2004-2024 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <inttypes.h>               // PRIu32
  13 #include <stdio.h>                  // NULL
  14 #include <stdlib.h>                 // free(), etc.
  15 
  16 #include <sys/param.h>
  17 #include <sys/types.h>
  18 #include <sys/stat.h>
  19 
  20 #include <crm/crm.h>
  21 #include <crm/cluster/internal.h>
  22 #include <crm/common/xml.h>
  23 
  24 #include <pacemaker-controld.h>
  25 
  26 #if SUPPORT_COROSYNC
  27 
  28 extern void post_cache_update(int seq);
  29 
  30 /*       A_HA_CONNECT   */
  31 
  32 static void
  33 crmd_cs_dispatch(cpg_handle_t handle, const struct cpg_name *groupName,
     /* [previous][next][first][last][top][bottom][index][help] */
  34                  uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
  35 {
  36     const char *from = NULL;
  37     char *data = pcmk__cpg_message_data(handle, nodeid, pid, msg, &from);
  38     pcmk__node_status_t *peer = NULL;
  39     xmlNode *xml = NULL;
  40 
  41     if(data == NULL) {
  42         return;
  43     }
  44 
  45     xml = pcmk__xml_parse(data);
  46     if (xml == NULL) {
  47         crm_err("Could not parse message content: %.100s", data);
  48         free(data);
  49         return;
  50     }
  51 
  52     crm_xml_add(xml, PCMK__XA_SRC, from);
  53 
  54     peer = pcmk__get_node(0, from, NULL, pcmk__node_search_cluster_member);
  55     if (!pcmk_is_set(peer->processes, crm_proc_cpg)) {
  56         /* If we can still talk to our peer process on that node, then it must
  57          * be part of the corosync membership
  58          */
  59         crm_warn("Receiving messages from a node we think is dead: "
  60                  "%s[%" PRIu32 "]",
  61                  peer->name, peer->cluster_layer_id);
  62         crm_update_peer_proc(__func__, peer, crm_proc_cpg, PCMK_VALUE_ONLINE);
  63     }
  64 
  65     crmd_ha_msg_filter(xml);
  66     pcmk__xml_free(xml);
  67     free(data);
  68 }
  69 
  70 static gboolean
  71 crmd_quorum_callback(unsigned long long seq, gboolean quorate)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73     crm_update_quorum(quorate, FALSE);
  74     post_cache_update(seq);
  75     return TRUE;
  76 }
  77 
  78 static void
  79 crmd_cs_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81     if (!pcmk_is_set(controld_globals.fsa_input_register, R_HA_DISCONNECTED)) {
  82         crm_crit("Lost connection to cluster layer, shutting down");
  83         crmd_exit(CRM_EX_DISCONNECT);
  84     }
  85 }
  86 
  87 /*!
  88  * \brief Handle a Corosync notification of a CPG configuration change
  89  *
  90  * \param[in] handle               CPG connection
  91  * \param[in] cpg_name             CPG group name
  92  * \param[in] member_list          List of current CPG members
  93  * \param[in] member_list_entries  Number of entries in \p member_list
  94  * \param[in] left_list            List of CPG members that left
  95  * \param[in] left_list_entries    Number of entries in \p left_list
  96  * \param[in] joined_list          List of CPG members that joined
  97  * \param[in] joined_list_entries  Number of entries in \p joined_list
  98  */
  99 static void
 100 cpg_membership_callback(cpg_handle_t handle, const struct cpg_name *cpg_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 101                         const struct cpg_address *member_list,
 102                         size_t member_list_entries,
 103                         const struct cpg_address *left_list,
 104                         size_t left_list_entries,
 105                         const struct cpg_address *joined_list,
 106                         size_t joined_list_entries)
 107 {
 108     /* When nodes leave CPG, the DC clears their transient node attributes.
 109      *
 110      * However if there is no DC, or the DC is among the nodes that left, each
 111      * remaining node needs to do the clearing, to ensure it gets done.
 112      * Otherwise, the attributes would persist when the nodes rejoin, which
 113      * could have serious consequences for unfencing, agents that use attributes
 114      * for internal logic, etc.
 115      *
 116      * Here, we set a global boolean if the DC is among the nodes that left, for
 117      * use by the peer callback.
 118      */
 119     if (controld_globals.dc_name != NULL) {
 120         pcmk__node_status_t *peer = NULL;
 121 
 122         peer = pcmk__search_node_caches(0, controld_globals.dc_name,
 123                                         pcmk__node_search_cluster_member);
 124         if (peer != NULL) {
 125             for (int i = 0; i < left_list_entries; ++i) {
 126                 if (left_list[i].nodeid == peer->cluster_layer_id) {
 127                     controld_set_global_flags(controld_dc_left);
 128                     break;
 129                 }
 130             }
 131         }
 132     }
 133 
 134     // Process the change normally, which will call the peer callback as needed
 135     pcmk__cpg_confchg_cb(handle, cpg_name, member_list, member_list_entries,
 136                          left_list, left_list_entries,
 137                          joined_list, joined_list_entries);
 138 
 139     controld_clear_global_flags(controld_dc_left);
 140 }
 141 
 142 extern gboolean crm_connect_corosync(pcmk_cluster_t *cluster);
 143 
 144 gboolean
 145 crm_connect_corosync(pcmk_cluster_t *cluster)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147     if (pcmk_get_cluster_layer() == pcmk_cluster_layer_corosync) {
 148         pcmk__cluster_set_status_callback(&peer_update_callback);
 149 
 150         pcmk_cluster_set_destroy_fn(cluster, crmd_cs_destroy);
 151         pcmk_cpg_set_deliver_fn(cluster, crmd_cs_dispatch);
 152         pcmk_cpg_set_confchg_fn(cluster, cpg_membership_callback);
 153 
 154         if (pcmk_cluster_connect(cluster) == pcmk_rc_ok) {
 155             pcmk__corosync_quorum_connect(crmd_quorum_callback,
 156                                           crmd_cs_destroy);
 157             return TRUE;
 158         }
 159     }
 160     return FALSE;
 161 }
 162 
 163 #endif

/* [previous][next][first][last][top][bottom][index][help] */