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-2023 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
 144     {
 145         NULL, FALSE, FALSE,
 146         cib_prepare_none, cib_cleanup_none, cib_process_default
 147     },
 148     {
 149         PCMK__CIB_REQUEST_QUERY, FALSE, FALSE,
 150         cib_prepare_none, cib_cleanup_query, cib_process_query
 151     },
 152     {
 153         PCMK__CIB_REQUEST_MODIFY, TRUE, TRUE,
 154         cib_prepare_data, cib_cleanup_data, cib_process_modify
 155     },
 156     {
 157         PCMK__CIB_REQUEST_APPLY_PATCH, TRUE, TRUE,
 158         cib_prepare_diff, cib_cleanup_data, cib_server_process_diff
 159     },
 160     {
 161         PCMK__CIB_REQUEST_REPLACE, TRUE, TRUE,
 162         cib_prepare_data, cib_cleanup_data, cib_process_replace_svr
 163     },
 164     {
 165         PCMK__CIB_REQUEST_CREATE, TRUE, TRUE,
 166         cib_prepare_data, cib_cleanup_data, cib_process_create
 167     },
 168     {
 169         PCMK__CIB_REQUEST_DELETE, TRUE, TRUE,
 170         cib_prepare_data, cib_cleanup_data, cib_process_delete
 171     },
 172     {
 173         PCMK__CIB_REQUEST_SYNC_TO_ALL, FALSE, TRUE,
 174         cib_prepare_sync, cib_cleanup_none, cib_process_sync
 175     },
 176     {
 177         PCMK__CIB_REQUEST_BUMP, TRUE, TRUE,
 178         cib_prepare_none, cib_cleanup_output, cib_process_bump
 179     },
 180     {
 181         PCMK__CIB_REQUEST_ERASE, TRUE, TRUE,
 182         cib_prepare_none, cib_cleanup_output, cib_process_erase
 183     },
 184     {
 185         PCMK__CIB_REQUEST_NOOP, FALSE, FALSE,
 186         cib_prepare_none, cib_cleanup_none, cib_process_default
 187     },
 188     {
 189         PCMK__CIB_REQUEST_ABS_DELETE, TRUE, TRUE,
 190         cib_prepare_data, cib_cleanup_data, cib_process_delete_absolute
 191     },
 192     {
 193         PCMK__CIB_REQUEST_UPGRADE, TRUE, TRUE,
 194         cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server
 195     },
 196     {
 197         PCMK__CIB_REQUEST_SECONDARY, FALSE, TRUE,
 198         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
 199     },
 200     {
 201         PCMK__CIB_REQUEST_ALL_SECONDARY, FALSE, TRUE,
 202         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
 203     },
 204     {
 205         PCMK__CIB_REQUEST_SYNC_TO_ONE, FALSE, TRUE,
 206         cib_prepare_sync, cib_cleanup_none, cib_process_sync_one
 207     },
 208     {
 209         PCMK__CIB_REQUEST_PRIMARY, TRUE, TRUE,
 210         cib_prepare_data, cib_cleanup_data, cib_process_readwrite
 211     },
 212     {
 213         PCMK__CIB_REQUEST_IS_PRIMARY, FALSE, TRUE,
 214         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
 215     },
 216     {
 217         PCMK__CIB_REQUEST_SHUTDOWN, FALSE, TRUE,
 218         cib_prepare_sync, cib_cleanup_none, cib_process_shutdown_req
 219     },
 220     {
 221         CRM_OP_PING, FALSE, FALSE,
 222         cib_prepare_none, cib_cleanup_output, cib_process_ping
 223     },
 224 };
 225 
 226 int
 227 cib_get_operation_id(const char *op, int *operation)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229     static GHashTable *operation_hash = NULL;
 230 
 231     if (operation_hash == NULL) {
 232         int lpc = 0;
 233         int max_msg_types = PCMK__NELEM(cib_server_ops);
 234 
 235         operation_hash = pcmk__strkey_table(NULL, free);
 236         for (lpc = 1; lpc < max_msg_types; lpc++) {
 237             int *value = malloc(sizeof(int));
 238 
 239             if(value) {
 240                 *value = lpc;
 241                 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
 242             }
 243         }
 244     }
 245 
 246     if (op != NULL) {
 247         int *value = g_hash_table_lookup(operation_hash, op);
 248 
 249         if (value) {
 250             *operation = *value;
 251             return pcmk_ok;
 252         }
 253     }
 254     crm_err("Operation %s is not valid", op);
 255     *operation = -1;
 256     return -EINVAL;
 257 }
 258 
 259 xmlNode *
 260 cib_msg_copy(xmlNode * msg, gboolean with_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262     int lpc = 0;
 263     const char *field = NULL;
 264     const char *value = NULL;
 265     xmlNode *value_struct = NULL;
 266 
 267     static const char *field_list[] = {
 268         F_XML_TAGNAME,
 269         F_TYPE,
 270         F_CIB_CLIENTID,
 271         F_CIB_CALLOPTS,
 272         F_CIB_CALLID,
 273         F_CIB_OPERATION,
 274         F_CIB_ISREPLY,
 275         F_CIB_SECTION,
 276         F_CIB_HOST,
 277         F_CIB_RC,
 278         F_CIB_DELEGATED,
 279         F_CIB_OBJID,
 280         F_CIB_OBJTYPE,
 281         F_CIB_EXISTING,
 282         F_CIB_SEENCOUNT,
 283         F_CIB_TIMEOUT,
 284         F_CIB_GLOBAL_UPDATE,
 285         F_CIB_CLIENTNAME,
 286         F_CIB_USER,
 287         F_CIB_NOTIFY_TYPE,
 288         F_CIB_NOTIFY_ACTIVATE
 289     };
 290 
 291     static const char *data_list[] = {
 292         F_CIB_CALLDATA,
 293         F_CIB_UPDATE,
 294         F_CIB_UPDATE_RESULT
 295     };
 296 
 297     xmlNode *copy = create_xml_node(NULL, "copy");
 298 
 299     CRM_ASSERT(copy != NULL);
 300 
 301     for (lpc = 0; lpc < PCMK__NELEM(field_list); lpc++) {
 302         field = field_list[lpc];
 303         value = crm_element_value(msg, field);
 304         if (value != NULL) {
 305             crm_xml_add(copy, field, value);
 306         }
 307     }
 308     for (lpc = 0; with_data && lpc < PCMK__NELEM(data_list); lpc++) {
 309         field = data_list[lpc];
 310         value_struct = get_message_xml(msg, field);
 311         if (value_struct != NULL) {
 312             add_message_xml(copy, field, value_struct);
 313         }
 314     }
 315 
 316     return copy;
 317 }
 318 
 319 cib_op_t *
 320 cib_op_func(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322     return &(cib_server_ops[call_type].fn);
 323 }
 324 
 325 gboolean
 326 cib_op_modifies(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 327 {
 328     return cib_server_ops[call_type].modifies_cib;
 329 }
 330 
 331 int
 332 cib_op_can_run(int call_type, int call_options, bool privileged)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334     if (!privileged && cib_server_ops[call_type].needs_privileges) {
 335         return -EACCES;
 336     }
 337     return pcmk_ok;
 338 }
 339 
 340 int
 341 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
 342 {
 343     crm_trace("Prepare %d", call_type);
 344     return cib_server_ops[call_type].prepare(request, input, section);
 345 }
 346 
 347 int
 348 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 349 {
 350     crm_trace("Cleanup %d", call_type);
 351     return cib_server_ops[call_type].cleanup(options, input, output);
 352 }

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