25 #include <sys/utsname.h> 
   35 struct config_root_s {
 
   48     { NULL,         NULL,                 
"//cib" },
 
   70     const char *attributes[] = {
 
   79     for (lpc = 0; lpc < 
DIMOF(attributes); lpc++) {
 
   82         const char *elem_r = NULL;
 
   96         if (int_elem_l < int_elem_r) {
 
  100         } 
else if (int_elem_l > int_elem_r) {
 
  121     rc = cib->
cmds->
query(cib, NULL, &xml_cib, options);
 
  126         crm_err(
"Couldn't retrieve the CIB");
 
  130     } 
else if (xml_cib == NULL) {
 
  131         crm_err(
"The CIB result was empty");
 
  146     xmlNode *the_cib = NULL;
 
  150     if (the_cib != NULL) {
 
  178                          int *_admin_epoch, 
int *_epoch, 
int *_updates)
 
  180     int add[] = { 0, 0, 0 };
 
  181     int del[] = { 0, 0, 0 };
 
  185     *admin_epoch = add[0];
 
  189     *_admin_epoch = del[0];
 
  204     int max = 
DIMOF(known_paths);
 
  206     for (; lpc < max; lpc++) {
 
  207         if ((object_type == NULL && known_paths[lpc].name == NULL)
 
  208             || 
safe_str_eq(object_type, known_paths[lpc].name)) {
 
  209             return known_paths[lpc].path;
 
  219     int max = 
DIMOF(known_paths);
 
  221     for (; lpc < max; lpc++) {
 
  222         if (
safe_str_eq(object_type, known_paths[lpc].name)) {
 
  223             return known_paths[lpc].parent;
 
  248     xmlNode *cib_root = NULL, *config = NULL;
 
  270 cib_acl_enabled(xmlNode *xml, 
const char *user)
 
  276         const char *value = NULL;
 
  277         GHashTable *options = crm_str_table_new();
 
  280         value = 
cib_pref(options, 
"enable-acl");
 
  282         g_hash_table_destroy(options);
 
  285     crm_trace(
"CIB ACL is %s", rc ? 
"enabled" : 
"disabled");
 
  292                const char *section, xmlNode * req, xmlNode * input,
 
  293                gboolean manage_counters, gboolean * config_changed,
 
  294                xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff, xmlNode ** output)
 
  297     gboolean check_dtd = TRUE;
 
  299     xmlNode *scratch = NULL;
 
  300     xmlNode *local_diff = NULL;
 
  302     const char *new_version = NULL;
 
  303     static struct qb_log_callsite *diff_cs = NULL;
 
  305     bool with_digest = FALSE;
 
  307     crm_trace(
"Begin %s%s%s op", is_set(call_options, 
cib_dryrun)?
"dry-run of ":
"", is_query ? 
"read-only " : 
"", op);
 
  309     CRM_CHECK(output != NULL, 
return -ENOMSG);
 
  310     CRM_CHECK(result_cib != NULL, 
return -ENOMSG);
 
  311     CRM_CHECK(config_changed != NULL, 
return -ENOMSG);
 
  318     *config_changed = FALSE;
 
  325         xmlNode *cib_ro = current_cib;
 
  326         xmlNode *cib_filtered = NULL;
 
  328         if(cib_acl_enabled(cib_ro, user)) {
 
  330                 if (cib_filtered == NULL) {
 
  331                     crm_debug(
"Pre-filtered the entire cib");
 
  334                 cib_ro = cib_filtered;
 
  339         rc = (*fn) (op, call_options, section, req, input, cib_ro, result_cib, output);
 
  341         if(output == NULL || *output == NULL) {
 
  344         } 
else if(cib_filtered == *output) {
 
  347         } 
else if(*output == current_cib) {
 
  350         } 
else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
 
  354         } 
else if((*output)->doc == current_cib->doc) {
 
  367         scratch = current_cib;
 
  375         rc = (*fn) (op, call_options, section, req, input, scratch, &scratch, output);
 
  380         rc = (*fn) (op, call_options, section, req, input, current_cib, &scratch, output);
 
  383             crm_trace(
"Inferring changes after %s op", op);
 
  384             xml_track_changes(scratch, user, current_cib, cib_acl_enabled(current_cib, user));
 
  387         CRM_CHECK(current_cib != scratch, 
return -EINVAL);
 
  392     if (rc == 
pcmk_ok && scratch == NULL) {
 
  397         crm_trace(
"ACL rejected part or all of the proposed changes");
 
  409             crm_err(
"Discarding update with feature set '%s' greater than our own '%s'",
 
  411             rc = -EPROTONOSUPPORT;
 
  424             crm_err(
"%s went backwards: %d -> %d (Opts: 0x%x)",
 
  430         } 
else if (old == 
new) {
 
  434                 crm_err(
"%s went backwards: %d -> %d (Opts: 0x%x)",
 
  453         local_diff = 
xml_create_patchset(2, current_cib, scratch, (
bool*)config_changed, manage_counters);
 
  456         static time_t expires = 0;
 
  457         time_t tm_now = time(NULL);
 
  459         if (expires < tm_now) {
 
  460             expires = tm_now + 60;  
 
  464         local_diff = 
xml_create_patchset(0, current_cib, scratch, (
bool*)config_changed, manage_counters);
 
  470     if (diff_cs == NULL) {
 
  471         diff_cs = qb_log_callsite_get(__PRETTY_FUNCTION__, __FILE__, 
"diff-validation", LOG_DEBUG, __LINE__, 
crm_trace_nonlog);
 
  486         int test_rc, format = 1;
 
  487         xmlNode * c = 
copy_xml(current_cib);
 
  497             crm_err(
"v%d patchset error, patch failed to apply: %s (%d)", format, 
pcmk_strerror(test_rc), test_rc);
 
  522     if (*config_changed && is_not_set(call_options, 
cib_no_mtime)) {
 
  523         char *now_str = NULL;
 
  524         time_t now = time(NULL);
 
  527         now_str = ctime(&now);
 
  532             static int minimum_schema = 0;
 
  535             if (minimum_schema == 0) {
 
  540             if (current_schema >= minimum_schema) {
 
  554     crm_trace(
"Perform validation: %s", check_dtd ? 
"true" : 
"false");
 
  558         crm_warn(
"Updated CIB does not validate against %s schema/dtd", 
crm_str(current_dtd));
 
  564     *result_cib = scratch;
 
  566     if(rc != 
pcmk_ok && cib_acl_enabled(current_cib, user)) {
 
  568             if (*result_cib == NULL) {
 
  569                 crm_debug(
"Pre-filtered the entire cib result");
 
  588 cib_create_op(
int call_id, 
const char *token, 
const char *op, 
const char *
host, 
const char *section,
 
  589               xmlNode * 
data, 
int call_options, 
const char *user_name)
 
  609     crm_trace(
"Sending call options: %.8lx, %d", (
long)call_options, call_options);
 
  625     xmlNode *output = NULL;
 
  636         crm_trace(
"No callback found for call %d", call_id);
 
  663         crm_trace(
"Invoking global callback for call %d", call_id);
 
  666     crm_trace(
"OP callback activated for %d", call_id);
 
  672     xmlNode *msg = user_data;
 
  674     const char *
event = NULL;
 
  677         crm_warn(
"Skipping callback - NULL message");
 
  684         crm_warn(
"Skipping callback - NULL callback client");
 
  687     } 
else if (entry->
callback == NULL) {
 
  688         crm_warn(
"Skipping callback - NULL callback");
 
  692         crm_trace(
"Skipping callback - event mismatch %p/%s vs. %s", entry, entry->
event, event);
 
  696     crm_trace(
"Invoking callback for %p/%s event...", entry, event);
 
  715         "cluster-ipc-limit", NULL,
 
  717         "Maximum IPC message backlog before disconnecting a cluster daemon",
 
  718         "Raise this if log has \"Evicting client\" messages for cluster daemon" 
  719             " PIDs (a good value is the number of resources in the cluster" 
  720             " multiplied by the number of nodes)" 
  728                     "Cluster Information Base Options",
 
  729                     "This is a fake resource that details the options that can be configured for the Cluster Information Base.",
 
  730                     cib_opts, 
DIMOF(cib_opts));
 
  748     xmlNode *config = NULL;
 
  751     if (options == NULL || current_cib == NULL) {
 
  757     g_hash_table_remove_all(options);
 
  777     xmlNode *diff = NULL;
 
  786     if (rc < 
pcmk_ok || diff == NULL) {
 
  790     if (level > LOG_CRIT) {
 
  801                 crm_trace(
"Masking error, we already have the supplied update");
 
  814 #define XPATH_CONFIG_CHANGE \ 
  815     "//" XML_CIB_TAG_CRMCONFIG " | " \ 
  816     "//" XML_DIFF_CHANGE "[contains(@" XML_DIFF_PATH ",'/" XML_CIB_TAG_CRMCONFIG "/')]" 
  821     gboolean changed = FALSE;
 
  826         if (numXpathResults(xpathObj) > 0) {
 
  836                 const char *section, xmlNode * 
data,
 
  837                 xmlNode ** output_data, 
int call_options, 
const char *user_name)
 
  839     int (*delegate) (
cib_t * cib, 
const char *op, 
const char *
host,
 
  840                      const char *section, xmlNode * 
data,
 
  841                      xmlNode ** output_data, 
int call_options, 
const char *user_name) =
 
  845     if(user_name == NULL) {
 
  846         user_name = getenv(
"CIB_user");
 
  850     return delegate(cib, op, host, section, data, output_data, call_options, user_name);
 
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
 
#define CRM_CHECK(expr, failure_action)
 
#define XML_ATTR_UPDATE_ORIG
 
xmlNode * get_message_xml(xmlNode *msg, const char *field)
 
#define XML_ATTR_UPDATE_CLIENT
 
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
 
#define XML_CIB_TAG_SECTION_ALL
 
gboolean safe_str_neq(const char *a, const char *b)
 
#define XML_CIB_TAG_DOMAINS
 
#define XML_ATTR_NUMUPDATES
 
void xml_calculate_changes(xmlNode *old, xmlNode *new)
 
#define XPATH_CONFIG_CHANGE
 
struct crm_time_s crm_time_t
 
const char * pcmk_strerror(int rc)
 
#define XML_CIB_TAG_CONSTRAINTS
 
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
 
#define pcmk_err_old_data
 
int(* cib_op_t)(const char *, int, const char *, xmlNode *, xmlNode *, xmlNode *, xmlNode **, xmlNode **)
 
#define XML_ATTR_UPDATE_USER
 
const char * get_object_path(const char *object_type)
 
#define XML_TAG_FENCING_TOPOLOGY
 
void xml_track_changes(xmlNode *xml, const char *user, xmlNode *acl_source, bool enforce_acls)
 
void remove_cib_op_callback(int call_id, gboolean all_callbacks)
 
bool xml_acl_denied(xmlNode *xml)
 
#define F_CIB_CALLBACK_TOKEN
 
int crm_parse_int(const char *text, const char *default_text)
 
int get_schema_version(const char *name)
 
#define CRM_LOG_ASSERT(expr)
 
void copy_in_properties(xmlNode *target, xmlNode *src)
 
void xml_accept_changes(xmlNode *xml)
 
unsigned int crm_trace_nonlog
 
const char * get_object_parent(const char *object_type)
 
#define XML_CIB_TAG_NODES
 
void(* callback)(const char *event, xmlNode *msg)
 
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
 
#define XML_ATTR_GENERATION
 
gboolean validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
 
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
 
#define XML_CIB_TAG_PROPSET
 
bool xml_tracking_changes(xmlNode *xml)
 
xmlNode * cib_create_op(int call_id, const char *token, const char *op, const char *host, const char *section, xmlNode *data, int call_options, const char *user_name)
 
void cib_native_notify(gpointer data, gpointer user_data)
 
xmlNode * copy_xml(xmlNode *src_node)
 
#define XML_CIB_TAG_RESOURCES
 
xmlNode * cib_get_generation(cib_t *cib)
 
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
 
void config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, pe_cluster_option *option_list, int len)
 
#define pcmk_err_diff_resync
 
#define crm_warn(fmt, args...)
 
bool pcmk_acl_required(const char *user)
 
cib_api_operations_t * cmds
 
#define crm_debug(fmt, args...)
 
int cib_process_diff(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
 
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
 
gboolean cib_internal_config_changed(xmlNode *diff)
 
void(* op_callback)(const xmlNode *msg, int call_id, int rc, xmlNode *output)
 
#define pcmk_err_schema_validation
 
#define crm_trace(fmt, args...)
 
xmlNode * createEmptyCib(int admin_epoch)
 
#define crm_log_xml_debug(xml, text)
 
#define F_CIB_UPDATE_RESULT
 
Wrappers for and extensions to libxml2. 
 
xmlNode * create_xml_node(xmlNode *parent, const char *name)
 
#define crm_log_xml_warn(xml, text)
 
int crm_element_value_int(xmlNode *data, const char *name, int *dest)
 
const char * crm_element_value(xmlNode *data, const char *name)
 
gboolean check_positive_number(const char *value)
 
#define XML_ATTR_VALIDATION
 
void xml_acl_disable(xmlNode *xml)
 
#define CIB_OPTIONS_FIRST
 
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
 
gboolean check_boolean(const char *value)
 
void free_xml(xmlNode *child)
 
#define XML_CIB_TAG_GENERATION_TUPPLE
 
const char * xml_latest_schema(void)
 
void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest)
 
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
 
bool xml_patch_versions(xmlNode *patchset, int add[3], int del[3])
 
GHashTable * cib_op_callback_table
 
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
 
void xml_log_changes(uint8_t level, const char *function, xmlNode *xml)
 
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
 
gboolean cib_read_config(GHashTable *options, xmlNode *current_cib)
 
int cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output, int level)
 
int cib_compare_generation(xmlNode *left, xmlNode *right)
 
#define crm_err(fmt, args...)
 
gboolean cib_diff_version_details(xmlNode *diff, int *admin_epoch, int *epoch, int *updates, int *_admin_epoch, int *_epoch, int *_updates)
 
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
 
#define XML_CIB_ATTR_WRITTEN
 
crm_time_t * crm_time_new(const char *string)
 
#define XML_CIB_TAG_CRMCONFIG
 
#define XML_CIB_TAG_RSCCONFIG
 
void verify_cib_options(GHashTable *options)
 
pe_cluster_option cib_opts[]
 
int compare_version(const char *version1, const char *version2)
 
int 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 **diff, xmlNode **output)
 
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
 
#define XML_ATTR_GENERATION_ADMIN
 
#define XML_ATTR_CRM_VERSION
 
void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len)
 
const char * cib_pref(GHashTable *options, const char *name)
 
void save_xml_to_file(xmlNode *xml, const char *desc, const char *filename)
 
xmlNode * get_cib_copy(cib_t *cib)
 
void strip_text_nodes(xmlNode *xml)
 
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
 
#define XML_CIB_TAG_STATUS
 
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now)
 
#define crm_log_xml_trace(xml, text)
 
gboolean crm_is_true(const char *s)
 
#define XML_CIB_TAG_CONFIGURATION
 
int cib_internal_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, xmlNode **output_data, int call_options, const char *user_name)
 
void xml_log_patchset(uint8_t level, const char *function, xmlNode *xml)
 
#define safe_str_eq(a, b)
 
struct config_root_s known_paths[]
 
const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name)
 
void fix_plus_plus_recursive(xmlNode *target)
 
void freeXpathObject(xmlXPathObjectPtr xpathObj)
 
#define XML_CIB_TAG_OPCONFIG
 
xmlNode * xml_create_patchset(int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version)
 
void crm_time_free(crm_time_t *dt)