16 #include <sys/utsname.h> 31 xmlNode *the_cib = NULL;
35 if (the_cib != NULL) {
63 int *_admin_epoch,
int *_epoch,
int *_updates)
65 int add[] = { 0, 0, 0 };
66 int del[] = { 0, 0, 0 };
70 *admin_epoch = add[0];
74 *_admin_epoch = del[0];
99 crm_err(
"CIB diff notification received with no XML");
112 if (*patchset == NULL) {
113 crm_err(
"CIB diff notification received with no patchset");
119 #define XPATH_DIFF_V1 "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED 132 element_in_patchset_v1(
const xmlNode *patchset,
const char *element)
136 xmlXPathObject *xpath_obj =
xpath_search(patchset, xpath);
140 if (xpath_obj == NULL) {
159 element_in_patchset_v2(
const xmlNode *patchset,
const char *element)
163 char *element_regex = NULL;
166 CRM_CHECK(element_xpath != NULL,
return false);
185 && pcmk__xe_is(pcmk__xml_first_child(change), element)) {
218 return element_in_patchset_v1(patchset, element);
221 return element_in_patchset_v2(patchset, element);
224 crm_warn(
"Unknown patch format: %d", format);
240 xmlNode *cib_root = NULL, *config = NULL;
258 #if PCMK__RESOURCE_STICKINESS_DEFAULT != 0 275 cib_acl_enabled(xmlNode *xml,
const char *user)
280 const char *value = NULL;
284 value =
cib_pref(options,
"enable-acl");
286 g_hash_table_destroy(options);
289 crm_trace(
"CIB ACL is %s", rc ?
"enabled" :
"disabled");
304 should_copy_cib(
const char *op,
const char *section,
int call_options)
343 const char *section, xmlNode *req, xmlNode *
input,
344 bool manage_counters,
bool *config_changed,
345 xmlNode **current_cib, xmlNode **result_cib, xmlNode **diff,
349 bool check_schema =
true;
350 bool make_copy =
true;
352 xmlNode *scratch = NULL;
353 xmlNode *patchset_cib = NULL;
354 xmlNode *local_diff = NULL;
356 const char *new_version = NULL;
358 bool with_digest =
false;
362 (is_query?
"read-only " :
""), op);
364 CRM_CHECK(output != NULL,
return -ENOMSG);
365 CRM_CHECK(current_cib != NULL,
return -ENOMSG);
366 CRM_CHECK(result_cib != NULL,
return -ENOMSG);
367 CRM_CHECK(config_changed != NULL,
return -ENOMSG);
374 *config_changed =
false;
381 xmlNode *cib_ro = *current_cib;
382 xmlNode *cib_filtered = NULL;
384 if (cib_acl_enabled(cib_ro, user)
388 if (cib_filtered == NULL) {
389 crm_debug(
"Pre-filtered the entire cib");
392 cib_ro = cib_filtered;
396 rc = (*fn) (op, call_options, section, req,
input, cib_ro, result_cib, output);
398 if(output == NULL || *output == NULL) {
401 }
else if(cib_filtered == *output) {
404 }
else if (*output == *current_cib) {
407 }
else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
411 }
else if ((*output)->doc == (*current_cib)->doc) {
420 make_copy = should_copy_cib(op, section, call_options);
425 scratch = *current_cib;
433 rc = (*fn) (op, call_options, section, req,
input, scratch, &scratch, output);
438 *current_cib = scratch;
442 patchset_cib = *current_cib;
445 rc = (*fn) (op, call_options, section, req,
input, *current_cib,
449 crm_trace(
"Inferring changes after %s op", op);
451 cib_acl_enabled(*current_cib, user));
454 CRM_CHECK(*current_cib != scratch,
return -EINVAL);
459 if (rc ==
pcmk_ok && scratch == NULL) {
464 crm_trace(
"ACL rejected part or all of the proposed changes");
476 crm_err(
"Discarding update with feature set '%s' greater than our own '%s'",
478 rc = -EPROTONOSUPPORT;
483 if (patchset_cib != NULL) {
491 crm_err(
"%s went backwards: %d -> %d (Opts: %#x)",
497 }
else if (old ==
new) {
501 crm_err(
"%s went backwards: %d -> %d (Opts: %#x)",
521 config_changed, manage_counters);
524 static time_t expires = 0;
525 time_t tm_now = time(NULL);
527 if (expires < tm_now) {
528 expires = tm_now + 60;
533 config_changed, manage_counters);
545 if (make_copy && (local_diff != NULL)) {
552 xmlNode *cib_copy =
copy_xml(patchset_cib);
563 crm_err(
"v%d patchset error, patch failed to apply: %s " 579 check_schema =
false;
599 static int minimum_schema = 0;
602 if (minimum_schema == 0) {
607 if (current_schema >= minimum_schema) {
614 if (origin != NULL) {
620 if (client != NULL) {
635 crm_trace(
"Perform validation: %s", pcmk__btoa(check_schema));
640 crm_warn(
"Updated CIB does not validate against %s schema",
641 pcmk__s(current_schema,
"unspecified"));
647 *result_cib = scratch;
652 if ((rc !=
pcmk_ok) && cib_acl_enabled(patchset_cib, user)
655 if (*result_cib == NULL) {
656 crm_debug(
"Pre-filtered the entire cib result");
674 const char *section, xmlNode *
data,
int call_options,
675 const char *user_name,
const char *client_name,
678 CRM_CHECK((cib != NULL) && (op_msg != NULL),
return -EPROTO);
681 if (*op_msg == NULL) {
699 crm_trace(
"Sending call options: %.8lx, %d", (
long)call_options, call_options);
722 validate_transaction_request(
const xmlNode *request)
735 crm_err(
"Operation %s is not supported in CIB transactions", op);
740 crm_err(
"Operation targeting a specific node (%s) is not supported in " 762 CRM_ASSERT((cib != NULL) && (request != NULL));
764 rc = validate_transaction_request(request);
775 const char *client_id = NULL;
778 crm_err(
"Failed to add '%s' operation to transaction for client %s: %s",
779 op, pcmk__s(client_id,
"(unidentified)"),
pcmk_rc_str(rc));
788 xmlNode *output = NULL;
800 crm_trace(
"No callback found for call %d", call_id);
813 crm_trace(
"Invoking callback %s for call %d",
814 pcmk__s(blob->
id,
"without ID"), call_id);
828 crm_trace(
"Invoking global callback for call %d", call_id);
831 crm_trace(
"OP callback activated for %d", call_id);
837 xmlNode *msg = user_data;
839 const char *
event = NULL;
842 crm_warn(
"Skipping callback - NULL message");
849 crm_warn(
"Skipping callback - NULL callback client");
852 }
else if (entry->
callback == NULL) {
853 crm_warn(
"Skipping callback - NULL callback");
857 crm_trace(
"Skipping callback - event mismatch %p/%s vs. %s", entry, entry->
event, event);
861 crm_trace(
"Invoking callback for %p/%s event...", entry, event);
873 "enable-acl", NULL,
"boolean", NULL,
875 N_(
"Enable Access Control Lists (ACLs) for the CIB"),
879 "cluster-ipc-limit", NULL,
"integer", NULL,
881 N_(
"Maximum IPC message backlog before disconnecting a cluster daemon"),
882 N_(
"Raise this if log has \"Evicting client\" messages for cluster daemon" 883 " PIDs (a good value is the number of resources in the cluster" 884 " multiplied by the number of nodes).")
891 const char *desc_short =
"Cluster Information Base manager options";
892 const char *desc_long =
"Cluster options used by Pacemaker's Cluster " 893 "Information Base manager";
903 verify_cib_options(GHashTable *options)
918 xmlNode *config = NULL;
921 if (options == NULL || current_cib == NULL) {
927 g_hash_table_remove_all(options);
935 verify_cib_options(options);
944 const char *section, xmlNode *
data,
945 xmlNode ** output_data,
int call_options,
const char *user_name)
947 int (*delegate) (
cib_t * cib,
const char *op,
const char *
host,
948 const char *section, xmlNode *
data,
949 xmlNode ** output_data,
int call_options,
const char *user_name) =
952 if(user_name == NULL) {
953 user_name = getenv(
"CIB_user");
956 return delegate(cib, op,
host, section,
data, output_data, call_options, user_name);
976 xmlNode *diff = NULL;
985 if (rc <
pcmk_ok || diff == NULL) {
989 if (level > LOG_CRIT) {
998 crm_debug(
"Update didn't apply: %s (%d) %p",
1002 crm_trace(
"Masking error, we already have the supplied update");
1013 #define log_signon_query_err(out, fmt, args...) do { \ 1014 if (out != NULL) { \ 1015 out->err(out, fmt, ##args); \ 1017 crm_err(fmt, ##args); \ 1025 cib_t *cib_conn = NULL;
1038 if (cib_conn == NULL) {
1056 rc = cib_conn->
cmds->
query(cib_conn, NULL, cib_object,
1069 if ((rc ==
pcmk_rc_ok) && (*cib_object == NULL)) {
1084 rc = (*cib)->cmds->signoff(*cib);
#define pcmk_err_old_data
#define CRM_CHECK(expr, failure_action)
#define XML_ATTR_UPDATE_ORIG
#define pcmk_err_schema_validation
const char * get_object_parent(const char *object_type)
#define XML_ATTR_UPDATE_CLIENT
const char * pcmk_strerror(int rc)
int cib_perform_op(const char *op, int call_options, cib__op_fn_t fn, bool is_query, const char *section, xmlNode *req, xmlNode *input, bool manage_counters, bool *config_changed, xmlNode **current_cib, xmlNode **result_cib, xmlNode **diff, xmlNode **output)
#define pcmk__if_tracing(if_action, else_action)
#define XML_ATTR_NUMUPDATES
int pcmk_rc2legacy(int rc)
cib_t * cib_new(void)
Create a new CIB connection object.
const char * pcmk__xe_add_last_written(xmlNode *xe)
struct crm_time_s crm_time_t
#define XML_CIB_TAG_CONSTRAINTS
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
#define PCMK__RESOURCE_STICKINESS_DEFAULT
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Copy ACL-allowed portions of specified XML.
xmlNode * first_named_child(const xmlNode *parent, const char *name)
void(* callback)(const char *event, xmlNode *msg)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
void copy_in_properties(xmlNode *target, const xmlNode *src)
#define XML_ATTR_UPDATE_USER
xmlNode * cib_get_generation(cib_t *cib)
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
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)
int cib__extend_transaction(cib_t *cib, xmlNode *request)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
xmlNode * get_object_root(const char *object_type, xmlNode *the_root)
#define XML_NVPAIR_ATTR_NAME
int get_schema_version(const char *name)
int cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output, int level)
Apply a CIB update patch to a given CIB.
#define XML_RSC_ATTR_STICKINESS
Supported in a transaction.
Deprecated Pacemaker configuration utilities.
void xml_accept_changes(xmlNode *xml)
#define XML_CIB_TAG_NVPAIR
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
#define XML_CIB_TAG_NODES
int cib__clean_up_connection(cib_t **cib)
bool pcmk__valid_positive_number(const char *value)
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
#define XML_ATTR_GENERATION
gboolean validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
cib_callback_client_t * cib__lookup_id(int call_id)
bool cib__element_in_patchset(const xmlNode *patchset, const char *element)
#define XML_CIB_TAG_PROPSET
bool xml_tracking_changes(xmlNode *xml)
gboolean cib_read_config(GHashTable *options, xmlNode *current_cib)
int cib__get_notify_patchset(const xmlNode *msg, const xmlNode **patchset)
xmlNode * copy_xml(xmlNode *src_node)
const char * get_object_path(const char *object_type)
#define XML_CIB_TAG_RESOURCES
#define crm_warn(fmt, args...)
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
void pcmk__strip_xml_text(xmlNode *xml)
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)
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
gchar * pcmk__format_option_metadata(const char *name, const char *desc_short, const char *desc_long, pcmk__cluster_option_t *option_list, int len)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
void(* op_callback)(const xmlNode *msg, int call_id, int rc, xmlNode *output)
#define crm_log_xml_debug(xml, text)
const char * pcmk__cluster_option(GHashTable *options, const pcmk__cluster_option_t *option_list, int len, const char *name)
#define F_CIB_UPDATE_RESULT
#define XML_TAG_META_SETS
Wrappers for and extensions to libxml2.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
#define crm_log_xml_warn(xml, text)
void pe_unpack_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table.
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
#define XML_ATTR_VALIDATION
const char * pcmk_cib_parent_name_for(const char *element_name)
Get the parent element name of a given CIB element name.
int(*) int(* transient)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
int pcmk_legacy2rc(int legacy_rc)
#define CIB_OPTIONS_FIRST
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
void free_xml(xmlNode *child)
gboolean cib_diff_version_details(xmlNode *diff, int *admin_epoch, int *epoch, int *updates, int *_admin_epoch, int *_epoch, int *_updates)
xmlNode * get_message_xml(const xmlNode *msg, const char *field)
#define XML_CIB_TAG_GENERATION_TUPPLE
const char * pcmk__cib_abs_xpath_for(const char *element)
const char * xml_latest_schema(void)
void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest)
const char * pcmk_cib_xpath_for(const char *element_name)
Get the relative XPath needed to find a specified CIB element name.
int(* cib__op_fn_t)(const char *, int, const char *, xmlNode *, xmlNode *, xmlNode *, xmlNode **, xmlNode **)
bool pcmk__valid_boolean(const char *value)
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
#define pcmk_err_diff_resync
void save_xml_to_file(const xmlNode *xml, const char *desc, const char *filename)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
int cib__create_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, int call_options, const char *user_name, const char *client_name, xmlNode **op_msg)
#define crm_err(fmt, args...)
crm_time_t * crm_time_new(const char *string)
#define XML_CIB_TAG_CRMCONFIG
#define XML_CIB_TAG_RSCCONFIG
void xml_remove_prop(xmlNode *obj, const char *name)
void xml_acl_disable(xmlNode *xml)
This structure contains everything that makes up a single output formatter.
int compare_version(const char *version1, const char *version2)
#define crm_log_xml_info(xml, text)
#define XML_ATTR_GENERATION_ADMIN
#define XML_NVPAIR_ATTR_VALUE
uint32_t flags
Group of enum cib__op_attr flags.
#define XML_ATTR_CRM_VERSION
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
#define XML_CIB_TAG_STATUS
#define pcmk__log_xml_patchset(level, patchset)
#define crm_log_xml_trace(xml, text)
void pcmk__validate_cluster_options(GHashTable *options, pcmk__cluster_option_t *option_list, int len)
gboolean crm_is_true(const char *s)
#define pcmk__log_xml_changes(level, xml)
bool xml_patch_versions(const xmlNode *patchset, int add[3], int del[3])
int cib__get_operation(const char *op, const cib__operation_t **operation)
const char * cib_pref(GHashTable *options, const char *name)
#define XML_CIB_TAG_CONFIGURATION
void fix_plus_plus_recursive(xmlNode *target)
Parse integer assignment statements on this node and all its child nodes.
void freeXpathObject(xmlXPathObjectPtr xpathObj)
int(* client_id)(const cib_t *cib, const char **async_id, const char **sync_id)
Get the given CIB connection's unique client identifier(s)
xmlNode * xml_create_patchset(int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version)
void cib_native_notify(gpointer data, gpointer user_data)
void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml)
Process request when the client commits the active transaction.
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
#define log_signon_query_err(out, fmt, args...)
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)
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
void crm_time_free(crm_time_t *dt)