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-2018 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This source code is licensed under the GNU General Public License version 2
   5  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   6  */
   7 
   8 #include <crm_internal.h>
   9 
  10 #include <sys/param.h>
  11 #include <stdio.h>
  12 #include <sys/types.h>
  13 #include <unistd.h>
  14 
  15 #include <stdlib.h>
  16 #include <errno.h>
  17 #include <fcntl.h>
  18 
  19 #include <crm/crm.h>
  20 #include <crm/cib.h>
  21 #include <crm/msg_xml.h>
  22 #include <crm/common/ipc.h>
  23 #include <crm/cluster.h>
  24 
  25 #include <crm/common/xml.h>
  26 
  27 #include <pacemaker-based.h>
  28 
  29 gboolean stand_alone = FALSE;
  30 
  31 extern int cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff,
  32                                gboolean privileged);
  33 
  34 static xmlNode *
  35 cib_prepare_common(xmlNode * root, const char *section)
     /* [previous][next][first][last][top][bottom][index][help] */
  36 {
  37     xmlNode *data = NULL;
  38 
  39     /* extract the CIB from the fragment */
  40     if (root == NULL) {
  41         return NULL;
  42 
  43     } else if (pcmk__strcase_any_of(crm_element_name(root), XML_TAG_FRAGMENT,
  44                                     F_CRM_DATA, F_CIB_CALLDATA, NULL)) {
  45         data = first_named_child(root, XML_TAG_CIB);
  46 
  47     } else {
  48         data = root;
  49     }
  50 
  51     /* grab the section specified for the command */
  52     if (section != NULL && data != NULL && pcmk__str_eq(crm_element_name(data), XML_TAG_CIB, pcmk__str_none)) {
  53         data = get_object_root(section, data);
  54     }
  55 
  56     /* crm_log_xml_trace(root, "cib:input"); */
  57     return data;
  58 }
  59 
  60 static int
  61 cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63     *data = NULL;
  64     *section = crm_element_value(request, F_CIB_SECTION);
  65     return pcmk_ok;
  66 }
  67 
  68 static int
  69 cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71     xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
  72 
  73     *section = crm_element_value(request, F_CIB_SECTION);
  74     *data = cib_prepare_common(input_fragment, *section);
  75     /* crm_log_xml_debug(*data, "data"); */
  76     return pcmk_ok;
  77 }
  78 
  79 static int
  80 cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82     *data = NULL;
  83     *section = crm_element_value(request, F_CIB_SECTION);
  84     return pcmk_ok;
  85 }
  86 
  87 static int
  88 cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     xmlNode *input_fragment = NULL;
  91     const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
  92 
  93     *data = NULL;
  94     *section = NULL;
  95 
  96     if (crm_is_true(update)) {
  97         input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
  98 
  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 = DIMOF(cib_server_ops);
 174 
 175         operation_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, 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 #if ENABLE_ACL
 228         F_CIB_USER,
 229 #endif
 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 < DIMOF(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 < DIMOF(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] */