root/maint/mocked/based-notifyfenced.c

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

DEFINITIONS

This source file includes following definitions.
  1. mock_based_cib_notify_send_one
  2. do_cib_notify
  3. mock_based_notifyfencedmer_callback_worker
  4. mock_based_notifyfenced_cib_notify_hook
  5. mock_based_notifyfenced_argparse_hook
  6. mock_based_notifyfenced_destroy_hook
  7. mock_based_notifyfenced_init

   1 /*
   2  * Copyright 2019-2020 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * Licensed under the GNU General Public License version 2 or later (GPLv2+).
   7  */
   8 
   9 /*
  10  * Intended demo use case:
  11  *
  12  * - as root, start corosync
  13  * - start "./based -N"; hint:
  14  *   su -s /bin/sh -c './based -N' hacluster
  15  * - start pacemaker-fenced; hint:
  16  *   su -c 'env PCMK_logpriority=crit ../../daemons/fenced/pacemaker-fenced'
  17  * - wait a bit (5 < seconds < 20)
  18  * - as haclient group (or root), run "stonith admin --list-registered"
  19  * - observe whether such invocation is blocked or not
  20  */
  21 
  22 
  23 #include <stdio.h>  /* printf, perror */
  24 
  25 #include "crm/cib.h"  /* cib_zero_copy */
  26 #include "crm/cib/internal.h"  /* CIB_OP_CREATE */
  27 #include "crm/msg_xml.h"  /* F_SUBTYPE */
  28 #include "daemons/based/pacemaker-based.h"  /* cib_notify_diff */
  29 
  30 #include "based.h"
  31 
  32 
  33 #define OPTCHAR 'N'
  34 static size_t module_handle;
  35 
  36 
  37 struct cib_notification_s {
  38     xmlNode *msg;
  39     struct iovec *iov;
  40     int32_t iov_size;
  41 };
  42 
  43 /* see based/based_notify.c:cib_notify_send_one */
  44 static bool
  45 mock_based_cib_notify_send_one(pcmk__client_t *client, xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47     const char *type = NULL;
  48     bool do_send = false;
  49     struct iovec *iov;
  50     ssize_t bytes;
  51     struct cib_notification_s update = {
  52         .msg = xml,
  53     };
  54 
  55     CRM_CHECK(client != NULL, return true);
  56     pcmk__ipc_prepare_iov(0, xml, 0, &iov, &bytes);
  57     update.iov = iov;
  58     update.iov_size = bytes;
  59     if (client->ipcs == NULL && client->remote == NULL) {
  60         crm_warn("Skipping client with NULL channel");
  61         return FALSE;
  62     }
  63 
  64     type = crm_element_value(update.msg, F_SUBTYPE);
  65     CRM_LOG_ASSERT(type != NULL);
  66     if (pcmk_is_set(client->options, cib_notify_diff)
  67         && pcmk__str_eq(type, T_CIB_DIFF_NOTIFY, pcmk__str_casei)) {
  68 
  69         if (pcmk__ipc_send_iov(client, update.iov,
  70                                crm_ipc_server_event) != pcmk_rc_ok) {
  71             crm_warn("Notification of client %s/%s failed", client->name, client->id);
  72         }
  73 
  74     }
  75     pcmk_free_ipc_event(iov);
  76 
  77     return FALSE;
  78 }
  79 
  80 /* see based/based_notify.c:do_cib_notify + cib_notify_send */
  81 void
  82 do_cib_notify(pcmk__client_t *cib_client, int options, const char *op,
     /* [previous][next][first][last][top][bottom][index][help] */
  83               xmlNode *update, int result, xmlNode *result_data,
  84               const char *msg_type)
  85 {
  86     xmlNode *update_msg = NULL;
  87     const char *id = NULL;
  88 
  89     update_msg = create_xml_node(NULL, "notify");
  90 
  91 
  92     crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
  93     crm_xml_add(update_msg, F_SUBTYPE, msg_type);
  94     crm_xml_add(update_msg, F_CIB_OPERATION, op);
  95     crm_xml_add_int(update_msg, F_CIB_RC, result);
  96 
  97     if (result_data != NULL) {
  98         id = crm_element_value(result_data, XML_ATTR_ID);
  99         if (id != NULL)
 100             crm_xml_add(update_msg, F_CIB_OBJID, id);
 101     }
 102 
 103     if (update != NULL) {
 104         crm_trace("Setting type to update->name: %s", crm_element_name(update));
 105         crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
 106 
 107     } else if (result_data != NULL) {
 108         crm_trace("Setting type to new_obj->name: %s", crm_element_name(result_data));
 109         crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
 110 
 111     } else {
 112         crm_trace("Not Setting type");
 113     }
 114 
 115 #if 0
 116     attach_cib_generation(update_msg, "cib_generation", the_cib);
 117 #endif
 118 
 119     if (update != NULL) {
 120         add_message_xml(update_msg, F_CIB_UPDATE, update);
 121     }
 122     if (result_data != NULL) {
 123         add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
 124     }
 125 
 126     mock_based_cib_notify_send_one(cib_client, update_msg);
 127     free_xml(update_msg);
 128 }
 129 
 130 static gboolean
 131 mock_based_notifyfencedmer_callback_worker(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133     pcmk__client_t *cib_client = (pcmk__client_t *) data;
 134 
 135     xmlNode *result_data;
 136     xmlNode *input, *update;
 137     int options;
 138     char update_str[4096];
 139 
 140     cib__set_call_options(options, crm_system_name, cib_zero_copy);
 141 
 142 
 143     input = create_xml_node(NULL, "cib");
 144 
 145     /* spam it */
 146 #if 0
 147     for (size_t i = 0; i < SIZE_MAX - 1; i++) {
 148 #else
 149     for (size_t i = 0; i < 10000; i++) {
 150 #endif
 151         /* NOTE: we need to trigger fenced attention, add new fence device */
 152         snprintf(update_str, sizeof(update_str),
 153 "<diff crm_feature_set='3.1.0' format='1'>\n"
 154 "  <diff-removed admin_epoch='%1$llu' epoch='%1$llu' num_updates='%1$llu'>\n"
 155 "    <cib admin_epoch='%1$llu' epoch='%1$llu' num_updates='%1$llu'/>\n"
 156 "  </diff-removed>\n"
 157 "  <diff-added admin_epoch='%2$llu' epoch='%2$llu' num_updates='%2$llu'>\n"
 158 "    <cib validate-with='pacemaker-1.2' admin_epoch='%2$llu' epoch='%2$llu' num_updates='%2$llu'>\n"
 159 "      <configuration>\n"
 160 "        <resources>\n"
 161 "          <primitive id='FENCEDEV-fence-dummy-%2$llu' class='stonith' type='__apparently_bogus__' __crm_diff_marker__='added:top'/>\n"
 162 "        </resources>\n"
 163 "      </configuration>\n"
 164 "    </cib>\n"
 165 "  </diff-added>\n"
 166 "</diff>\n", i, i+1);
 167         update = xmlReadMemory(update_str, sizeof(update_str),
 168                                "file:///tmp/update", NULL, 0)->children;
 169         do_cib_notify(cib_client, options, CIB_OP_CREATE, input, pcmk_ok,
 170                       update, T_CIB_DIFF_NOTIFY);
 171         free_xml(update);
 172     };
 173 
 174     free_xml(input);
 175 }
 176 
 177 static void
 178 mock_based_notifyfenced_cib_notify_hook(pcmk__client_t *cib_client)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180 
 181     /* MOCK: client asked for upcoming diff's, let's
 182              spam it a bit after a while... */
 183     crm_info("Going to spam %s (%s) in 5 seconds...",
 184              cib_client->name, cib_client->id);
 185     mainloop_timer_start(mainloop_timer_add("spammer", 5000, FALSE,
 186                          mock_based_notifyfencedmer_callback_worker,
 187                          cib_client));
 188 }
 189 
 190 /* * */
 191 
 192 static int
 193 mock_based_notifyfenced_argparse_hook(struct mock_based_context_s *ctxt,
     /* [previous][next][first][last][top][bottom][index][help] */
 194                                     bool usage, int argc_to_go,
 195                                     const char *argv_to_go[])
 196 {
 197     const char *opt = *argv_to_go;
 198 restart:
 199     switch(*opt) {
 200     case '-':
 201         if (opt == *argv_to_go) {
 202             opt++;
 203             goto restart;
 204         }
 205         break;
 206     case OPTCHAR:
 207         if (usage) {
 208             printf("spam the \"cib diff\" notification client"
 209                    " (targeting pacemaker-fenced in particular)\n");
 210 
 211         } else {
 212 #if 0
 213             ctxt->modules[module_handle]->priv =
 214                 malloc(sizeof(mock_based_notifyfenced_priv_t));
 215             if (ctxt->modules[module_handle]->priv == NULL) {
 216                 perror("malloc");
 217                 return -1;
 218             }
 219 #endif
 220         }
 221         return 1;
 222     }
 223     return 0;
 224 }
 225 
 226 #if 0
 227 static void
 228 mock_based_notifyfenced_destroy_hook(module_t *mod) {
     /* [previous][next][first][last][top][bottom][index][help] */
 229     free(mod->priv);
 230 }
 231 #endif
 232 
 233 __attribute__((__constructor__))
 234 void
 235 mock_based_notifyfenced_init(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 236     module_handle = mock_based_register_module((module_t){
 237         .shortopt = OPTCHAR,
 238         .hooks = {
 239             .argparse = mock_based_notifyfenced_argparse_hook,
 240             //.destroy = mock_based_notifyfenced_destroy_hook,
 241             /* specialized hooks */
 242             .cib_notify = mock_based_notifyfenced_cib_notify_hook,
 243         }
 244     });
 245 }

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