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-2022 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 <sys/param.h>
  13 #include <sys/types.h>
  14 #include <sys/stat.h>
  15 
  16 #include <crm/crm.h>
  17 #include <crm/cluster/internal.h>
  18 #include <crm/common/xml.h>
  19 
  20 #include <pacemaker-controld.h>
  21 
  22 #if SUPPORT_COROSYNC
  23 
  24 extern void post_cache_update(int seq);
  25 
  26 /*       A_HA_CONNECT   */
  27 
  28 static void
  29 crmd_cs_dispatch(cpg_handle_t handle, const struct cpg_name *groupName,
     /* [previous][next][first][last][top][bottom][index][help] */
  30                  uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
  31 {
  32     uint32_t kind = 0;
  33     const char *from = NULL;
  34     char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
  35 
  36     if(data == NULL) {
  37         return;
  38     }
  39     if (kind == crm_class_cluster) {
  40         crm_node_t *peer = NULL;
  41         xmlNode *xml = string2xml(data);
  42 
  43         if (xml == NULL) {
  44             crm_err("Could not parse message content (%d): %.100s", kind, data);
  45             free(data);
  46             return;
  47         }
  48 
  49         crm_xml_add(xml, F_ORIG, from);
  50         /* crm_xml_add_int(xml, F_SEQ, wrapper->id); Fake? */
  51 
  52         peer = crm_get_peer(0, from);
  53         if (!pcmk_is_set(peer->processes, crm_proc_cpg)) {
  54             /* If we can still talk to our peer process on that node,
  55              * then it must be part of the corosync membership
  56              */
  57             crm_warn("Receiving messages from a node we think is dead: %s[%d]",
  58                      peer->uname, peer->id);
  59             crm_update_peer_proc(__func__, peer, crm_proc_cpg,
  60                                  ONLINESTATUS);
  61         }
  62         crmd_ha_msg_filter(xml);
  63         free_xml(xml);
  64     } else {
  65         crm_err("Invalid message class (%d): %.100s", kind, data);
  66     }
  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     } else {
  86         crm_info("Corosync connection closed");
  87     }
  88 }
  89 
  90 /*!
  91  * \brief Handle a Corosync notification of a CPG configuration change
  92  *
  93  * \param[in] handle               CPG connection
  94  * \param[in] cpg_name             CPG group name
  95  * \param[in] member_list          List of current CPG members
  96  * \param[in] member_list_entries  Number of entries in \p member_list
  97  * \param[in] left_list            List of CPG members that left
  98  * \param[in] left_list_entries    Number of entries in \p left_list
  99  * \param[in] joined_list          List of CPG members that joined
 100  * \param[in] joined_list_entries  Number of entries in \p joined_list
 101  */
 102 static void
 103 cpg_membership_callback(cpg_handle_t handle, const struct cpg_name *cpg_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 104                         const struct cpg_address *member_list,
 105                         size_t member_list_entries,
 106                         const struct cpg_address *left_list,
 107                         size_t left_list_entries,
 108                         const struct cpg_address *joined_list,
 109                         size_t joined_list_entries)
 110 {
 111     /* When nodes leave CPG, the DC clears their transient node attributes.
 112      *
 113      * However if there is no DC, or the DC is among the nodes that left, each
 114      * remaining node needs to do the clearing, to ensure it gets done.
 115      * Otherwise, the attributes would persist when the nodes rejoin, which
 116      * could have serious consequences for unfencing, agents that use attributes
 117      * for internal logic, etc.
 118      *
 119      * Here, we set a global boolean if the DC is among the nodes that left, for
 120      * use by the peer callback.
 121      */
 122     if (controld_globals.dc_name != NULL) {
 123         crm_node_t *peer = NULL;
 124 
 125         peer = pcmk__search_cluster_node_cache(0, controld_globals.dc_name);
 126         if (peer != NULL) {
 127             for (int i = 0; i < left_list_entries; ++i) {
 128                 if (left_list[i].nodeid == peer->id) {
 129                     controld_set_global_flags(controld_dc_left);
 130                     break;
 131                 }
 132             }
 133         }
 134     }
 135 
 136     // Process the change normally, which will call the peer callback as needed
 137     pcmk_cpg_membership(handle, cpg_name, member_list, member_list_entries,
 138                         left_list, left_list_entries,
 139                         joined_list, joined_list_entries);
 140 
 141     controld_clear_global_flags(controld_dc_left);
 142 }
 143 
 144 extern gboolean crm_connect_corosync(crm_cluster_t * cluster);
 145 
 146 gboolean
 147 crm_connect_corosync(crm_cluster_t * cluster)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149     if (is_corosync_cluster()) {
 150         crm_set_status_callback(&peer_update_callback);
 151         cluster->cpg.cpg_deliver_fn = crmd_cs_dispatch;
 152         cluster->cpg.cpg_confchg_fn = cpg_membership_callback;
 153         cluster->destroy = crmd_cs_destroy;
 154 
 155         if (crm_cluster_connect(cluster)) {
 156             pcmk__corosync_quorum_connect(crmd_quorum_callback,
 157                                           crmd_cs_destroy);
 158             return TRUE;
 159         }
 160     }
 161     return FALSE;
 162 }
 163 
 164 #endif

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