16#include <sys/utsname.h>
46 int *_admin_epoch,
int *_epoch,
int *_updates)
48 int add[] = { 0, 0, 0 };
49 int del[] = { 0, 0, 0 };
53 *admin_epoch = add[0];
57 *_admin_epoch = del[0];
77 xmlNode *wrapper = NULL;
83 crm_err(
"CIB diff notification received with no XML");
90 crm_warn(
"Ignore failed CIB update: %s " QB_XS
" rc=%d",
99 if (*patchset == NULL) {
100 crm_err(
"CIB diff notification received with no patchset");
119 xmlNode *cib_root = NULL, *config = NULL;
137#if PCMK__RESOURCE_STICKINESS_DEFAULT != 0
154cib_acl_enabled(xmlNode *xml,
const char *user)
159 const char *value = NULL;
165 g_hash_table_destroy(options);
168 crm_trace(
"CIB ACL is %s", rc ?
"enabled" :
"disabled");
183should_copy_cib(
const char *op,
const char *section,
int call_options)
223 xmlNode *req, xmlNode *
input,
bool manage_counters,
224 bool *config_changed, xmlNode **current_cib,
225 xmlNode **result_cib, xmlNode **diff, xmlNode **output)
228 bool check_schema =
true;
229 bool make_copy =
true;
231 xmlNode *scratch = NULL;
232 xmlNode *patchset_cib = NULL;
233 xmlNode *local_diff = NULL;
236 const bool enable_acl = cib_acl_enabled(*current_cib, user);
237 bool with_digest =
false;
241 (is_query?
"read-only " :
""), op);
243 CRM_CHECK(output != NULL,
return -ENOMSG);
244 CRM_CHECK(current_cib != NULL,
return -ENOMSG);
245 CRM_CHECK(result_cib != NULL,
return -ENOMSG);
246 CRM_CHECK(config_changed != NULL,
return -ENOMSG);
253 *config_changed =
false;
260 xmlNode *cib_ro = *current_cib;
261 xmlNode *cib_filtered = NULL;
267 if (cib_filtered == NULL) {
268 crm_debug(
"Pre-filtered the entire cib");
271 cib_ro = cib_filtered;
275 rc = (*fn) (op, call_options, section, req,
input, cib_ro, result_cib, output);
277 if(output == NULL || *output == NULL) {
280 }
else if(cib_filtered == *output) {
283 }
else if (*output == *current_cib) {
286 }
else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
290 }
else if ((*output)->doc == (*current_cib)->doc) {
299 make_copy = should_copy_cib(op, section, call_options);
304 scratch = *current_cib;
317 rc = (*fn) (op, call_options, section, req,
input, scratch, &scratch, output);
325 *current_cib = scratch;
329 patchset_cib = *current_cib;
336 rc = (*fn) (op, call_options, section, req,
input, *current_cib,
344 crm_trace(
"Inferring changes after %s op", op);
351 CRM_CHECK(*current_cib != scratch,
return -EINVAL);
356 if (rc ==
pcmk_ok && scratch == NULL) {
361 crm_trace(
"ACL rejected part or all of the proposed changes");
378 crm_err(
"Discarding update with feature set '%s' greater than "
385 if (patchset_cib != NULL) {
393 crm_err(
"%s went backwards: %d -> %d (Opts: %#x)",
399 }
else if (old ==
new) {
403 crm_err(
"%s went backwards: %d -> %d (Opts: %#x)",
416 static time_t expires = 0;
417 time_t tm_now = time(NULL);
419 if (expires < tm_now) {
420 expires = tm_now + 60;
426 config_changed, manage_counters);
437 if (make_copy && (local_diff != NULL)) {
455 crm_err(
"v%d patchset error, patch failed to apply: %s "
471 check_schema =
false;
489 if (schema == NULL) {
504 if (origin != NULL) {
510 if (client != NULL) {
524 crm_trace(
"Perform validation: %s", pcmk__btoa(check_schema));
525 if ((rc ==
pcmk_ok) && check_schema
532 *result_cib = scratch;
537 if ((rc !=
pcmk_ok) && cib_acl_enabled(patchset_cib, user)
540 if (*result_cib == NULL) {
541 crm_debug(
"Pre-filtered the entire cib result");
559 const char *section, xmlNode *
data,
int call_options,
560 const char *user_name,
const char *client_name,
563 CRM_CHECK((cib != NULL) && (op_msg != NULL),
return -EPROTO);
580 crm_trace(
"Sending call options: %.8lx, %d", (
long)call_options, call_options);
601validate_transaction_request(
const xmlNode *request)
614 crm_err(
"Operation %s is not supported in CIB transactions", op);
619 crm_err(
"Operation targeting a specific node (%s) is not supported in "
643 rc = validate_transaction_request(request);
654 const char *client_id = NULL;
657 crm_err(
"Failed to add '%s' operation to transaction for client %s: %s",
658 op, pcmk__s(client_id,
"(unidentified)"),
pcmk_rc_str(rc));
667 xmlNode *output = NULL;
671 xmlNode *wrapper = NULL;
682 crm_trace(
"No callback found for call %d", call_id);
695 crm_trace(
"Invoking callback %s for call %d",
696 pcmk__s(blob->
id,
"without ID"), call_id);
699 }
else if ((cib != NULL) && (rc !=
pcmk_ok)) {
709 crm_trace(
"OP callback activated for %d", call_id);
715 xmlNode *msg = user_data;
717 const char *
event = NULL;
720 crm_warn(
"Skipping callback - NULL message");
727 crm_warn(
"Skipping callback - NULL callback client");
730 }
else if (entry->
callback == NULL) {
731 crm_warn(
"Skipping callback - NULL callback");
735 crm_trace(
"Skipping callback - event mismatch %p/%s vs. %s", entry, entry->
event, event);
739 crm_trace(
"Invoking callback for %p/%s event...", entry, event);
747 xmlNode *config = NULL;
750 if (options == NULL || current_cib == NULL) {
756 g_hash_table_remove_all(options);
778 const char *section, xmlNode *
data,
779 xmlNode ** output_data,
int call_options,
const char *user_name)
781 int (*delegate)(
cib_t *cib,
const char *op,
const char *
host,
782 const char *section, xmlNode *
data, xmlNode **output_data,
783 int call_options,
const char *user_name) = NULL;
790 if (delegate == NULL) {
791 return -EPROTONOSUPPORT;
793 if (user_name == NULL) {
794 user_name = getenv(
"CIB_user");
796 return delegate(cib, op,
host, section,
data, output_data, call_options, user_name);
816 xmlNode *wrapper = NULL;
817 xmlNode *diff = NULL;
826 if (rc <
pcmk_ok || diff == NULL) {
830 if (level > LOG_CRIT) {
839 crm_debug(
"Update didn't apply: %s (%d) %p",
843 crm_trace(
"Masking error, we already have the supplied update");
854#define log_signon_query_err(out, fmt, args...) do { \
856 out->err(out, fmt, ##args); \
858 crm_err(fmt, ##args); \
866 cib_t *cib_conn = NULL;
879 if (cib_conn == NULL) {
909 if ((rc ==
pcmk_rc_ok) && (*cib_object == NULL)) {
920 crm_trace(
"Attempting connection to CIB manager (up to %d time%s)",
923 for (
int remaining = attempts - 1; remaining >= 0; --remaining) {
928 || ((errno != EAGAIN) && (errno != EALREADY))) {
934 crm_debug(
"Re-attempting connection to CIB manager (%d attempt%s remaining)",
950 rc = (*cib)->cmds->signoff(*cib);
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
void xml_acl_disable(xmlNode *xml)
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Copy ACL-allowed portions of specified XML.
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
int cib__get_operation(const char *op, const cib__operation_t **operation)
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
@ cib__op_attr_transaction
Supported in a transaction.
int cib_process_diff(const char *op, int options, const char *section, xmlNode *req, xmlNode *input, xmlNode *existing_cib, xmlNode **result_cib, xmlNode **answer)
cib_callback_client_t * cib__lookup_id(int call_id)
int(* cib__op_fn_t)(const char *, int, const char *, xmlNode *, xmlNode *, xmlNode *, xmlNode **, xmlNode **)
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
cib_t * cib_new(void)
Create a new CIB connection object.
void remove_cib_op_callback(int call_id, gboolean all_callbacks)
int pcmk__check_feature_set(const char *cib_version)
@ cib_transaction
Process request when the client commits the active transaction.
int cib__extend_transaction(cib_t *cib, xmlNode *request)
int cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output, int level)
Apply a CIB update patch to a given CIB.
int cib__clean_up_connection(cib_t **cib)
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
int cib__get_notify_patchset(const xmlNode *msg, const xmlNode **patchset)
int cib_perform_op(cib_t *cib, const char *op, uint32_t 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 log_signon_query_err(out, fmt, args...)
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
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)
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)
gboolean cib_diff_version_details(xmlNode *diff, int *admin_epoch, int *epoch, int *updates, int *_admin_epoch, int *_epoch, int *_updates)
gboolean cib_version_details(xmlNode *cib, int *admin_epoch, int *epoch, int *updates)
xmlNode * createEmptyCib(int cib_epoch)
Create XML for a new (empty) CIB.
gboolean cib_read_config(GHashTable *options, xmlNode *current_cib)
int cib__signon_attempts(cib_t *cib, enum cib_conn_type type, int attempts)
void cib_native_notify(gpointer data, gpointer user_data)
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
void pcmk__sleep_ms(unsigned int ms)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
#define PCMK__RESOURCE_STICKINESS_DEFAULT
enum pcmk_ipc_server type
void crm_time_free(crm_time_t *dt)
crm_time_t * crm_time_new(const char *string)
struct crm_time_s crm_time_t
#define crm_log_xml_info(xml, text)
#define crm_warn(fmt, args...)
#define crm_log_xml_debug(xml, text)
#define CRM_CHECK(expr, failure_action)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_log_xml_trace(xml, text)
#define crm_log_xml_warn(xml, text)
#define crm_trace(fmt, args...)
#define pcmk__log_xml_patchset(level, patchset)
#define pcmk__if_tracing(if_action, else_action)
#define pcmk__log_xml_changes(level, xml)
void pcmk_unpack_nvpair_blocks(const xmlNode *xml, const char *element_name, const char *first_id, const pcmk_rule_input_t *rule_input, GHashTable *values, crm_time_t *next_change)
Unpack nvpair blocks contained by an XML element into a hash table, evaluated for any rules.
#define PCMK_META_RESOURCE_STICKINESS
#define PCMK_OPT_ENABLE_ACL
#define PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS
const char * pcmk__cluster_option(GHashTable *options, const char *name)
void pcmk__validate_cluster_options(GHashTable *options)
#define pcmk_err_cib_corrupt
const char * pcmk_strerror(int rc)
#define pcmk_err_old_data
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
#define pcmk_err_schema_validation
int pcmk_rc2legacy(int rc)
#define pcmk_err_diff_resync
int pcmk_legacy2rc(int legacy_rc)
#define pcmk__assert(expr)
const char * pcmk__highest_schema_name(void)
bool pcmk__configured_schema_validates(xmlNode *xml)
void pcmk__warn_if_schema_deprecated(const char *schema)
int pcmk__cmp_schemas_by_name(const char *schema1_name, const char *schema2_name)
gboolean crm_is_true(const char *s)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
#define pcmk__plural_s(i)
uint32_t flags
Group of enum cib__op_attr flags.
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
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)
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
void(* callback)(const char *event, xmlNode *msg)
cib_api_operations_t * cmds
This structure contains everything that makes up a single output formatter.
int int(* transient)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
Wrappers for and extensions to libxml2.
bool xml_patch_versions(const xmlNode *patchset, int add[3], int del[3])
void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest)
int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version)
xmlNode * xml_create_patchset(int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
const char * pcmk__xe_add_last_written(xmlNode *xe)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
@ pcmk__xaf_none
Flag has no effect.
bool pcmk__xml_doc_all_flags_set(const xmlDoc *xml, uint32_t flags)
void pcmk__xml_commit_changes(xmlDoc *doc)
void pcmk__strip_xml_text(xmlNode *xml)
void pcmk__xml_doc_set_flags(xmlDoc *doc, uint32_t flags)
@ pcmk__xf_tracking
Tracking is enabled (set for document only)
void pcmk__xml_free(xmlNode *xml)
void pcmk__xml_mark_changes(xmlNode *old_xml, xmlNode *new_xml)
void save_xml_to_file(const xmlNode *xml, const char *desc, const char *filename)
#define PCMK_XE_CONSTRAINTS
#define PCMK_XA_VALIDATE_WITH
#define PCMK_XA_UPDATE_ORIGIN
#define PCMK_XE_CRM_CONFIG
#define PCMK_XE_RESOURCES
#define PCMK_XE_META_ATTRIBUTES
#define PCMK_XA_ADMIN_EPOCH
#define PCMK_XA_CRM_FEATURE_SET
#define PCMK_XE_CONFIGURATION
#define PCMK_XE_CLUSTER_PROPERTY_SET
#define PCMK_XA_UPDATE_USER
#define PCMK_XA_NUM_UPDATES
#define PCMK_XA_UPDATE_CLIENT
#define PCMK_XE_RSC_DEFAULTS
#define PCMK__XA_CIB_CALLOPT
#define PCMK__XA_CIB_CALLID
#define PCMK__XA_CIB_USER
#define PCMK__XE_CIB_COMMAND
#define PCMK__XA_CIB_SECTION
#define PCMK__XE_CIB_CALLDATA
#define PCMK__XA_CIB_HOST
#define PCMK__XA_CIB_CLIENTNAME
#define PCMK__XE_CIB_UPDATE_RESULT