root/cib/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_cleanup_sync
  11. cib_get_operation_id
  12. cib_msg_copy
  13. cib_op_func
  14. cib_op_modifies
  15. cib_op_can_run
  16. cib_op_prepare
  17. cib_op_cleanup

   1 /*
   2  * Copyright (C) 2008 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) any later version.
   8  *
   9  * This software is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 
  19 #include <crm_internal.h>
  20 
  21 #include <sys/param.h>
  22 #include <stdio.h>
  23 #include <sys/types.h>
  24 #include <unistd.h>
  25 
  26 #include <stdlib.h>
  27 #include <errno.h>
  28 #include <fcntl.h>
  29 
  30 #include <crm/crm.h>
  31 #include <crm/cib.h>
  32 #include <crm/msg_xml.h>
  33 #include <crm/common/ipc.h>
  34 #include <crm/cluster.h>
  35 
  36 #include <crm/common/xml.h>
  37 
  38 #include <cibio.h>
  39 #include <callbacks.h>
  40 #include <cibmessages.h>
  41 #include "common.h"
  42 
  43 extern gboolean cib_is_master;
  44 extern const char *cib_root;
  45 gboolean stand_alone = FALSE;
  46 extern int cib_status;
  47 extern gboolean can_write(int flags);
  48 extern int cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff,
  49                                gboolean privileged);
  50 
  51 static xmlNode *
  52 cib_prepare_common(xmlNode * root, const char *section)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54     xmlNode *data = NULL;
  55 
  56     /* extract the CIB from the fragment */
  57     if (root == NULL) {
  58         return NULL;
  59 
  60     } else if (safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT)
  61                || safe_str_eq(crm_element_name(root), F_CRM_DATA)
  62                || safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) {
  63         data = first_named_child(root, XML_TAG_CIB);
  64 
  65     } else {
  66         data = root;
  67     }
  68 
  69     /* grab the section specified for the command */
  70     if (section != NULL && data != NULL && crm_str_eq(crm_element_name(data), XML_TAG_CIB, TRUE)) {
  71         data = get_object_root(section, data);
  72     }
  73 
  74     /* crm_log_xml_trace(root, "cib:input"); */
  75     return data;
  76 }
  77 
  78 static int
  79 cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81     *data = NULL;
  82     *section = crm_element_value(request, F_CIB_SECTION);
  83     return pcmk_ok;
  84 }
  85 
  86 static int
  87 cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89     xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
  90 
  91     *section = crm_element_value(request, F_CIB_SECTION);
  92     *data = cib_prepare_common(input_fragment, *section);
  93     /* crm_log_xml_debug(*data, "data"); */
  94     return pcmk_ok;
  95 }
  96 
  97 static int
  98 cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100     *data = NULL;
 101     *section = crm_element_value(request, F_CIB_SECTION);
 102     return pcmk_ok;
 103 }
 104 
 105 static int
 106 cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108     xmlNode *input_fragment = NULL;
 109     const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
 110 
 111     *data = NULL;
 112     *section = NULL;
 113 
 114     if (crm_is_true(update)) {
 115         input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
 116 
 117     } else {
 118         input_fragment = get_message_xml(request, F_CIB_CALLDATA);
 119     }
 120 
 121     CRM_CHECK(input_fragment != NULL, crm_log_xml_warn(request, "no input"));
 122     *data = cib_prepare_common(input_fragment, NULL);
 123     return pcmk_ok;
 124 }
 125 
 126 static int
 127 cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129     CRM_LOG_ASSERT(*data == NULL);
 130     if ((options & cib_no_children)
 131         || safe_str_eq(crm_element_name(*output), "xpath-query")) {
 132         free_xml(*output);
 133     }
 134     return pcmk_ok;
 135 }
 136 
 137 static int
 138 cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140     free_xml(*output);
 141     *data = NULL;
 142     return pcmk_ok;
 143 }
 144 
 145 static int
 146 cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148     free_xml(*output);
 149     return pcmk_ok;
 150 }
 151 
 152 static int
 153 cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155     CRM_LOG_ASSERT(*data == NULL);
 156     CRM_LOG_ASSERT(*output == NULL);
 157     return pcmk_ok;
 158 }
 159 
 160 static int
 161 cib_cleanup_sync(int options, xmlNode ** data, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163     /* data is non-NULL but doesn't need to be free'd */
 164     CRM_LOG_ASSERT(*data == NULL);
 165     CRM_LOG_ASSERT(*output == NULL);
 166     return pcmk_ok;
 167 }
 168 
 169 /*
 170   typedef struct cib_operation_s
 171   {
 172   const char*   operation;
 173   gboolean      modifies_cib;
 174   gboolean      needs_privileges;
 175   gboolean      needs_quorum;
 176   int (*prepare)(xmlNode *, xmlNode**, const char **);
 177   int (*cleanup)(xmlNode**, xmlNode**);
 178   int (*fn)(
 179   const char *, int, const char *,
 180   xmlNode*, xmlNode*, xmlNode**, xmlNode**);
 181   } cib_operation_t;
 182 */
 183 /* technically bump does modify the cib...
 184  * but we want to split the "bump" from the "sync"
 185  */
 186 /* *INDENT-OFF* */
 187 static cib_operation_t cib_server_ops[] = {
 188     {NULL,             FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
 189     {CIB_OP_QUERY,     FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query,  cib_process_query},
 190     {CIB_OP_MODIFY,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_modify},
 191     {CIB_OP_APPLY_DIFF,TRUE,  TRUE,  TRUE,  cib_prepare_diff, cib_cleanup_data,   cib_server_process_diff},
 192     {CIB_OP_REPLACE,   TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_replace_svr},
 193     {CIB_OP_CREATE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_create},
 194     {CIB_OP_DELETE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete},
 195     {CIB_OP_SYNC,      FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_sync,   cib_process_sync},
 196     {CIB_OP_BUMP,      TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_bump},
 197     {CIB_OP_ERASE,     TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_erase},
 198     {CRM_OP_NOOP,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
 199     {CIB_OP_DELETE_ALT,TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete_absolute},
 200     {CIB_OP_UPGRADE,   TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server},
 201     {CIB_OP_SLAVE,     FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 202     {CIB_OP_SLAVEALL,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 203     {CIB_OP_SYNC_ONE,  FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_sync,   cib_process_sync_one},
 204     {CIB_OP_MASTER,    TRUE,  TRUE,  FALSE, cib_prepare_data, cib_cleanup_data,   cib_process_readwrite},
 205     {CIB_OP_ISMASTER,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
 206     {"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync,   cib_process_shutdown_req},
 207     {CRM_OP_PING,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping},
 208 };
 209 /* *INDENT-ON* */
 210 
 211 int
 212 cib_get_operation_id(const char *op, int *operation)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214     static GHashTable *operation_hash = NULL;
 215 
 216     if (operation_hash == NULL) {
 217         int lpc = 0;
 218         int max_msg_types = DIMOF(cib_server_ops);
 219 
 220         operation_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
 221         for (lpc = 1; lpc < max_msg_types; lpc++) {
 222             int *value = malloc(sizeof(int));
 223 
 224             if(value) {
 225                 *value = lpc;
 226                 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
 227             }
 228         }
 229     }
 230 
 231     if (op != NULL) {
 232         int *value = g_hash_table_lookup(operation_hash, op);
 233 
 234         if (value) {
 235             *operation = *value;
 236             return pcmk_ok;
 237         }
 238     }
 239     crm_err("Operation %s is not valid", op);
 240     *operation = -1;
 241     return -EINVAL;
 242 }
 243 
 244 xmlNode *
 245 cib_msg_copy(xmlNode * msg, gboolean with_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247     int lpc = 0;
 248     const char *field = NULL;
 249     const char *value = NULL;
 250     xmlNode *value_struct = NULL;
 251 
 252     static const char *field_list[] = {
 253         F_XML_TAGNAME,
 254         F_TYPE,
 255         F_CIB_CLIENTID,
 256         F_CIB_CALLOPTS,
 257         F_CIB_CALLID,
 258         F_CIB_OPERATION,
 259         F_CIB_ISREPLY,
 260         F_CIB_SECTION,
 261         F_CIB_HOST,
 262         F_CIB_RC,
 263         F_CIB_DELEGATED,
 264         F_CIB_OBJID,
 265         F_CIB_OBJTYPE,
 266         F_CIB_EXISTING,
 267         F_CIB_SEENCOUNT,
 268         F_CIB_TIMEOUT,
 269         F_CIB_CALLBACK_TOKEN,
 270         F_CIB_GLOBAL_UPDATE,
 271         F_CIB_CLIENTNAME,
 272 #if ENABLE_ACL
 273         F_CIB_USER,
 274 #endif
 275         F_CIB_NOTIFY_TYPE,
 276         F_CIB_NOTIFY_ACTIVATE
 277     };
 278 
 279     static const char *data_list[] = {
 280         F_CIB_CALLDATA,
 281         F_CIB_UPDATE,
 282         F_CIB_UPDATE_RESULT
 283     };
 284 
 285     xmlNode *copy = create_xml_node(NULL, "copy");
 286 
 287     CRM_ASSERT(copy != NULL);
 288 
 289     for (lpc = 0; lpc < DIMOF(field_list); lpc++) {
 290         field = field_list[lpc];
 291         value = crm_element_value(msg, field);
 292         if (value != NULL) {
 293             crm_xml_add(copy, field, value);
 294         }
 295     }
 296     for (lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) {
 297         field = data_list[lpc];
 298         value_struct = get_message_xml(msg, field);
 299         if (value_struct != NULL) {
 300             add_message_xml(copy, field, value_struct);
 301         }
 302     }
 303 
 304     return copy;
 305 }
 306 
 307 cib_op_t *
 308 cib_op_func(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310     return &(cib_server_ops[call_type].fn);
 311 }
 312 
 313 gboolean
 314 cib_op_modifies(int call_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 315 {
 316     return cib_server_ops[call_type].modifies_cib;
 317 }
 318 
 319 int
 320 cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322     if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) {
 323         /* abort */
 324         return -EACCES;
 325     }
 326 #if 0
 327     if (rc == pcmk_ok
 328         && stand_alone == FALSE
 329         && global_update == FALSE
 330         && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) {
 331         return -pcmk_err_no_quorum;
 332     }
 333 #endif
 334     return pcmk_ok;
 335 }
 336 
 337 int
 338 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340     crm_trace("Prepare %d", call_type);
 341     return cib_server_ops[call_type].prepare(request, input, section);
 342 }
 343 
 344 int
 345 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 346 {
 347     crm_trace("Cleanup %d", call_type);
 348     return cib_server_ops[call_type].cleanup(options, input, output);
 349 }

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