Skip to content

Commit

Permalink
Low: libpacemaker: Don't assert on injecting nonexistent nodes.
Browse files Browse the repository at this point in the history
If crm_simulate tries to inject a node up or node fail action for a
nonexistent node, it'll just assert.  Instead, log an error message and
return NULL.

That NULL then needs to be propagated up a couple layers to functions
that actually expect and know how to handle errors.

Fixes T945
  • Loading branch information
clumens committed Jan 23, 2025
1 parent 4540673 commit 8fe1757
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
38 changes: 30 additions & 8 deletions lib/pacemaker/pcmk_injections.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ pcmk__inject_action_result(xmlNode *cib_resource, lrmd_event_data_t *op,
* \param[in] node Name of node to inject
* \param[in] uuid UUID of node to inject
*
* \return XML of \c PCMK__XE_NODE_STATE entry for new node
* \return XML of \c PCMK__XE_NODE_STATE entry for new node, or NULL if
* \c node is not valid
* \note If the global pcmk__simulate_node_config has been set to true, a
* node entry in the configuration section will be added, as well as a
* node state entry in the status section.
Expand Down Expand Up @@ -320,6 +321,11 @@ pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)

rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
cib_xpath|cib_sync_call);
if (rc == -ENXIO) {
crm_trace("Node %s does not exist", node);
goto done;
}

crm_trace("Injecting node state for %s (rc=%d)", node, rc);
}

Expand All @@ -333,7 +339,6 @@ pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
return NULL; // not reached, but makes static analysis happy
}

pcmk__assert(rc == pcmk_ok);
return cib_object;
}

Expand All @@ -345,13 +350,18 @@ pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
* \param[in] node Name of node to inject change for
* \param[in] up If true, change state to online, otherwise offline
*
* \return XML of changed (or added) node state entry
* \return XML of changed (or added) node state entry, or NULL if node is
* not valid
*/
xmlNode *
pcmk__inject_node_state_change(cib_t *cib_conn, const char *node, bool up)
{
xmlNode *cib_node = pcmk__inject_node(cib_conn, node, NULL);

if (cib_node == NULL) {
return cib_node;
}

if (up) {
pcmk__xe_set_props(cib_node,
PCMK__XA_IN_CCM, PCMK_VALUE_TRUE,
Expand Down Expand Up @@ -601,7 +611,10 @@ inject_action(pcmk__output_t *out, const char *spec, cib_t *cib,
rprovider = crm_element_value(rsc->priv->xml, PCMK_XA_PROVIDER);

cib_node = pcmk__inject_node(cib, node, NULL);
pcmk__assert(cib_node != NULL);
if (cib_node == NULL) {
out->err(out, "Node does not exist: %s", node);
goto done;
}

if (pcmk__str_eq(task, PCMK_ACTION_STOP, pcmk__str_none)) {
infinity = true;
Expand Down Expand Up @@ -679,7 +692,10 @@ pcmk__inject_scheduler_input(pcmk_scheduler_t *scheduler, cib_t *cib,
out->message(out, "inject-modify-node", "Online", node);

cib_node = pcmk__inject_node_state_change(cib, node, true);
pcmk__assert(cib_node != NULL);
if (cib_node == NULL) {
out->err(out, "Node does not exist: %s", node);
continue;
}

rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
pcmk__assert(rc == pcmk_ok);
Expand All @@ -693,7 +709,10 @@ pcmk__inject_scheduler_input(pcmk_scheduler_t *scheduler, cib_t *cib,
out->message(out, "inject-modify-node", "Offline", node);

cib_node = pcmk__inject_node_state_change(cib, node, false);
pcmk__assert(cib_node != NULL);
if (cib_node == NULL) {
out->err(out, "Node does not exist: %s", node);
continue;
}

rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
pcmk__assert(rc == pcmk_ok);
Expand All @@ -720,9 +739,12 @@ pcmk__inject_scheduler_input(pcmk_scheduler_t *scheduler, cib_t *cib,
out->message(out, "inject-modify-node", "Failing", node);

cib_node = pcmk__inject_node_state_change(cib, node, true);
crm_xml_add(cib_node, PCMK__XA_IN_CCM, PCMK_VALUE_FALSE);
pcmk__assert(cib_node != NULL);
if (cib_node == NULL) {
out->err(out, "Node does not exist: %s", node);
continue;
}

crm_xml_add(cib_node, PCMK__XA_IN_CCM, PCMK_VALUE_FALSE);
rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
pcmk__assert(rc == pcmk_ok);
pcmk__xml_free(cib_node);
Expand Down
14 changes: 13 additions & 1 deletion lib/pacemaker/pcmk_simulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,14 @@ simulate_resource_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
uuid = crm_element_value_copy(action->xml, PCMK__META_ON_NODE_UUID);
cib_node = pcmk__inject_node(fake_cib, node,
((router_node == NULL)? uuid: node));
if (cib_node == NULL) {
crm_err("Could not simulate action %d on unknown node %s",
action->id, node);
free(node);
return EINVAL;
}

free(uuid);
pcmk__assert(cib_node != NULL);

// Add a history entry for the action
cib_resource = pcmk__inject_resource_history(out, cib_node, resource,
Expand Down Expand Up @@ -714,6 +720,12 @@ simulate_fencing_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
// Set node state to offline
xmlNode *cib_node = pcmk__inject_node_state_change(fake_cib, target,
false);
if (cib_node == NULL) {
out->err(out, "Could not simulate fencing action %d on unknown node %s",
action->id, target);
free(target);
return -EINVAL;
}

pcmk__assert(cib_node != NULL);
crm_xml_add(cib_node, PCMK_XA_CRM_DEBUG_ORIGIN, __func__);
Expand Down

0 comments on commit 8fe1757

Please sign in to comment.