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 = get_object_root(section, data);
  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     const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
  94 
  95     *data = NULL;
  96     *section = NULL;
  97 
  98     if (crm_is_true(update)) {
  99         input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
 100 
 101     } else {
 102         input_fragment = get_message_xml(request, F_CIB_CALLDATA);
 103     }
 104 
 105     CRM_CHECK(input_fragment != NULL, crm_log_xml_warn(request, "no input"));
 106     *data = cib_prepare_common(input_fragment, NULL);
 107     return pcmk_ok;
 108 }
 109 
 110 static int
 111 cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 112 {
 113     CRM_LOG_ASSERT(*data == NULL);
 114     if ((options & cib_no_children)
 115         || pcmk__str_eq(crm_element_name(*output), "xpath-query", pcmk__str_casei)) {
 116         free_xml(*output);
 117     }
 118     return pcmk_ok;
 119 }
 120 
 121 static int
 122 cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124     free_xml(*output);
 125     *data = NULL;
 126     return pcmk_ok;
 127 }
 128 
 129 static int
 130 cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132     free_xml(*output);
 133     return pcmk_ok;
 134 }
 135 
 136 static int
 137 cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139     CRM_LOG_ASSERT(*data == NULL);
 140     CRM_LOG_ASSERT(*output == NULL);
 141     return pcmk_ok;
 142 }
 143 
 144 static cib_operation_t cib_server_ops[] = {
 145     // Booleans are modifies_cib, needs_privileges, needs_quorum
 146     {NULL,             FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
 147     {CIB_OP_QUERY,     FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query,  cib_process_query},
 148     {CIB_OP_MODIFY,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_modify},
 149     {CIB_OP_APPLY_DIFF,TRUE,  TRUE,  TRUE,  cib_prepare_diff, cib_cleanup_data,   cib_server_process_diff},
 150     {CIB_OP_REPLACE,   TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_replace_svr},
 151     {CIB_OP_CREATE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_create},
 152     {CIB_OP_DELETE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete},
 153     {CIB_OP_SYNC,      FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_none,   cib_process_sync},
 154     {CIB_OP_BUMP,      TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_bump},
 155     {CIB_OP_ERASE,     TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_erase},
 156     {CRM_OP_NOOP,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
 157     {CIB_OP_DELETE_ALT,TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete_absolute},
 158     {CIB_OP_UPGRADE,   TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server},
 159     {CIB_OP_SLAVE,     FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 160     {CIB_OP_SLAVEALL,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 161     {CIB_OP_SYNC_ONE,  FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_none,   cib_process_sync_one},
 162     {CIB_OP_MASTER,    TRUE,  TRUE,  FALSE, cib_prepare_data, cib_cleanup_data,   cib_process_readwrite},
 163     {CIB_OP_ISMASTER,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 164     {"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_none,   cib_process_shutdown_req},
 165     {CRM_OP_PING,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping},
 166 };
 167 
 168 int
 169 cib_get_operation_id(const char *op, int *operation)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171     static GHashTable *operation_hash = NULL;
 172 
 173     if (operation_hash == NULL) {
 174         int lpc = 0;
 175         int max_msg_types = PCMK__NELEM(cib_server_ops);
 176 
 177         operation_hash = pcmk__strkey_table(NULL, free);
 178         for (lpc = 1; lpc < max_msg_types; lpc++) {
 179             int *value = malloc(sizeof(int));
 180 
 181             if(value) {
 182                 *value = lpc;
 183                 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
 184             }
 185         }
 186     }
 187 
 188     if (op != NULL) {
 189         int *value = g_hash_table_lookup(operation_hash, op);
 190 
 191         if (value) {
 192             *operation = *value;
 193             return pcmk_ok;
 194         }
 195     }
 196     crm_err("Operation %s is not valid", op);
 197     *operation = -1;
 198     return -EINVAL;
 199 }
 200 
 201 xmlNode *
 202 cib_msg_copy(xmlNode * msg, gboolean with_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204     int lpc = 0;
 205     const char *field = NULL;
 206     const char *value = NULL;
 207     xmlNode *value_struct = NULL;
 208 
 209     static const char *field_list[] = {
 210         F_XML_TAGNAME,
 211         F_TYPE,
 212         F_CIB_CLIENTID,
 213         F_CIB_CALLOPTS,
 214         F_CIB_CALLID,
 215         F_CIB_OPERATION,
 216         F_CIB_ISREPLY,
 217         F_CIB_SECTION,
 218         F_CIB_HOST,
 219         F_CIB_RC,
 220         F_CIB_DELEGATED,
 221         F_CIB_OBJID,
 222         F_CIB_OBJTYPE,
 223         F_CIB_EXISTING,
 224         F_CIB_SEENCOUNT,
 225         F_CIB_TIMEOUT,
 226         F_CIB_CALLBACK_TOKEN,
 227         F_CIB_GLOBAL_UPDATE,
 228         F_CIB_CLIENTNAME,
 229         F_CIB_USER,
 230         F_CIB_NOTIFY_TYPE,
 231         F_CIB_NOTIFY_ACTIVATE
 232     };
 233 
 234     static const char *data_list[] = {
 235         F_CIB_CALLDATA,
 236         F_CIB_UPDATE,
 237         F_CIB_UPDATE_RESULT
 238     };
 239 
 240     xmlNode *copy = create_xml_node(NULL, "copy");
 241 
 242     CRM_ASSERT(copy != NULL);
 243 
 244     for (lpc = 0; lpc < PCMK__NELEM(field_list); lpc++) {
 245         field = field_list[lpc];
 246         value = crm_element_value(msg, field);
 247         if (value != NULL) {
 248             crm_xml_add(copy, field, value);
 249         }
 250     }
 251     for (lpc = 0; with_data && lpc < PCMK__NELEM(data_list); lpc++) {
 252         field = data_list[lpc];
 253         value_struct = get_message_xml(msg, field);
 254         if (value_struct != NULL) {
 255             add_message_xml(copy, field, value_struct);
 256         }
 257     }
 258 
 259     return copy;
 260 }
 261 
 262 cib_op_t *
 263 cib_op_func(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 264 {
 265     return &(cib_server_ops[call_type].fn);
 266 }
 267 
 268 gboolean
 269 cib_op_modifies(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271     return cib_server_ops[call_type].modifies_cib;
 272 }
 273 
 274 int
 275 cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277     if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) {
 278         /* abort */
 279         return -EACCES;
 280     }
 281 #if 0
 282     if (rc == pcmk_ok
 283         && stand_alone == FALSE
 284         && global_update == FALSE
 285         && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) {
 286         return -pcmk_err_no_quorum;
 287     }
 288 #endif
 289     return pcmk_ok;
 290 }
 291 
 292 int
 293 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
 294 {
 295     crm_trace("Prepare %d", call_type);
 296     return cib_server_ops[call_type].prepare(request, input, section);
 297 }
 298 
 299 int
 300 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 301 {
 302     crm_trace("Cleanup %d", call_type);
 303     return cib_server_ops[call_type].cleanup(options, input, output);
 304 }

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