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

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