Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
01b2506
Refactor: libcib: New cib__get_calldata()
nrwahl2 Jan 3, 2026
9ffea2b
Refactor: libcib: New cib__set_calldata()
nrwahl2 Jan 3, 2026
151e494
Refactor: libcib: Call xml_apply_patchset() in cib_apply_patch_event()
nrwahl2 Jan 3, 2026
ba7d444
Refactor: libcib: Drop input arg from cib__op_fn_t
nrwahl2 Jan 3, 2026
3c9a0d0
Refactor: libcib: Drop input argument from cib_perform_op helpers
nrwahl2 Jan 3, 2026
9f0bee2
Refactor: libcib: Reduce number of arguments in cib_ops.c
nrwahl2 Jan 3, 2026
9b0d998
Log: based: Drop redundant log from cib_process_command()
nrwahl2 Jan 3, 2026
0965918
Refactor: based: Drop redundant cib_process_command() config_changed set
nrwahl2 Jan 3, 2026
6e97cbb
Refactor: based: Unindent block of cib_process_command()
nrwahl2 Jan 3, 2026
889e0aa
Refactor: based: Unindent some of process_ping_reply()
nrwahl2 Jan 3, 2026
b34f725
Refactor: based: Unindent rest of process_ping_reply()
nrwahl2 Jan 3, 2026
9a076de
Refactor: based: Convert ping_seq to long long
nrwahl2 Jan 3, 2026
3829cff
Low: based: Ignore ping reply if we're no longer DC
nrwahl2 Jan 3, 2026
c390ada
Refactor: based: Unindent outermost else block in based_process_upgrade
nrwahl2 Jan 4, 2026
6c2a196
Refactor: based: Unindent pcmk_rc_ok section of based_process_upgrade()
nrwahl2 Jan 4, 2026
804fe22
Refactor: based: Don't set answer to NULL in cib__op_fn_t functions
nrwahl2 Jan 4, 2026
887f171
Refactor: libcib: Rename cib__perform_query() to cib__perform_op_ro()
nrwahl2 Jan 4, 2026
6b02f5e
Refactor: libcib: Rename cib_perform_op() to cib__perform_op_rw()
nrwahl2 Jan 4, 2026
7548260
Refactor: based: Don't free remote_versions in process_ping_reply()
nrwahl2 Jan 4, 2026
ae92fa0
Refactor: based: Assume the_cib is not NULL
nrwahl2 Jan 4, 2026
72254f7
Doc: based, libcib: Clarify cib__op_attr_modifies
nrwahl2 Jan 4, 2026
d54935d
Refactor: based: Set ping_modified_since to true only if the CIB changed
nrwahl2 Jan 12, 2026
b187b1b
Doc: based: Add Doxygen for process_ping_reply()
nrwahl2 Jan 4, 2026
c7dc7b2
Refactor: based: sync_our_cib() takes const argument
nrwahl2 Jan 4, 2026
d5ca362
Low: based: Free ping_digest on exit
nrwahl2 Jan 4, 2026
38cfbab
Refactor: based: Minor reorganization of cib_process_command()
nrwahl2 Jan 4, 2026
13421e3
Feature: libcrmcommon: Assert on memory error in mainloop_add_fd()
nrwahl2 Jan 6, 2026
51c3876
Refactor: libcrmcommon: Unindent mainloop_add_fd()
nrwahl2 Jan 6, 2026
e2c56c9
Low: based: Free remote client if TLS session creation fails
nrwahl2 Jan 6, 2026
5ddbbc0
Refactor: based: Drop qb_ipcs_stats_get() call
nrwahl2 Jan 6, 2026
50d70f1
Doc: libcrmcommon: Add detail to mainloop_del_fd() Doxygen
nrwahl2 Jan 8, 2026
be3243b
Low: based: Drop remote clients during shutdown
nrwahl2 Jan 6, 2026
ca4e05e
Refactor: based: Use pcmk__drop_all_clients() in based_shutdown()
nrwahl2 Jan 4, 2026
b2a8d47
Refactor: based: Call based_shutdown() only once
nrwahl2 Jan 6, 2026
c31b052
Refactor: based: Inline initiate_exit()
nrwahl2 Jan 6, 2026
f470dbf
Refactor: based: create_cib_reply/based_diff_notify take standard rc
nrwahl2 Jan 4, 2026
91b0122
Refactor: based: based_diff_notify() takes request argument
nrwahl2 Jan 4, 2026
3bf9331
Refactor: based: create_cib_reply() takes request argument
nrwahl2 Jan 4, 2026
2df7d05
Doc: based: Drop irrelevant comment about legacy mode
nrwahl2 Jan 4, 2026
034dea0
Refactor: based: Unindent do_local_notify() call
nrwahl2 Jan 4, 2026
79f2232
Refactor: based: Guard create_cib_reply() call with !cib_discard_reply
nrwahl2 Jan 4, 2026
be2a801
Refactor: based: Move privilege check to based_process_request()
nrwahl2 Jan 4, 2026
f75af13
Refactor: based: Drop NULL-check of reply from cib_process_command()
nrwahl2 Jan 4, 2026
6ef967a
Refactor: based: Drop based_process_request last cib_discard_reply check
nrwahl2 Jan 4, 2026
beb78cc
Refactor: libcib: Use done label in cib__perform_op_ro()
nrwahl2 Jan 4, 2026
90b599f
Low: libcib: Avoid memory leak in processing CIB file commit transaction
nrwahl2 Jan 4, 2026
1e7de54
Refactor: libcib: Assert to satisfy Coverity
nrwahl2 May 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
451 changes: 194 additions & 257 deletions daemons/based/based_callbacks.c

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions daemons/based/based_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,15 +280,6 @@ based_ipc_destroy(qb_ipcs_connection_t *c)
{
pcmk__trace("Destroying client connection %p", c);
based_ipc_closed(c);

/* Shut down if this was the last client to leave.
*
* @TODO Is it correct to do this for destroy but not for closed? Other
* daemons handle closed and destroyed connections in the same way.
*/
if (cib_shutdown_flag) {
based_shutdown(0);
}
}

struct qb_ipcs_service_handlers ipc_ro_callbacks = {
Expand Down
196 changes: 85 additions & 111 deletions daemons/based/based_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ xmlNode *the_cib = NULL;
* \brief Process a \c PCMK__CIB_REQUEST_ABS_DELETE
*
* \param[in] req Ignored
* \param[in] input Ignored
* \param[in] cib Ignored
* \param[in] answer Ignored
*
Expand All @@ -47,8 +46,7 @@ xmlNode *the_cib = NULL;
* \note This is unimplemented and simply returns an error.
*/
int
based_process_abs_delete(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_abs_delete(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
/* @COMPAT Remove when PCMK__CIB_REQUEST_ABS_DELETE is removed. Note that
* external clients with Pacemaker versions < 3.0.0 can send it.
Expand All @@ -57,14 +55,14 @@ based_process_abs_delete(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_commit_transact(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_commit_transact(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
/* On success, our caller will activate *cib locally, trigger a replace
* notification if appropriate, and sync *cib to all nodes. On failure, our
* caller will free *cib.
*/
int rc = pcmk_rc_ok;
xmlNode *input = cib__get_calldata(req);
const char *client_id = pcmk__xe_get(req, PCMK__XA_CIB_CLIENTID);
const char *origin = pcmk__xe_get(req, PCMK__XA_SRC);
pcmk__client_t *client = pcmk__find_client_by_id(client_id);
Expand All @@ -82,25 +80,21 @@ based_process_commit_transact(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_is_primary(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_is_primary(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
// @COMPAT Pacemaker Remote clients <3.0.0 may send this
return (based_is_primary? pcmk_rc_ok : EPERM);
}

// @COMPAT: Remove when PCMK__CIB_REQUEST_NOOP is removed
int
based_process_noop(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_noop(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
*answer = NULL;
return pcmk_rc_ok;
}

int
based_process_ping(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_ping(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
/* existing_cib and *cib should be identical. In the absence of ACL
* filtering, they should also match the_cib. However, they may be copies
Expand All @@ -112,24 +106,19 @@ based_process_ping(xmlNode *req, xmlNode *input, xmlNode **cib,
const char *host = pcmk__xe_get(req, PCMK__XA_SRC);
const char *seq = pcmk__xe_get(req, PCMK__XA_CIB_PING_ID);
char *digest = pcmk__digest_xml(the_cib, true);

xmlNode *wrapper = NULL;
xmlNode *shallow = NULL;

*answer = pcmk__xe_create(NULL, PCMK__XE_PING_RESPONSE);

pcmk__xe_set(*answer, PCMK_XA_CRM_FEATURE_SET, CRM_FEATURE_SET);
pcmk__xe_set(*answer, PCMK_XA_DIGEST, digest);
pcmk__xe_set(*answer, PCMK__XA_CIB_PING_ID, seq);

wrapper = pcmk__xe_create(*answer, PCMK__XE_CIB_CALLDATA);

if (*cib != NULL) {
// Use *cib so that ACL filtering is applied to the answer
xmlNode *shallow = pcmk__xe_create(wrapper,
(const char *) (*cib)->name);

pcmk__xe_copy_attrs(shallow, *cib, pcmk__xaf_none);
}
// Use *cib so that ACL filtering is applied to the answer
shallow = pcmk__xe_create(NULL, (const char *) (*cib)->name);
pcmk__xe_copy_attrs(shallow, *cib, pcmk__xaf_none);
cib__set_calldata(*answer, shallow);
pcmk__xml_free(shallow);

pcmk__info("Reporting our current digest to %s: %s for %s.%s.%s",
host, digest,
Expand All @@ -143,8 +132,7 @@ based_process_ping(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_primary(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_primary(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
if (!based_is_primary) {
pcmk__info("We are now in R/W mode");
Expand All @@ -158,10 +146,8 @@ based_process_primary(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_schemas(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_schemas(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
xmlNode *wrapper = NULL;
xmlNode *data = NULL;

const char *after_ver = NULL;
Expand All @@ -170,8 +156,7 @@ based_process_schemas(xmlNode *req, xmlNode *input, xmlNode **cib,

*answer = pcmk__xe_create(NULL, PCMK__XA_SCHEMAS);

wrapper = pcmk__xe_first_child(req, PCMK__XE_CIB_CALLDATA, NULL, NULL);
data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
data = cib__get_calldata(req);
if (data == NULL) {
pcmk__warn("No data specified in request");
return EPROTO;
Expand Down Expand Up @@ -203,8 +188,7 @@ based_process_schemas(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_secondary(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_secondary(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
if (based_is_primary) {
pcmk__info("We are now in R/O mode");
Expand All @@ -218,13 +202,10 @@ based_process_secondary(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_shutdown(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_shutdown(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
const char *host = pcmk__xe_get(req, PCMK__XA_SRC);

*answer = NULL;

if (pcmk__xe_get(req, PCMK__XA_CIB_ISREPLYTO) == NULL) {
pcmk__info("Peer %s is requesting to shut down", host);
return pcmk_rc_ok;
Expand All @@ -241,106 +222,102 @@ based_process_shutdown(xmlNode *req, xmlNode *input, xmlNode **cib,
}

int
based_process_sync(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_sync(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
return sync_our_cib(req, true);
}

int
based_process_upgrade(xmlNode *req, xmlNode *input, xmlNode **cib,
xmlNode **answer)
based_process_upgrade(xmlNode *req, xmlNode **cib, xmlNode **answer)
{
int rc = pcmk_rc_ok;

*answer = NULL;
xmlNode *scratch = NULL;
const char *host = pcmk__xe_get(req, PCMK__XA_SRC);
const char *client_id = pcmk__xe_get(req, PCMK__XA_CIB_CLIENTID);
const char *call_opts = pcmk__xe_get(req, PCMK__XA_CIB_CALLOPT);
const char *call_id = pcmk__xe_get(req, PCMK__XA_CIB_CALLID);
const char *original_schema = NULL;
const char *new_schema = NULL;
pcmk__node_status_t *origin = NULL;

if (pcmk__xe_get(req, PCMK__XA_CIB_SCHEMA_MAX) != NULL) {
/* The originator of an upgrade request sends it to the DC, without
* PCMK__XA_CIB_SCHEMA_MAX. If an upgrade is needed, the DC
* re-broadcasts the request with PCMK__XA_CIB_SCHEMA_MAX, and each node
* performs the upgrade (and notifies its local clients) here.
*/
return cib__process_upgrade(req, input, cib, answer);
return cib__process_upgrade(req, cib, answer);
}

} else {
xmlNode *scratch = pcmk__xml_copy(NULL, *cib);
const char *host = pcmk__xe_get(req, PCMK__XA_SRC);
const char *original_schema = NULL;
const char *new_schema = NULL;
const char *client_id = pcmk__xe_get(req, PCMK__XA_CIB_CLIENTID);
const char *call_opts = pcmk__xe_get(req, PCMK__XA_CIB_CALLOPT);
const char *call_id = pcmk__xe_get(req, PCMK__XA_CIB_CALLID);

original_schema = pcmk__xe_get(*cib, PCMK_XA_VALIDATE_WITH);
if (original_schema == NULL) {
pcmk__info("Rejecting upgrade request from %s: No "
PCMK_XA_VALIDATE_WITH,
host);
return pcmk_rc_cib_corrupt;
}
scratch = pcmk__xml_copy(NULL, *cib);

rc = pcmk__update_schema(&scratch, NULL, true, true);
new_schema = pcmk__xe_get(scratch, PCMK_XA_VALIDATE_WITH);
original_schema = pcmk__xe_get(*cib, PCMK_XA_VALIDATE_WITH);
if (original_schema == NULL) {
pcmk__info("Rejecting upgrade request from %s: No "
PCMK_XA_VALIDATE_WITH, host);
return pcmk_rc_cib_corrupt;
}

if (pcmk__cmp_schemas_by_name(new_schema, original_schema) > 0) {
xmlNode *up = pcmk__xe_create(NULL, __func__);
rc = pcmk__update_schema(&scratch, NULL, true, true);
new_schema = pcmk__xe_get(scratch, PCMK_XA_VALIDATE_WITH);

rc = pcmk_rc_ok;
pcmk__notice("Upgrade request from %s verified", host);
if (pcmk__cmp_schemas_by_name(new_schema, original_schema) > 0) {
xmlNode *up = pcmk__xe_create(NULL, __func__);

pcmk__xe_set(up, PCMK__XA_T, PCMK__VALUE_CIB);
pcmk__xe_set(up, PCMK__XA_CIB_OP, PCMK__CIB_REQUEST_UPGRADE);
pcmk__xe_set(up, PCMK__XA_CIB_SCHEMA_MAX, new_schema);
pcmk__xe_set(up, PCMK__XA_CIB_DELEGATED_FROM, host);
pcmk__xe_set(up, PCMK__XA_CIB_CLIENTID, client_id);
pcmk__xe_set(up, PCMK__XA_CIB_CALLOPT, call_opts);
pcmk__xe_set(up, PCMK__XA_CIB_CALLID, call_id);
rc = pcmk_rc_ok;
pcmk__notice("Upgrade request from %s verified", host);

pcmk__cluster_send_message(NULL, pcmk_ipc_based, up);
pcmk__xe_set(up, PCMK__XA_T, PCMK__VALUE_CIB);
pcmk__xe_set(up, PCMK__XA_CIB_OP, PCMK__CIB_REQUEST_UPGRADE);
pcmk__xe_set(up, PCMK__XA_CIB_SCHEMA_MAX, new_schema);
pcmk__xe_set(up, PCMK__XA_CIB_DELEGATED_FROM, host);
pcmk__xe_set(up, PCMK__XA_CIB_CLIENTID, client_id);
pcmk__xe_set(up, PCMK__XA_CIB_CALLOPT, call_opts);
pcmk__xe_set(up, PCMK__XA_CIB_CALLID, call_id);

pcmk__xml_free(up);
pcmk__cluster_send_message(NULL, pcmk_ipc_based, up);

} else if (rc == pcmk_rc_ok) {
rc = pcmk_rc_schema_unchanged;
}
pcmk__xml_free(up);
goto done;
}

if (rc == pcmk_rc_ok) {
rc = pcmk_rc_schema_unchanged;
}

if (rc != pcmk_rc_ok) {
// Notify originating peer so it can notify its local clients
pcmk__node_status_t *origin = NULL;

origin = pcmk__search_node_caches(0, host, NULL,
pcmk__node_search_cluster_member);

pcmk__info("Rejecting upgrade request from %s: %s "
QB_XS " rc=%d peer=%s", host, pcmk_rc_str(rc), rc,
((origin != NULL)? origin->name : "lost"));

if (origin) {
xmlNode *up = pcmk__xe_create(NULL, __func__);

pcmk__xe_set(up, PCMK__XA_T, PCMK__VALUE_CIB);
pcmk__xe_set(up, PCMK__XA_CIB_OP, PCMK__CIB_REQUEST_UPGRADE);
pcmk__xe_set(up, PCMK__XA_CIB_DELEGATED_FROM, host);
pcmk__xe_set(up, PCMK__XA_CIB_ISREPLYTO, host);
pcmk__xe_set(up, PCMK__XA_CIB_CLIENTID, client_id);
pcmk__xe_set(up, PCMK__XA_CIB_CALLOPT, call_opts);
pcmk__xe_set(up, PCMK__XA_CIB_CALLID, call_id);
pcmk__xe_set_int(up, PCMK__XA_CIB_UPGRADE_RC,
pcmk_rc2legacy(rc));
if (!pcmk__cluster_send_message(origin, pcmk_ipc_based, up)) {
pcmk__warn("Could not send CIB upgrade result to %s", host);
}
pcmk__xml_free(up);
}
// Notify originating peer so it can notify its local clients
origin = pcmk__search_node_caches(0, host, NULL,
pcmk__node_search_cluster_member);

pcmk__info("Rejecting upgrade request from %s: %s " QB_XS " rc=%d peer=%s",
host, pcmk_rc_str(rc), rc,
((origin != NULL)? origin->name : "lost"));

if (origin != NULL) {
xmlNode *up = pcmk__xe_create(NULL, __func__);

pcmk__xe_set(up, PCMK__XA_T, PCMK__VALUE_CIB);
pcmk__xe_set(up, PCMK__XA_CIB_OP, PCMK__CIB_REQUEST_UPGRADE);
pcmk__xe_set(up, PCMK__XA_CIB_DELEGATED_FROM, host);
pcmk__xe_set(up, PCMK__XA_CIB_ISREPLYTO, host);
pcmk__xe_set(up, PCMK__XA_CIB_CLIENTID, client_id);
pcmk__xe_set(up, PCMK__XA_CIB_CALLOPT, call_opts);
pcmk__xe_set(up, PCMK__XA_CIB_CALLID, call_id);
pcmk__xe_set_int(up, PCMK__XA_CIB_UPGRADE_RC, pcmk_rc2legacy(rc));
if (!pcmk__cluster_send_message(origin, pcmk_ipc_based, up)) {
pcmk__warn("Could not send CIB upgrade result to %s", host);
}
pcmk__xml_free(scratch);
pcmk__xml_free(up);
}

done:
pcmk__xml_free(scratch);
return rc;
}

static xmlNode *
cib_msg_copy(xmlNode *msg)
cib_msg_copy(const xmlNode *msg)
{
static const char *field_list[] = {
PCMK__XA_T,
Expand Down Expand Up @@ -373,17 +350,15 @@ cib_msg_copy(xmlNode *msg)
}

int
sync_our_cib(xmlNode *request, bool all)
sync_our_cib(const xmlNode *request, bool all)
{
int rc = pcmk_rc_ok;
char *digest = NULL;
const char *host = pcmk__xe_get(request, PCMK__XA_SRC);
const char *op = pcmk__xe_get(request, PCMK__XA_CIB_OP);
pcmk__node_status_t *peer = NULL;
xmlNode *replace_request = NULL;
xmlNode *wrapper = NULL;

CRM_CHECK(the_cib != NULL, return EINVAL);
CRM_CHECK(all || (host != NULL), return EINVAL);

pcmk__debug("Syncing CIB to %s", (all? "all peers" : host));
Expand All @@ -408,8 +383,7 @@ sync_our_cib(xmlNode *request, bool all)
digest = pcmk__digest_xml(the_cib, true);
pcmk__xe_set(replace_request, PCMK_XA_DIGEST, digest);

wrapper = pcmk__xe_create(replace_request, PCMK__XE_CIB_CALLDATA);
pcmk__xml_copy(wrapper, the_cib);
cib__set_calldata(replace_request, the_cib);

if (!all) {
peer = pcmk__get_node(0, host, NULL, pcmk__node_search_cluster_member);
Expand Down
Loading