root/daemons/based/based_common.c

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

DEFINITIONS

This source file includes following definitions.
  1. cib_prepare_common
  2. cib_prepare_none
  3. cib_prepare_data
  4. cib_prepare_sync
  5. cib_prepare_diff
  6. cib_cleanup_query
  7. cib_cleanup_data
  8. cib_cleanup_output
  9. cib_cleanup_none
  10. cib_get_operation_id
  11. cib_msg_copy
  12. cib_op_func
  13. cib_op_modifies
  14. cib_op_can_run
  15. cib_op_prepare
  16. cib_op_cleanup

   1 /*
   2  * Copyright 2008-2021 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 <crm/crm.h>
  22 #include <crm/cib.h>
  23 #include <crm/msg_xml.h>
  24 #include <crm/common/ipc.h>
  25 #include <crm/cluster.h>
  26 
  27 #include <crm/common/xml.h>
  28 
  29 #include <pacemaker-based.h>
  30 
  31 gboolean stand_alone = FALSE;
  32 
  33 extern int cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff,
  34                                gboolean privileged);
  35 
  36 static xmlNode *
  37 cib_prepare_common(xmlNode * root, const char *section)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39     xmlNode *data = NULL;
  40 
  41     /* extract the CIB from the fragment */
  42     if (root == NULL) {
  43         return NULL;
  44 
  45     } else if (pcmk__strcase_any_of(crm_element_name(root), XML_TAG_FRAGMENT,
  46                                     F_CRM_DATA, F_CIB_CALLDATA, NULL)) {
  47         data = first_named_child(root, XML_TAG_CIB);
  48 
  49     } else {
  50         data = root;
  51     }
  52 
  53     /* grab the section specified for the command */
  54     if (section != NULL && data != NULL && pcmk__str_eq(crm_element_name(data), XML_TAG_CIB, pcmk__str_none)) {
  55         data = pcmk_find_cib_element(data, section);
  56     }
  57 
  58     /* crm_log_xml_trace(root, "cib:input"); */
  59     return data;
  60 }
  61 
  62 static int
  63 cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65     *data = NULL;
  66     *section = crm_element_value(request, F_CIB_SECTION);
  67     return pcmk_ok;
  68 }
  69 
  70 static int
  71 cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73     xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
  74 
  75     *section = crm_element_value(request, F_CIB_SECTION);
  76     *data = cib_prepare_common(input_fragment, *section);
  77     /* crm_log_xml_debug(*data, "data"); */
  78     return pcmk_ok;
  79 }
  80 
  81 static int
  82 cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84     *data = NULL;
  85     *section = crm_element_value(request, F_CIB_SECTION);
  86     return pcmk_ok;
  87 }
  88 
  89 static int
  90 cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92     xmlNode *input_fragment = NULL;
  93 
  94     *data = NULL;
  95     *section = NULL;
  96 
  97     if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
  98         input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
  99     } else {
 100         input_fragment = get_message_xml(request, F_CIB_CALLDATA);
 101     }
 102 
 103     CRM_CHECK(input_fragment != NULL, crm_log_xml_warn(request, "no input"));
 104     *data = cib_prepare_common(input_fragment, NULL);
 105     return pcmk_ok;
 106 }
 107 
 108 static int
 109 cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111     CRM_LOG_ASSERT(*data == NULL);
 112     if ((options & cib_no_children)
 113         || pcmk__str_eq(crm_element_name(*output), "xpath-query", pcmk__str_casei)) {
 114         free_xml(*output);
 115     }
 116     return pcmk_ok;
 117 }
 118 
 119 static int
 120 cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122     free_xml(*output);
 123     *data = NULL;
 124     return pcmk_ok;
 125 }
 126 
 127 static int
 128 cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130     free_xml(*output);
 131     return pcmk_ok;
 132 }
 133 
 134 static int
 135 cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137     CRM_LOG_ASSERT(*data == NULL);
 138     CRM_LOG_ASSERT(*output == NULL);
 139     return pcmk_ok;
 140 }
 141 
 142 static cib_operation_t cib_server_ops[] = {
 143     // Booleans are modifies_cib, needs_privileges, needs_quorum
 144     {NULL,             FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
 145     {CIB_OP_QUERY,     FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query,  cib_process_query},
 146     {CIB_OP_MODIFY,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_modify},
 147     {CIB_OP_APPLY_DIFF,TRUE,  TRUE,  TRUE,  cib_prepare_diff, cib_cleanup_data,   cib_server_process_diff},
 148     {CIB_OP_REPLACE,   TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_replace_svr},
 149     {CIB_OP_CREATE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_create},
 150     {CIB_OP_DELETE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete},
 151     {CIB_OP_SYNC,      FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_none,   cib_process_sync},
 152     {CIB_OP_BUMP,      TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_bump},
 153     {CIB_OP_ERASE,     TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_erase},
 154     {CRM_OP_NOOP,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
 155     {CIB_OP_DELETE_ALT,TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete_absolute},
 156     {CIB_OP_UPGRADE,   TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server},
 157     {CIB_OP_SLAVE,     FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 158     {CIB_OP_SLAVEALL,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 159     {CIB_OP_SYNC_ONE,  FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_none,   cib_process_sync_one},
 160     {CIB_OP_MASTER,    TRUE,  TRUE,  FALSE, cib_prepare_data, cib_cleanup_data,   cib_process_readwrite},
 161     {CIB_OP_ISMASTER,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 162     {"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_none,   cib_process_shutdown_req},
 163     {CRM_OP_PING,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping},
 164 };
 165 
 166 int
 167 cib_get_operation_id(const char *op, int *operation)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169     static GHashTable *operation_hash = NULL;
 170 
 171     if (operation_hash == NULL) {
 172         int lpc = 0;
 173         int max_msg_types = PCMK__NELEM(cib_server_ops);
 174 
 175         operation_hash = pcmk__strkey_table(NULL, free);
 176         for (lpc = 1; lpc < max_msg_types; lpc++) {
 177             int *value = malloc(sizeof(int));
 178 
 179             if(value) {
 180                 *value = lpc;
 181                 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
 182             }
 183         }
 184     }
 185 
 186     if (op != NULL) {
 187         int *value = g_hash_table_lookup(operation_hash, op);
 188 
 189         if (value) {
 190             *operation = *value;
 191             return pcmk_ok;
 192         }
 193     }
 194     crm_err("Operation %s is not valid", op);
 195     *operation = -1;
 196     return -EINVAL;
 197 }
 198 
 199 xmlNode *
 200 cib_msg_copy(xmlNode * msg, gboolean with_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202     int lpc = 0;
 203     const char *field = NULL;
 204     const char *value = NULL;
 205     xmlNode *value_struct = NULL;
 206 
 207     static const char *field_list[] = {
 208         F_XML_TAGNAME,
 209         F_TYPE,
 210         F_CIB_CLIENTID,
 211         F_CIB_CALLOPTS,
 212         F_CIB_CALLID,
 213         F_CIB_OPERATION,
 214         F_CIB_ISREPLY,
 215         F_CIB_SECTION,
 216         F_CIB_HOST,
 217         F_CIB_RC,
 218         F_CIB_DELEGATED,
 219         F_CIB_OBJID,
 220         F_CIB_OBJTYPE,
 221         F_CIB_EXISTING,
 222         F_CIB_SEENCOUNT,
 223         F_CIB_TIMEOUT,
 224         F_CIB_CALLBACK_TOKEN,
 225         F_CIB_GLOBAL_UPDATE,
 226         F_CIB_CLIENTNAME,
 227         F_CIB_USER,
 228         F_CIB_NOTIFY_TYPE,
 229         F_CIB_NOTIFY_ACTIVATE
 230     };
 231 
 232     static const char *data_list[] = {
 233         F_CIB_CALLDATA,
 234         F_CIB_UPDATE,
 235         F_CIB_UPDATE_RESULT
 236     };
 237 
 238     xmlNode *copy = create_xml_node(NULL, "copy");
 239 
 240     CRM_ASSERT(copy != NULL);
 241 
 242     for (lpc = 0; lpc < PCMK__NELEM(field_list); lpc++) {
 243         field = field_list[lpc];
 244         value = crm_element_value(msg, field);
 245         if (value != NULL) {
 246             crm_xml_add(copy, field, value);
 247         }
 248     }
 249     for (lpc = 0; with_data && lpc < PCMK__NELEM(data_list); lpc++) {
 250         field = data_list[lpc];
 251         value_struct = get_message_xml(msg, field);
 252         if (value_struct != NULL) {
 253             add_message_xml(copy, field, value_struct);
 254         }
 255     }
 256 
 257     return copy;
 258 }
 259 
 260 cib_op_t *
 261 cib_op_func(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263     return &(cib_server_ops[call_type].fn);
 264 }
 265 
 266 gboolean
 267 cib_op_modifies(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269     return cib_server_ops[call_type].modifies_cib;
 270 }
 271 
 272 int
 273 cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275     if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) {
 276         /* abort */
 277         return -EACCES;
 278     }
 279 #if 0
 280     if (rc == pcmk_ok
 281         && stand_alone == FALSE
 282         && global_update == FALSE
 283         && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) {
 284         return -pcmk_err_no_quorum;
 285     }
 286 #endif
 287     return pcmk_ok;
 288 }
 289 
 290 int
 291 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293     crm_trace("Prepare %d", call_type);
 294     return cib_server_ops[call_type].prepare(request, input, section);
 295 }
 296 
 297 int
 298 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 299 {
 300     crm_trace("Cleanup %d", call_type);
 301     return cib_server_ops[call_type].cleanup(options, input, output);
 302 }

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