based refactors: Use pcmk__request_t in the CIB manager - #4154
Conversation
Our .c files include crm_internal.h, which includes crm/cluster/internal.h. The explicit include makes sense for header files, since we don't include crm_internal.h there, but not for .c files. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Include cluster/internal.h instead. Note that cluster/internal.h is included by crm_internal.h. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Our .c files include crm_internal.h, which includes crm/common/internal.h. The explicit include makes sense for header files, since we don't include crm_internal.h there, but not for .c files. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And rename based_terminate() to based_quit_main_loop(). The main loop processes events in batches. On each iteration, it checks to see what sources are ready (that is, pending dispatch), and then it dispatches them. It iterates over the list of ready sources and runs each source's callback function, provided the source has not been removed/destroyed. When we call g_main_loop_quit(), we call it from within a source's callback. g_main_loop_quit() ensures that no additional loop iterations will occur. However, any sources that are already in the pending list will still be dispatched. This means that if we quit the main loop, we need to be prepared for any pending source callbacks. This commit handles that by returning early from functions that shouldn't do anything during shutdown, if we're in the process of shutting down (that is, if we've called g_main_loop_quit()). This lets us quit based the same way regardless of the exit code and consolidate cleanup at the end of main(). It also hopefully makes behavior more reliable when we quit the main loop. Previously, if we were quitting with CRM_EX_OK (due to a SIGTERM), we would free based_cib, cib_root, and possibly other important data structures that we generally assume are non-NULL. If some function tried to dereference those when processing pending sources, we might seg fault. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
34b8ecb to
4569cc4
Compare
|
Election storm in cts-lab. |
4569cc4 to
f195534
Compare
Somehow this is being caused by the |
It's the This was copied from |
The comment above the assignment says "Don't re-enter this block." However, that's already impossible thanks to the in_progress static variable. If it's true, we exit at the beginning of the function. If it's false, we set it to true after checking it. That in_progress logic was not present as of commit 0f9b4c1, when the "Don't re-enter" comment was added. Interestingly though, the in_progress logic was added one hour after the "Don't re-enter" and NULL assignment, but the latter were never removed. See commit 716d9d7. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
mainloop_add_signal() adds mainloop_signal_handler() as a "wrapper" handler for the given signal. If the signal is received, mainloop_signal_handler() sets a boolean trigger value to true and returns. This is a lightweight operation. The "wrapped" signal handler gets called in a later main loop iteration. However, this can't happen after we've called attrd_shutdown(). Either we exit immediately or we quit the main loop. In either case, there will be no additional main loop iterations. Note that the controller is a bit different. There, we "drain" the main loop, which may run more loop iterations. So it makes some sense to destroy signal handlers before doing so. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
There are two call sites. * attrd_cpg_destroy: This is called only via the main loop. See pcmk_cluster_set_destroy_fn() and pcmk__cpg_connect(). * attrd_shutdown: We can reach this only through the main loop. It's set up as a main loop signal handler via mainloop_add_signal(). The true signal handler is mainloop_signal_handler(), which sets a main loop trigger to call attrd_shutdown(). That trigger can't do anything unless the main loop is running. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And assume the cache is already initialized when we call based_peer_callback(). pcmk__corosync_connect() initializes the node caches by calling pcmk__get_node(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
This doesn't meaningfully change behavior except in the following ways. If you call the signon() method for a cib_native cib_t object, and you pass cib_query for the type: * The resulting cib_t:state value on success is cib_connected_command. Previously it was cib_connected_query. * The resulting connection can be used for read/write requests. Previously it could only be used for read-only requests. The cib_query (read-only) vs. cib_command (read/write) API was added when the CIB API was first created, in commit 58fdec7 (2004). No rationale was given. All cib_file and cib_remote clients use cib_command unconditionally. Their signon() methods ignore the type argument. Requests that the CIB manager receives via the cluster layer (Corosync) are also given read/write privileges. Read-only connections have been restricted to cib_native clients that sign on with type=cib_query. The asymmetry of cib_native clients vs. cib_remote clients doesn't seem to make sense, and cib_query doesn't seem especially useful. One can make an argument that it promotes safety/least-privilege by allowing a client to ensure that it doesn't modify the CIB. However, this can be achieved with some basic discipline, and it already wasn't available for cib_remote connections. Supporting read-only connections complicates our CIB manager implementation substantially. We will now treat connections created with cib_query the same as those created with cib_command, and this will simplify things by a lot. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
As of the previous commit, no remote client can connect to the PCMK__SERVER_BASED_RO channel. (cib_native clients now use PCMK__SERVER_BASED_RW unconditionally.) So replace the two separate cib_proxy_accept_*() functions with a single based_proxy_accept(). Keep the two ipcs objects (based_ipcs_ro and based_ipcs_rw) for now, since pcmk__serve_based_ipc() needs both. Their callbacks are the same, however. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
If there was a PCMK__SERVER_BASED_RO instance, there also should have been a PCMK__SERVER_BASED_RW instance. We're moving toward using PCMK__SERVER_BASED_RW everywhere, so use it here. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
This affects only proxied connections from older Pacemaker Remote nodes. IPC clients on cluster nodes and on same-version Pacemaker Remote nodes use PCMK__SERVER_BASED_RW unconditionally (as of a recent commit that updated cib_native_signon()). This shouldn't cause any breakages or noticeable changes for existing clients. The capabilities of PCMK__SERVER_BASED_RW were already a proper superset of the capabilities of PCMK__SERVER_BASED_RO. That is, a client connected to the PCMK__SERVER_BASED_RW channel could do anything that a client connected to the PCMK__SERVER_BASED_RO channel can do, but not vice-versa. So nothing that previously worked should break. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
We always pass true. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Instead, always use crm_system_name if set, or fall back to "client" otherwise. All internal callers pass crm_system_name. Further, crm_system_name should always be non-NULL if crm_log_preinit() has been called -- which is always true for internal callers. Up to now, callers have been allowed to pass an arbitrary client name. However, this does not seem to be useful for anything except logging, and certain names may cause Pacemaker daemons to treat requests from the client specially. It seems safer to use crm_system_name unconditionally (falling back to "client" if NULL). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Nothing checks it internally, and there's no apparent use case for anything external to check it. Further, cib_native clients already don't set it at all during signon. cib_file and cib_remote clients set it during signon; all clients set it back to cib_no_connection at signoff. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
cib_file and cib_remote clients already ignored the type argument. cib_native clients simply returned an ENOTCONN error if the type was invalid; otherwise, they ignored it. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
cib_command is the only type we ever use, so this enum is now meaningless. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Just for future-proofing and consistency. This doesn't fix a bug. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
f195534 to
3d74074
Compare
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
We don't use these attrs when processing CRM_OP_REGISTER and PCMK__VALUE_CIB_NOTIFY. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And set client->name only when dispatching a register request. In practice, this means that a client must call the signon() method before any other methods. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Make it look more like fenced_ipc_dispatch() and attrd_ipc_dispatch(). Not everything is in accordance with my preferences here, but the goal is to make it look as similar as possible to the other daemons. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
3d74074 to
fc7061d
Compare
|
retest this please |
|
Running cts-lab again now. No election storm. We'll see what happens... |
|
@clumens A cts-lab run of 50 iterations passed with no BadNews. The CI failures are unrelated -- 404 errors for repos. |
Should have been done as part of a6bf06d. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
retest this please |
|
retest this please |
| goto done; | ||
| } | ||
|
|
||
| pcmk__cluster_init_node_caches(); |
There was a problem hiding this comment.
If I'm following this correctly, node caches are created by based_cluster_connect -> pcmk_cluster_connect -> pcmk__corosync_connect -> pcmk__get_node. This chain won't happen in standalone mode. Does standalone mode require node caches for any reason?
| // @COMPAT cib_command_nonblocking is deprecated since 3.0.2 | ||
| case cib_query: | ||
| /* @COMPAT cib_command_nonblocking and cib_query are deprecated | ||
| * since 3.0.2 |
There was a problem hiding this comment.
cib_query will actually be deprecated as of whatever release comes after 3.0.3.
| r"getinfo response error: 1$", | ||
| r"sbd.* error: inquisitor_child: DEBUG MODE IS ACTIVE", | ||
| r"sbd.* pcmk:\s*error:.*Connection to cib_ro.* (failed|closed)", | ||
| r"sbd.* pcmk:\s*error:.*Connection to cib_rw.* (failed|closed)", |
There was a problem hiding this comment.
I think this commit pairs pretty well with https://projects.clusterlabs.org/T339. We can achieve the same thing, more comprehensively, by applying access controls at a different level. We'd just have to find time for it.
| } | ||
|
|
||
| /* @COMPAT Proxied clients from Pacemaker Remote nodes older than version | ||
| * 3.0.2 can connect using PCMK__SERVER_BASED_RO. Since we use |
There was a problem hiding this comment.
This should be whatever version comes after 3.0.3.
| * \brief Sign on a client to the CIB API | ||
| * | ||
| * \param[in,out] cib CIB connection (client) | ||
| * \param[in] name Ignored |
There was a problem hiding this comment.
I haven't traced it out, but will this patch have any consequences for 40cae9e ?
| } | ||
| if ((target_stat->st_mode & (S_IRUSR | S_IWUSR)) == 0) { | ||
|
|
||
| if (!pcmk__any_flags_set(target_stat->st_mode, S_IRUSR|S_IWUSR)) { |
There was a problem hiding this comment.
This should be pcmk__all_flags_set, shouldn't it?
There was a problem hiding this comment.
I don't see why it should. The old code says "if none of the flags in S_IRUSR | S_IWUSR is set in target_stat->st_mode, then ...". That's the same as "if it's false that any of the flags in S_IRUSR|S_IWUSR is set in target_stat->st_mode, then ...".
Am I overlooking or misreading anything?
| } | ||
|
|
||
| if ((target_stat->st_mode & (S_IRGRP | S_IWGRP)) == 0) { | ||
| if (!pcmk__any_flags_set(target_stat->st_mode, S_IRGRP|S_IWGRP)) { |
| CRM_LOG_ASSERT(client->user != NULL); | ||
| pcmk__update_acl_user(msg, PCMK__XA_CIB_USER, client->user); | ||
|
|
||
| pcmk__log_xml_trace(msg, "ipc-request"); |
There was a problem hiding this comment.
Move this log line along with the rest of the code so it'll reflect the other attributes we set.
This is the next batch from #4011.