Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F5197310
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/crm/cib/cib_file.c b/lib/crm/cib/cib_file.c
index 025ed9898b..dd4d65ebb4 100644
--- a/lib/crm/cib/cib_file.c
+++ b/lib/crm/cib/cib_file.c
@@ -1,312 +1,315 @@
/*
* Copyright (c) 2004 International Business Machines
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <crm_internal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <glib.h>
#include <heartbeat.h>
#include <clplumbing/ipc.h>
#include <ha_msg.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <cib_private.h>
#include <clplumbing/Gmain_timeout.h>
typedef struct cib_file_opaque_s
{
int flags;
char *filename;
} cib_file_opaque_t;
int cib_file_perform_op(
cib_t *cib, const char *op, const char *host, const char *section,
xmlNode *data, xmlNode **output_data, int call_options);
int cib_file_signon(cib_t* cib, const char *name, enum cib_conn_type type);
int cib_file_signoff(cib_t* cib);
int cib_file_free(cib_t* cib);
static int cib_file_inputfd(cib_t* cib) { return cib_NOTSUPPORTED; }
static int cib_file_set_connection_dnotify(
cib_t *cib, void (*dnotify)(gpointer user_data))
{
return cib_NOTSUPPORTED;
}
static int cib_file_register_callback(cib_t* cib, const char *callback, int enabled)
{
return cib_NOTSUPPORTED;
}
cib_t*
cib_file_new (const char *cib_location)
{
cib_file_opaque_t *private = NULL;
cib_t *cib = cib_new_variant();
crm_malloc0(private, sizeof(cib_file_opaque_t));
cib->variant = cib_file;
cib->variant_opaque = private;
if(cib_location == NULL) {
cib_location = getenv("CIB_file");
}
private->filename = crm_strdup(cib_location);
/* assign variant specific ops*/
cib->cmds->variant_op = cib_file_perform_op;
cib->cmds->signon = cib_file_signon;
cib->cmds->signoff = cib_file_signoff;
cib->cmds->free = cib_file_free;
cib->cmds->inputfd = cib_file_inputfd;
cib->cmds->register_callback = cib_file_register_callback;
cib->cmds->set_connection_dnotify = cib_file_set_connection_dnotify;
return cib;
}
static xmlNode *in_mem_cib = NULL;
static int load_file_cib(const char *filename)
{
int rc = cib_ok;
struct stat buf;
xmlNode *root = NULL;
FILE *cib_file = NULL;
gboolean dtd_ok = TRUE;
const char *ignore_dtd = NULL;
xmlNode *status = NULL;
rc = stat(filename, &buf);
if (rc == 0) {
cib_file = fopen(filename, "r");
if(cib_file == NULL) {
cl_perror("Could not open config file %s for reading", filename);
return cib_not_authorized;
}
root = file2xml(cib_file, FALSE);
fclose(cib_file);
if(root == NULL) {
return cib_dtd_validation;
}
} else {
return cib_NOTEXISTS;
}
rc = 0;
status = find_xml_node(root, XML_CIB_TAG_STATUS, FALSE);
if(status == NULL) {
create_xml_node(root, XML_CIB_TAG_STATUS);
}
ignore_dtd = crm_element_value(root, "ignore_dtd");
dtd_ok = validate_xml(root, NULL, TRUE);
if(dtd_ok == FALSE) {
crm_err("CIB does not validate against "DTD_DIRECTORY"/crm.dtd");
if(ignore_dtd != NULL && crm_is_true(ignore_dtd) == FALSE) {
rc = cib_dtd_validation;
goto bail;
}
}
if(do_id_check(root, NULL, TRUE, FALSE)) {
crm_err("%s does not contain a vaild configuration:"
" ID check failed",
filename);
rc = cib_id_check;
goto bail;
}
in_mem_cib = root;
return rc;
bail:
free_xml(root);
root = NULL;
return rc;
}
int
cib_file_signon(cib_t* cib, const char *name, enum cib_conn_type type)
{
int rc = cib_ok;
cib_file_opaque_t *private = cib->variant_opaque;
if(private->filename == FALSE) {
rc = cib_missing;
} else {
rc = load_file_cib(private->filename);
}
if(rc == cib_ok) {
fprintf(stderr, "%s: Opened connection to local file '%s'\n", name, private->filename);
cib->state = cib_connected_command;
cib->type = cib_command;
} else {
fprintf(stderr, "%s: Connection to local file '%s' failed: %s\n",
name, private->filename, cib_error2string(rc));
}
return rc;
}
int
cib_file_signoff(cib_t* cib)
{
int rc = cib_ok;
cib_file_opaque_t *private = cib->variant_opaque;
crm_debug("Signing out of the CIB Service");
rc = write_xml_file(in_mem_cib, private->filename, FALSE);
if(rc > 0) {
crm_info("Wrote CIB to %s", private->filename);
} else {
crm_err("Could not write CIB to %s", private->filename);
}
crm_free(in_mem_cib);
cib->state = cib_disconnected;
cib->type = cib_none;
return rc;
}
int
cib_file_free (cib_t* cib)
{
int rc = cib_ok;
crm_warn("Freeing CIB");
if(cib->state != cib_disconnected) {
rc = cib_file_signoff(cib);
if(rc == cib_ok) {
cib_file_opaque_t *private = cib->variant_opaque;
crm_free(private->filename);
crm_free(cib->cmds);
crm_free(private);
crm_free(cib);
}
}
return rc;
}
struct cib_func_entry
{
const char *op;
gboolean read_only;
cib_op_t fn;
};
static struct cib_func_entry cib_file_ops[] = {
{CIB_OP_QUERY, TRUE, cib_process_query},
{CIB_OP_MODIFY, FALSE, cib_process_modify},
/* {CIB_OP_UPDATE, FALSE, cib_process_change}, */
{CIB_OP_APPLY_DIFF, FALSE, cib_process_diff},
{CIB_OP_BUMP, FALSE, cib_process_bump},
{CIB_OP_REPLACE, FALSE, cib_process_replace},
/* {CIB_OP_CREATE, FALSE, cib_process_change}, */
{CIB_OP_DELETE, FALSE, cib_process_delete},
{CIB_OP_ERASE, FALSE, cib_process_erase},
};
int
cib_file_perform_op(
cib_t *cib, const char *op, const char *host, const char *section,
xmlNode *data, xmlNode **output_data, int call_options)
{
int rc = cib_ok;
gboolean query = FALSE;
gboolean changed = FALSE;
xmlNode *output = NULL;
xmlNode *result_cib = NULL;
cib_op_t *fn = NULL;
int lpc = 0;
static int max_msg_types = DIMOF(cib_file_ops);
crm_info("%s on %s", op, section);
if(cib->state == cib_disconnected) {
return cib_not_connected;
}
if(output_data != NULL) {
*output_data = NULL;
}
if(op == NULL) {
crm_err("No operation specified");
return cib_operation;
}
for (lpc = 0; lpc < max_msg_types; lpc++) {
if (safe_str_eq(op, cib_file_ops[lpc].op)) {
fn = &(cib_file_ops[lpc].fn);
query = cib_file_ops[lpc].read_only;
break;
}
}
if(fn == NULL) {
return cib_NOTSUPPORTED;
}
cib->call_id++;
rc = cib_perform_op(op, call_options, fn, query,
section, NULL, data, TRUE, &changed, in_mem_cib, &result_cib, &output);
if(rc != cib_ok) {
crm_err("Call failed: %s", cib_error2string(rc));
crm_log_xml(LOG_WARNING, "failed", output);
free_xml(result_cib);
} else if(query == FALSE) {
free_xml(in_mem_cib);
in_mem_cib = result_cib;
}
- if(output_data && output) {
- *output_data = copy_xml(output);
- }
-
if(cib->op_callback != NULL) {
cib->op_callback(NULL, cib->call_id, rc, output);
}
+ if(output_data && output) {
+ *output_data = output;
+
+ } else {
+ free_xml(output);
+ }
+
return rc;
}
diff --git a/lib/crm/cib/cib_utils.c b/lib/crm/cib/cib_utils.c
index 564208abc5..1582ab3c51 100644
--- a/lib/crm/cib/cib_utils.c
+++ b/lib/crm/cib/cib_utils.c
@@ -1,875 +1,864 @@
/*
* Copyright (c) 2004 International Business Machines
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <crm_internal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <glib.h>
#include <heartbeat.h>
#include <clplumbing/ipc.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <lib/crm/cib/cib_private.h>
char *
cib_pluralSection(const char *a_section)
{
char *a_section_parent = NULL;
if (a_section == NULL) {
a_section_parent = crm_strdup("all");
} else if(strcasecmp(a_section, XML_TAG_CIB) == 0) {
a_section_parent = crm_strdup("all");
} else if(strcasecmp(a_section, XML_CIB_TAG_NODE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_NODES);
} else if(strcasecmp(a_section, XML_CIB_TAG_STATE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_STATUS);
} else if(strcasecmp(a_section, XML_CIB_TAG_CONSTRAINT) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, XML_CONS_TAG_RSC_LOCATION) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, XML_CONS_TAG_RSC_DEPEND) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, XML_CONS_TAG_RSC_ORDER) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcasecmp(a_section, "resource") == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_RESOURCE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_GROUP) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_INCARNATION) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else if(strcasecmp(a_section, XML_CIB_TAG_NVPAIR) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CRMCONFIG);
} else if(strcasecmp(a_section, XML_TAG_ATTR_SETS) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CRMCONFIG);
} else {
crm_err("Unknown section %s", a_section);
a_section_parent = crm_strdup("all");
}
crm_debug_2("Plural of %s is %s", crm_str(a_section), a_section_parent);
return a_section_parent;
}
const char *
cib_error2string(enum cib_errors return_code)
{
const char *error_msg = NULL;
switch(return_code) {
case cib_bad_permissions:
error_msg = "bad permissions for the on-disk configuration. shutdown heartbeat and repair.";
break;
case cib_bad_digest:
error_msg = "the on-disk configuration was manually altered. shutdown heartbeat and repair.";
break;
case cib_bad_config:
error_msg = "the on-disk configuration is not valid";
break;
case cib_msg_field_add:
error_msg = "failed adding field to cib message";
break;
case cib_id_check:
error_msg = "missing id or id-collision detected";
break;
case cib_operation:
error_msg = "invalid operation";
break;
case cib_create_msg:
error_msg = "couldnt create cib message";
break;
case cib_client_gone:
error_msg = "client left before we could send reply";
break;
case cib_not_connected:
error_msg = "not connected";
break;
case cib_not_authorized:
error_msg = "not authorized";
break;
case cib_send_failed:
error_msg = "send failed";
break;
case cib_reply_failed:
error_msg = "reply failed";
break;
case cib_return_code:
error_msg = "no return code";
break;
case cib_output_ptr:
error_msg = "nowhere to store output";
break;
case cib_output_data:
error_msg = "corrupt output data";
break;
case cib_connection:
error_msg = "connection failed";
break;
case cib_callback_register:
error_msg = "couldnt register callback channel";
break;
case cib_authentication:
error_msg = "";
break;
case cib_registration_msg:
error_msg = "invalid registration msg";
break;
case cib_callback_token:
error_msg = "callback token not found";
break;
case cib_missing:
error_msg = "cib object missing";
break;
case cib_variant:
error_msg = "unknown/corrupt cib variant";
break;
case CIBRES_MISSING_ID:
error_msg = "The id field is missing";
break;
case CIBRES_MISSING_TYPE:
error_msg = "The type field is missing";
break;
case CIBRES_MISSING_FIELD:
error_msg = "A required field is missing";
break;
case CIBRES_OBJTYPE_MISMATCH:
error_msg = "CIBRES_OBJTYPE_MISMATCH";
break;
case cib_EXISTS:
error_msg = "The object already exists";
break;
case cib_NOTEXISTS:
error_msg = "The object/attribute does not exist";
break;
case CIBRES_CORRUPT:
error_msg = "The CIB is corrupt";
break;
case cib_NOOBJECT:
error_msg = "The update was empty";
break;
case cib_NOPARENT:
error_msg = "The parent object does not exist";
break;
case cib_NODECOPY:
error_msg = "Failed while copying update";
break;
case CIBRES_OTHER:
error_msg = "CIBRES_OTHER";
break;
case cib_ok:
error_msg = "ok";
break;
case cib_unknown:
error_msg = "Unknown error";
break;
case cib_STALE:
error_msg = "Discarded old update";
break;
case cib_ACTIVATION:
error_msg = "Activation Failed";
break;
case cib_NOSECTION:
error_msg = "Required section was missing";
break;
case cib_NOTSUPPORTED:
error_msg = "The action/feature is not supported";
break;
case cib_not_master:
error_msg = "Local service is not the master instance";
break;
case cib_client_corrupt:
error_msg = "Service client not valid";
break;
case cib_remote_timeout:
error_msg = "Remote node did not respond";
break;
case cib_master_timeout:
error_msg = "No master service is currently active";
break;
case cib_revision_unsupported:
error_msg = "The required CIB revision number is not supported";
break;
case cib_revision_unknown:
error_msg = "The CIB revision number could not be determined";
break;
case cib_missing_data:
error_msg = "Required data for this CIB API call not found";
break;
case cib_no_quorum:
error_msg = "Write requires quorum";
break;
case cib_diff_failed:
error_msg = "Application of an update diff failed";
break;
case cib_diff_resync:
error_msg = "Application of an update diff failed, requesting a full refresh";
break;
case cib_bad_section:
error_msg = "Invalid CIB section specified";
break;
case cib_old_data:
error_msg = "Update was older than existing configuration";
break;
case cib_dtd_validation:
error_msg = "Update does not conform to the DTD in "DTD_DIRECTORY"/crm.dtd";
break;
case cib_invalid_argument:
error_msg = "Invalid argument";
break;
}
if(error_msg == NULL) {
crm_err("Unknown CIB Error Code: %d", return_code);
error_msg = "<unknown error>";
}
return error_msg;
}
int
cib_section2enum(const char *a_section)
{
if(a_section == NULL || strcasecmp(a_section, "all") == 0) {
return cib_section_all;
} else if(strcasecmp(a_section, XML_CIB_TAG_NODES) == 0) {
return cib_section_nodes;
} else if(strcasecmp(a_section, XML_CIB_TAG_STATUS) == 0) {
return cib_section_status;
} else if(strcasecmp(a_section, XML_CIB_TAG_CONSTRAINTS) == 0) {
return cib_section_constraints;
} else if(strcasecmp(a_section, XML_CIB_TAG_RESOURCES) == 0) {
return cib_section_resources;
} else if(strcasecmp(a_section, XML_CIB_TAG_CRMCONFIG) == 0) {
return cib_section_crmconfig;
}
crm_err("Unknown CIB section: %s", a_section);
return cib_section_none;
}
int
cib_compare_generation(xmlNode *left, xmlNode *right)
{
int lpc = 0;
const char *attributes[] = {
XML_ATTR_GENERATION_ADMIN,
XML_ATTR_GENERATION,
XML_ATTR_NUMUPDATES,
XML_ATTR_NUMPEERS
};
crm_log_xml_debug_3(left, "left");
crm_log_xml_debug_3(right, "right");
for(lpc = 0; lpc < DIMOF(attributes); lpc++) {
int int_elem_l = -1;
int int_elem_r = -1;
const char *elem_r = NULL;
const char *elem_l = crm_element_value(left, attributes[lpc]);
if(right != NULL) {
elem_r = crm_element_value(right, attributes[lpc]);
}
if(elem_l != NULL) { int_elem_l = crm_parse_int(elem_l, NULL); }
if(elem_r != NULL) { int_elem_r = crm_parse_int(elem_r, NULL); }
if(int_elem_l < int_elem_r) {
crm_debug_2("%s (%s < %s)", attributes[lpc],
crm_str(elem_l), crm_str(elem_r));
return -1;
} else if(int_elem_l > int_elem_r) {
crm_debug_2("%s (%s > %s)", attributes[lpc],
crm_str(elem_l), crm_str(elem_r));
return 1;
}
}
return 0;
}
xmlNode*
get_cib_copy(cib_t *cib)
{
xmlNode *xml_cib;
-#if CRM_DEPRECATED_SINCE_2_0_4
- xmlNode *xml_cib_copy;
-#endif
int options = cib_scope_local|cib_sync_call;
if(cib->cmds->query(cib, NULL, &xml_cib, options) != cib_ok) {
crm_err("Couldnt retrieve the CIB");
return NULL;
} else if(xml_cib == NULL) {
crm_err("The CIB result was empty");
return NULL;
}
if(safe_str_eq(crm_element_name(xml_cib), XML_TAG_CIB)) {
return xml_cib;
-
-#if CRM_DEPRECATED_SINCE_2_0_4
- } else {
- xml_cib_copy = copy_xml(
- find_xml_node(xml_cib, XML_TAG_CIB, TRUE));
- free_xml(xml_cib);
- return xml_cib_copy;
-#endif
}
free_xml(xml_cib);
return NULL;
}
xmlNode*
cib_get_generation(cib_t *cib)
{
xmlNode *the_cib = get_cib_copy(cib);
xmlNode *generation = create_xml_node(
NULL, XML_CIB_TAG_GENERATION_TUPPLE);
if(the_cib != NULL) {
copy_in_properties(generation, the_cib);
free_xml(the_cib);
}
return generation;
}
void
log_cib_diff(int log_level, xmlNode *diff, const char *function)
{
int add_updates = 0;
int add_epoch = 0;
int add_admin_epoch = 0;
int del_updates = 0;
int del_epoch = 0;
int del_admin_epoch = 0;
if(diff == NULL) {
return;
}
cib_diff_version_details(
diff, &add_admin_epoch, &add_epoch, &add_updates,
&del_admin_epoch, &del_epoch, &del_updates);
if(add_updates != del_updates) {
do_crm_log(log_level, "%s: Diff: --- %d.%d.%d", function,
del_admin_epoch, del_epoch, del_updates);
do_crm_log(log_level, "%s: Diff: +++ %d.%d.%d", function,
add_admin_epoch, add_epoch, add_updates);
} else if(diff != NULL) {
do_crm_log(log_level,
"%s: Local-only Change: %d.%d.%d", function,
add_admin_epoch, add_epoch, add_updates);
}
log_xml_diff(log_level, diff, function);
}
gboolean
cib_version_details(
xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
{
const char *value = NULL;
if(cib == NULL) {
*admin_epoch = -1;
*epoch = -1;
*updates = -1;
return FALSE;
} else {
value = crm_element_value(cib, XML_ATTR_GENERATION_ADMIN);
*admin_epoch = crm_parse_int(value, "-1");
value = crm_element_value(cib, XML_ATTR_GENERATION);
*epoch = crm_parse_int(value, "-1");
value = crm_element_value(cib, XML_ATTR_NUMUPDATES);
*updates = crm_parse_int(value, "-1");
}
return TRUE;
}
gboolean
cib_diff_version_details(
xmlNode *diff, int *admin_epoch, int *epoch, int *updates,
int *_admin_epoch, int *_epoch, int *_updates)
{
xmlNode *tmp = NULL;
tmp = find_xml_node(diff, "diff-added", FALSE);
cib_version_details(tmp, admin_epoch, epoch, updates);
tmp = find_xml_node(diff, "diff-removed", FALSE);
cib_version_details(tmp, _admin_epoch, _epoch, _updates);
return TRUE;
}
/*
* The caller should never free the return value
*/
xmlNode*
get_object_root(const char *object_type, xmlNode *the_root)
{
const char *node_stack[2];
xmlNode *tmp_node = NULL;
if(the_root == NULL) {
crm_err("CIB root object was NULL");
return NULL;
}
node_stack[0] = XML_CIB_TAG_CONFIGURATION;
node_stack[1] = object_type;
if(object_type == NULL
|| strlen(object_type) == 0
|| safe_str_eq(XML_CIB_TAG_SECTION_ALL, object_type)
|| safe_str_eq(XML_TAG_CIB, object_type)) {
/* get the whole cib */
return the_root;
} else if(strcasecmp(object_type, XML_CIB_TAG_STATUS) == 0) {
/* these live in a different place */
tmp_node = find_xml_node(the_root, XML_CIB_TAG_STATUS, FALSE);
node_stack[0] = object_type;
node_stack[1] = NULL;
} else {
/* tmp_node = first_named_child(the_root, XML_CIB_TAG_CONFIGURATION); */
tmp_node = find_xml_node_nested(the_root, node_stack, 2);
}
if (tmp_node == NULL) {
crm_debug_2("Section [%s [%s]] not present in %s",
node_stack[0],
node_stack[1]?node_stack[1]:"",
crm_element_name(the_root));
}
return tmp_node;
}
const char *
get_crm_option(xmlNode *cib, const char *name, gboolean do_warn)
{
const char * value = NULL;
xmlNode * a_default = NULL;
xmlNode * config = get_object_root(XML_CIB_TAG_CRMCONFIG, cib);
if(config != NULL) {
a_default = find_entity(config, XML_CIB_TAG_NVPAIR, name);
}
if(a_default == NULL) {
if(do_warn) {
crm_warn("Option %s not set", name);
}
return NULL;
}
value = crm_element_value(a_default, XML_NVPAIR_ATTR_VALUE);
if(safe_str_eq(value, "")) {
value = NULL;
}
return value;
}
xmlNode*
create_cib_fragment_adv(
xmlNode *update, const char *update_section, const char *source)
{
xmlNode *cib = NULL;
gboolean whole_cib = FALSE;
xmlNode *object_root = NULL;
const char *update_name = NULL;
char *local_section = NULL;
/* crm_debug("Creating a blank fragment: %s", update_section); */
if(update == NULL && update_section == NULL) {
crm_debug_3("Creating a blank fragment");
update = createEmptyCib();
crm_xml_add(cib, XML_ATTR_ORIGIN, source);
return update;
} else if(update == NULL) {
crm_err("No update to create a fragment for");
return NULL;
} else if(update_section == NULL) {
local_section = cib_pluralSection(update_name);
update_section = local_section;
}
if(safe_str_eq(crm_element_name(update), XML_TAG_CIB)) {
whole_cib = TRUE;
}
if(whole_cib == FALSE) {
cib = createEmptyCib();
crm_xml_add(cib, XML_ATTR_ORIGIN, source);
object_root = get_object_root(update_section, cib);
add_node_copy(object_root, update);
} else {
cib = copy_xml(update);
crm_xml_add(cib, XML_ATTR_ORIGIN, source);
}
crm_free(local_section);
crm_debug_3("Verifying created fragment");
return cib;
}
/*
* It is the callers responsibility to free both the new CIB (output)
* and the new CIB (input)
*/
xmlNode*
createEmptyCib(void)
{
xmlNode *cib_root = NULL, *config = NULL, *status = NULL;
cib_root = create_xml_node(NULL, XML_TAG_CIB);
config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
status = create_xml_node(cib_root, XML_CIB_TAG_STATUS);
/* crm_xml_add(cib_root, "version", "1"); */
crm_xml_add(cib_root, "generated", XML_BOOLEAN_TRUE);
crm_xml_add(cib_root, XML_ATTR_GENERATION, "0");
crm_xml_add(cib_root, XML_ATTR_GENERATION_ADMIN, "0");
crm_xml_add(cib_root, XML_ATTR_NUMUPDATES, "0");
create_xml_node(config, XML_CIB_TAG_CRMCONFIG);
create_xml_node(config, XML_CIB_TAG_NODES);
create_xml_node(config, XML_CIB_TAG_RESOURCES);
create_xml_node(config, XML_CIB_TAG_CONSTRAINTS);
return cib_root;
}
enum cib_errors
cib_perform_op(const char *op, int call_options, cib_op_t *fn, gboolean is_query,
const char *section, xmlNode *req, xmlNode *input,
gboolean manage_counters, gboolean *config_changed,
xmlNode *current_cib, xmlNode **result_cib, xmlNode **output)
{
int rc = cib_ok;
xmlNode *scratch = NULL;
CRM_CHECK(output != NULL && result_cib != NULL && config_changed != NULL,
return cib_output_data);
*output = NULL;
*result_cib = NULL;
*config_changed = FALSE;
if(fn == NULL) {
return cib_operation;
}
if(rc != cib_ok) {
return rc;
}
if(is_query) {
rc = (*fn)(op, call_options, section, req, input, current_cib, result_cib, output);
return rc;
}
scratch = copy_xml(current_cib);
rc = (*fn)(op, call_options, section, req, input, current_cib, &scratch, output);
/*
crm_log_xml_debug(current_cib, "old");
crm_log_xml_debug(scratch, "new");
crm_log_xml_debug(*output, "output");
*/
CRM_CHECK(current_cib != scratch, return cib_unknown);
if(rc == cib_ok) {
CRM_CHECK(scratch != NULL, return cib_unknown);
if(do_id_check(scratch, NULL, TRUE, FALSE)) {
rc = cib_id_check;
if(call_options & cib_force_diff) {
crm_err("Global update introduces id collision!");
}
}
if(rc == cib_ok) {
gboolean dtd_ok;
const char *ignore_dtd;
fix_plus_plus_recursive(scratch);
/* crm_log_xml_debug(scratch, "newer"); */
*config_changed = cib_config_changed(current_cib, scratch, NULL);
/* crm_log_xml_debug(scratch, "newest"); */
if(manage_counters && *config_changed) {
cib_update_counter(scratch, XML_ATTR_NUMUPDATES, TRUE);
cib_update_counter(scratch, XML_ATTR_GENERATION, FALSE);
} else if(manage_counters) {
cib_update_counter(scratch, XML_ATTR_NUMUPDATES, FALSE);
}
ignore_dtd = crm_element_value(scratch, "ignore_dtd");
dtd_ok = validate_xml(scratch, NULL, TRUE);
if(
#if CRM_DEPRECATED_SINCE_2_0_4
ignore_dtd != NULL &&
#endif
crm_is_true(ignore_dtd) == FALSE && dtd_ok == FALSE) {
crm_err("Updated CIB does not validate against "DTD_DIRECTORY"/crm.dtd...");
rc = cib_dtd_validation;
}
}
}
*result_cib = scratch;
return rc;
}
int get_channel_token(IPC_Channel *ch, char **token)
{
int rc = cib_ok;
xmlNode *reg_msg = NULL;
const char *msg_type = NULL;
const char *tmp_ticket = NULL;
CRM_CHECK(ch != NULL, return cib_missing);
CRM_CHECK(token != NULL, return cib_output_ptr);
crm_debug_4("Waiting for msg on command channel");
reg_msg = xmlfromIPC(ch, 0);
if(ch->ops->get_chan_status(ch) != IPC_CONNECT) {
crm_err("No reply message - disconnected");
free_xml(reg_msg);
return cib_not_connected;
} else if(reg_msg == NULL) {
crm_err("No reply message - empty");
return cib_reply_failed;
}
msg_type = crm_element_value(reg_msg, F_CIB_OPERATION);
tmp_ticket = crm_element_value(reg_msg, F_CIB_CLIENTID);
if(safe_str_neq(msg_type, CRM_OP_REGISTER) ) {
crm_err("Invalid registration message: %s", msg_type);
rc = cib_registration_msg;
} else if(tmp_ticket == NULL) {
rc = cib_callback_token;
} else {
*token = crm_strdup(tmp_ticket);
}
free_xml(reg_msg);
return cib_ok;
}
xmlNode *
cib_create_op(
int call_id, const char *token, const char *op, const char *host, const char *section,
xmlNode *data, int call_options)
{
int rc = HA_OK;
xmlNode *op_msg = create_xml_node(NULL, "cib_command");
CRM_CHECK(op_msg != NULL, return NULL);
CRM_CHECK(token != NULL, return NULL);
crm_xml_add(op_msg, F_XML_TAGNAME, "cib_command");
crm_xml_add(op_msg, F_TYPE, T_CIB);
crm_xml_add(op_msg, F_CIB_CALLBACK_TOKEN, token);
crm_xml_add(op_msg, F_CIB_OPERATION, op);
crm_xml_add(op_msg, F_CIB_HOST, host);
crm_xml_add(op_msg, F_CIB_SECTION, section);
crm_xml_add_int(op_msg, F_CIB_CALLID, call_id);
crm_debug_4("Sending call options: %.8lx, %d",
(long)call_options, call_options);
crm_xml_add_int(op_msg, F_CIB_CALLOPTS, call_options);
if(data != NULL) {
#if 0
const char *tag = crm_element_name(data);
xmlNode *cib = data;
if(safe_str_neq(tag, XML_TAG_CIB)) {
cib = find_xml_node(data, XML_TAG_CIB, FALSE);
if(cib != NULL) {
tag = XML_TAG_CIB;
}
}
if(safe_str_eq(tag, XML_TAG_CIB)) {
const char *version = feature_set(cib);
crm_xml_add(cib, XML_ATTR_CIB_REVISION, version);
} else {
crm_info("Skipping feature check for %s tag", tag);
}
#endif
add_message_xml(op_msg, F_CIB_CALLDATA, data);
}
if (rc != HA_OK) {
crm_err("Failed to create CIB operation message");
crm_log_xml(LOG_ERR, "op", op_msg);
free_xml(op_msg);
return NULL;
}
if(call_options & cib_inhibit_bcast) {
CRM_CHECK((call_options & cib_scope_local), return NULL);
}
return op_msg;
}
void
cib_native_callback(cib_t *cib, xmlNode *msg)
{
int rc = 0;
int call_id = 0;
xmlNode *output = NULL;
cib_callback_client_t *blob = NULL;
cib_callback_client_t local_blob;
local_blob.callback = NULL;
local_blob.user_data = NULL;
local_blob.only_success = FALSE;
crm_element_value_int(msg, F_CIB_CALLID, &call_id);
blob = g_hash_table_lookup(
cib_op_callback_table, GINT_TO_POINTER(call_id));
if(blob != NULL) {
crm_debug_3("Callback found for call %d", call_id);
local_blob = *blob;
blob = NULL;
remove_cib_op_callback(call_id, FALSE);
} else {
crm_debug_3("No callback found for call %d", call_id);
local_blob.callback = NULL;
}
crm_element_value_int(msg, F_CIB_RC, &rc);
if(rc == cib_diff_resync) {
/* This is an internal value that clients do not and should not care about */
rc = cib_ok;
}
output = get_message_xml(msg, F_CIB_CALLDATA);
if(local_blob.callback != NULL
&& (rc == cib_ok || local_blob.only_success == FALSE)) {
local_blob.callback(
msg, call_id, rc, output, local_blob.user_data);
} else if(cib->op_callback == NULL && rc != cib_ok) {
crm_warn("CIB command failed: %s", cib_error2string(rc));
crm_log_xml(LOG_DEBUG, "Failed CIB Update", msg);
}
if(cib->op_callback == NULL) {
crm_debug_3("No OP callback set, ignoring reply");
} else {
cib->op_callback(msg, call_id, rc, output);
}
crm_debug_4("OP callback activated.");
}
void
cib_native_notify(gpointer data, gpointer user_data)
{
xmlNode *msg = user_data;
cib_notify_client_t *entry = data;
const char *event = NULL;
if(msg == NULL) {
crm_warn("Skipping callback - NULL message");
return;
}
event = crm_element_value(msg, F_SUBTYPE);
if(entry == NULL) {
crm_warn("Skipping callback - NULL callback client");
return;
} else if(entry->callback == NULL) {
crm_warn("Skipping callback - NULL callback");
return;
} else if(safe_str_neq(entry->event, event)) {
crm_debug_4("Skipping callback - event mismatch %p/%s vs. %s",
entry, entry->event, event);
return;
}
crm_debug_4("Invoking callback for %p/%s event...", entry, event);
entry->callback(event, msg);
crm_debug_4("Callback invoked...");
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Aug 14, 12:14 PM (11 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2207566
Default Alt Text
(31 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment