root/daemons/based/based_notify.c

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

DEFINITIONS

This source file includes following definitions.
  1. cib_notify_send_one
  2. cib_notify_send
  3. cib_diff_notify
  4. do_cib_notify
  5. attach_cib_generation
  6. cib_replace_notify

   1 /*
   2  * Copyright 2004-2020 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 <stdio.h>
  14 #include <sys/types.h>
  15 #include <unistd.h>
  16 #include <inttypes.h>           // PRIx64
  17 
  18 #include <stdlib.h>
  19 #include <errno.h>
  20 #include <fcntl.h>
  21 
  22 #include <time.h>
  23 
  24 #include <crm/crm.h>
  25 #include <crm/cib/internal.h>
  26 #include <crm/msg_xml.h>
  27 
  28 #include <crm/common/xml.h>
  29 #include <crm/common/remote_internal.h>
  30 #include <pacemaker-based.h>
  31 
  32 int pending_updates = 0;
  33 
  34 struct cib_notification_s {
  35     xmlNode *msg;
  36     struct iovec *iov;
  37     int32_t iov_size;
  38 };
  39 
  40 void attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib);
  41 
  42 static void do_cib_notify(int options, const char *op, xmlNode *update,
  43                           int result, xmlNode * result_data,
  44                           const char *msg_type);
  45 
  46 static void
  47 cib_notify_send_one(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49     const char *type = NULL;
  50     gboolean do_send = FALSE;
  51     int rc = pcmk_rc_ok;
  52 
  53     pcmk__client_t *client = value;
  54     struct cib_notification_s *update = user_data;
  55 
  56     if (client->ipcs == NULL && client->remote == NULL) {
  57         crm_warn("Skipping client with NULL channel");
  58         return;
  59     }
  60 
  61     type = crm_element_value(update->msg, F_SUBTYPE);
  62     CRM_LOG_ASSERT(type != NULL);
  63 
  64     if (pcmk_is_set(client->flags, cib_notify_diff)
  65         && pcmk__str_eq(type, T_CIB_DIFF_NOTIFY, pcmk__str_casei)) {
  66 
  67         do_send = TRUE;
  68 
  69     } else if (pcmk_is_set(client->flags, cib_notify_replace)
  70                && pcmk__str_eq(type, T_CIB_REPLACE_NOTIFY, pcmk__str_casei)) {
  71         do_send = TRUE;
  72 
  73     } else if (pcmk_is_set(client->flags, cib_notify_confirm)
  74                && pcmk__str_eq(type, T_CIB_UPDATE_CONFIRM, pcmk__str_casei)) {
  75         do_send = TRUE;
  76 
  77     } else if (pcmk_is_set(client->flags, cib_notify_pre)
  78                && pcmk__str_eq(type, T_CIB_PRE_NOTIFY, pcmk__str_casei)) {
  79         do_send = TRUE;
  80 
  81     } else if (pcmk_is_set(client->flags, cib_notify_post)
  82                && pcmk__str_eq(type, T_CIB_POST_NOTIFY, pcmk__str_casei)) {
  83 
  84         do_send = TRUE;
  85     }
  86 
  87     if (do_send) {
  88         switch (PCMK__CLIENT_TYPE(client)) {
  89             case pcmk__client_ipc:
  90                 rc = pcmk__ipc_send_iov(client, update->iov,
  91                                         crm_ipc_server_event);
  92                 if (rc != pcmk_rc_ok) {
  93                     crm_warn("Could not notify client %s: %s " CRM_XS " id=%s",
  94                              pcmk__client_name(client), pcmk_rc_str(rc),
  95                              client->id);
  96                 }
  97                 break;
  98 #ifdef HAVE_GNUTLS_GNUTLS_H
  99             case pcmk__client_tls:
 100 #endif
 101             case pcmk__client_tcp:
 102                 crm_debug("Sent %s notification to client %s (id %s)",
 103                           type, pcmk__client_name(client), client->id);
 104                 pcmk__remote_send_xml(client->remote, update->msg);
 105                 break;
 106             default:
 107                 crm_err("Unknown transport for client %s "
 108                         CRM_XS " flags=0x%016" PRIx64,
 109                         pcmk__client_name(client), client->flags);
 110         }
 111     }
 112 }
 113 
 114 static void
 115 cib_notify_send(xmlNode * xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117     struct iovec *iov;
 118     struct cib_notification_s update;
 119 
 120     ssize_t bytes = 0;
 121     int rc = pcmk__ipc_prepare_iov(0, xml, 0, &iov, &bytes);
 122 
 123     if (rc == pcmk_rc_ok) {
 124         update.msg = xml;
 125         update.iov = iov;
 126         update.iov_size = bytes;
 127         pcmk__foreach_ipc_client(cib_notify_send_one, &update);
 128 
 129     } else {
 130         crm_notice("Could not notify clients: %s " CRM_XS " rc=%d",
 131                    pcmk_rc_str(rc), rc);
 132     }
 133     pcmk_free_ipc_event(iov);
 134 }
 135 
 136 void
 137 cib_diff_notify(int options, const char *client, const char *call_id, const char *op,
     /* [previous][next][first][last][top][bottom][index][help] */
 138                 xmlNode * update, int result, xmlNode * diff)
 139 {
 140     int add_updates = 0;
 141     int add_epoch = 0;
 142     int add_admin_epoch = 0;
 143 
 144     int del_updates = 0;
 145     int del_epoch = 0;
 146     int del_admin_epoch = 0;
 147 
 148     int log_level = LOG_TRACE;
 149 
 150     if (diff == NULL) {
 151         return;
 152     }
 153 
 154     if (result != pcmk_ok) {
 155         log_level = LOG_WARNING;
 156     }
 157 
 158     cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
 159                              &del_admin_epoch, &del_epoch, &del_updates);
 160 
 161     if (add_updates != del_updates) {
 162         do_crm_log(log_level,
 163                    "Update (client: %s%s%s): %d.%d.%d -> %d.%d.%d (%s)",
 164                    client, call_id ? ", call:" : "", call_id ? call_id : "",
 165                    del_admin_epoch, del_epoch, del_updates,
 166                    add_admin_epoch, add_epoch, add_updates, pcmk_strerror(result));
 167 
 168     } else if (diff != NULL) {
 169         do_crm_log(log_level,
 170                    "Local-only Change (client:%s%s%s): %d.%d.%d (%s)",
 171                    client, call_id ? ", call: " : "", call_id ? call_id : "",
 172                    add_admin_epoch, add_epoch, add_updates, pcmk_strerror(result));
 173     }
 174 
 175     do_cib_notify(options, op, update, result, diff, T_CIB_DIFF_NOTIFY);
 176 }
 177 
 178 static void
 179 do_cib_notify(int options, const char *op, xmlNode * update,
     /* [previous][next][first][last][top][bottom][index][help] */
 180               int result, xmlNode * result_data, const char *msg_type)
 181 {
 182     xmlNode *update_msg = NULL;
 183     const char *id = NULL;
 184 
 185     update_msg = create_xml_node(NULL, "notify");
 186 
 187     if (result_data != NULL) {
 188         id = crm_element_value(result_data, XML_ATTR_ID);
 189     }
 190 
 191     crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
 192     crm_xml_add(update_msg, F_SUBTYPE, msg_type);
 193     crm_xml_add(update_msg, F_CIB_OPERATION, op);
 194     crm_xml_add_int(update_msg, F_CIB_RC, result);
 195 
 196     if (id != NULL) {
 197         crm_xml_add(update_msg, F_CIB_OBJID, id);
 198     }
 199 
 200     if (update != NULL) {
 201         crm_trace("Setting type to update->name: %s", crm_element_name(update));
 202         crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
 203 
 204     } else if (result_data != NULL) {
 205         crm_trace("Setting type to new_obj->name: %s", crm_element_name(result_data));
 206         crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
 207 
 208     } else {
 209         crm_trace("Not Setting type");
 210     }
 211 
 212     attach_cib_generation(update_msg, "cib_generation", the_cib);
 213     if (update != NULL) {
 214         add_message_xml(update_msg, F_CIB_UPDATE, update);
 215     }
 216     if (result_data != NULL) {
 217         add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
 218     }
 219 
 220     cib_notify_send(update_msg);
 221     free_xml(update_msg);
 222 }
 223 
 224 void
 225 attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib)
     /* [previous][next][first][last][top][bottom][index][help] */
 226 {
 227     xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
 228 
 229     if (a_cib != NULL) {
 230         copy_in_properties(generation, a_cib);
 231     }
 232     add_message_xml(msg, field, generation);
 233     free_xml(generation);
 234 }
 235 
 236 void
 237 cib_replace_notify(const char *origin, xmlNode * update, int result, xmlNode * diff)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239     xmlNode *replace_msg = NULL;
 240 
 241     int add_updates = 0;
 242     int add_epoch = 0;
 243     int add_admin_epoch = 0;
 244 
 245     int del_updates = 0;
 246     int del_epoch = 0;
 247     int del_admin_epoch = 0;
 248 
 249     if (diff == NULL) {
 250         return;
 251     }
 252 
 253     cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
 254                              &del_admin_epoch, &del_epoch, &del_updates);
 255 
 256     if (del_updates < 0) {
 257         crm_log_xml_debug(diff, "Bad replace diff");
 258     }
 259 
 260     if (add_updates != del_updates) {
 261         crm_info("Replaced: %d.%d.%d -> %d.%d.%d from %s",
 262                  del_admin_epoch, del_epoch, del_updates,
 263                  add_admin_epoch, add_epoch, add_updates, crm_str(origin));
 264     } else if (diff != NULL) {
 265         crm_info("Local-only Replace: %d.%d.%d from %s",
 266                  add_admin_epoch, add_epoch, add_updates, crm_str(origin));
 267     }
 268 
 269     replace_msg = create_xml_node(NULL, "notify-replace");
 270     crm_xml_add(replace_msg, F_TYPE, T_CIB_NOTIFY);
 271     crm_xml_add(replace_msg, F_SUBTYPE, T_CIB_REPLACE_NOTIFY);
 272     crm_xml_add(replace_msg, F_CIB_OPERATION, CIB_OP_REPLACE);
 273     crm_xml_add_int(replace_msg, F_CIB_RC, result);
 274     attach_cib_generation(replace_msg, "cib-replace-generation", update);
 275 
 276     crm_log_xml_trace(replace_msg, "CIB Replaced");
 277 
 278     cib_notify_send(replace_msg);
 279     free_xml(replace_msg);
 280 }

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