Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/lib/pacemaker/pcmk_resource.c b/lib/pacemaker/pcmk_resource.c
index 72ae66d2a1..ab6bb42f2f 100644
--- a/lib/pacemaker/pcmk_resource.c
+++ b/lib/pacemaker/pcmk_resource.c
@@ -1,247 +1,248 @@
/*
* Copyright 2021-2023 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <errno.h>
#include <glib.h>
#include <libxml/tree.h>
#include <crm/cib/internal.h>
#include <crm/common/mainloop.h>
#include <crm/common/results.h>
#include <crm/common/output_internal.h>
#include <crm/pengine/internal.h>
#include <pacemaker.h>
#include <pacemaker-internal.h>
// Search path for resource operation history (takes node name and resource ID)
#define XPATH_OP_HISTORY "//" XML_CIB_TAG_STATUS \
"/" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']" \
"/" XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES \
"/" XML_LRM_TAG_RESOURCE "[@" XML_ATTR_ID "='%s']"
static xmlNode *
best_op(const pcmk_resource_t *rsc, const pcmk_node_t *node)
{
char *xpath = NULL;
xmlNode *history = NULL;
xmlNode *best = NULL;
bool best_effective_op = false;
guint best_interval = 0;
bool best_failure = false;
const char *best_digest = NULL;
// Find node's resource history
xpath = crm_strdup_printf(XPATH_OP_HISTORY, node->details->uname, rsc->id);
history = get_xpath_object(xpath, rsc->cluster->input, LOG_NEVER);
free(xpath);
// Examine each history entry
for (xmlNode *lrm_rsc_op = first_named_child(history, XML_LRM_TAG_RSC_OP);
lrm_rsc_op != NULL; lrm_rsc_op = crm_next_same_xml(lrm_rsc_op)) {
const char *digest = crm_element_value(lrm_rsc_op,
XML_LRM_ATTR_RESTART_DIGEST);
guint interval_ms = 0;
const char *task = crm_element_value(lrm_rsc_op, XML_LRM_ATTR_TASK);
bool effective_op = false;
bool failure = pcmk__ends_with(ID(lrm_rsc_op), "_last_failure_0");
crm_element_value_ms(lrm_rsc_op, XML_LRM_ATTR_INTERVAL, &interval_ms);
effective_op = interval_ms == 0
&& pcmk__strcase_any_of(task, PCMK_ACTION_MONITOR,
PCMK_ACTION_START,
PCMK_ACTION_PROMOTE,
PCMK_ACTION_MIGRATE_FROM, NULL);
if (best == NULL) {
goto is_best;
}
if (best_effective_op) {
// Do not use an ineffective op if there's an effective one.
if (!effective_op) {
continue;
}
// Do not use an ineffective non-recurring op if there's a recurring one
} else if (best_interval != 0
&& !effective_op
&& interval_ms == 0) {
continue;
}
// Do not use last failure if there's a successful one.
if (!best_failure && failure) {
continue;
}
// Do not use an op without a restart digest if there's one with.
if (best_digest != NULL && digest == NULL) {
continue;
}
// Do not use an older op if there's a newer one.
if (pe__is_newer_op(best, lrm_rsc_op, true) > 0) {
continue;
}
is_best:
best = lrm_rsc_op;
best_effective_op = effective_op;
best_interval = interval_ms;
best_failure = failure;
best_digest = digest;
}
return best;
}
/*!
* \internal
* \brief Remove a resource
*
* \param[in,out] cib An open connection to the CIB
* \param[in] cib_opts Options to use in the CIB operation call
* \param[in] rsc_id Resource to remove
* \param[in] rsc_type Type of the resource ("primitive", "group", etc.)
*
* \return Standard Pacemaker return code
*/
int
pcmk__resource_delete(cib_t *cib, uint32_t cib_opts, const char *rsc_id,
const char *rsc_type)
{
int rc = pcmk_rc_ok;
xmlNode *msg_data = NULL;
if (cib == NULL) {
return ENOTCONN;
}
if (rsc_id == NULL || rsc_type == NULL) {
return EINVAL;
}
msg_data = create_xml_node(NULL, rsc_type);
crm_xml_add(msg_data, XML_ATTR_ID, rsc_id);
rc = cib->cmds->remove(cib, XML_CIB_TAG_RESOURCES, msg_data, cib_opts);
rc = pcmk_legacy2rc(rc);
free_xml(msg_data);
return rc;
}
int
pcmk_resource_delete(xmlNodePtr *xml, const char *rsc_id, const char *rsc_type)
{
pcmk__output_t *out = NULL;
int rc = pcmk_rc_ok;
uint32_t cib_opts = cib_sync_call;
cib_t *cib = NULL;
rc = pcmk__xml_output_new(&out, xml);
if (rc != pcmk_rc_ok) {
return rc;
}
cib = cib_new();
if (cib == NULL) {
rc = pcmk_rc_cib_corrupt;
goto done;
}
rc = cib->cmds->signon(cib, crm_system_name, cib_command);
rc = pcmk_legacy2rc(rc);
if (rc != pcmk_rc_ok) {
goto done;
}
rc = pcmk__resource_delete(cib, cib_opts, rsc_id, rsc_type);
done:
if (cib != NULL) {
cib__clean_up_connection(&cib);
}
pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
return rc;
}
/*!
* \internal
* \brief Calculate and output resource operation digests
*
* \param[in,out] out Output object
* \param[in,out] rsc Resource to calculate digests for
* \param[in] node Node whose operation history should be used
* \param[in] overrides Hash table of configuration parameters to override
*
* \return Standard Pacemaker return code
*/
int
pcmk__resource_digests(pcmk__output_t *out, pcmk_resource_t *rsc,
const pcmk_node_t *node, GHashTable *overrides)
{
const char *task = NULL;
xmlNode *xml_op = NULL;
op_digest_cache_t *digests = NULL;
guint interval_ms = 0;
int rc = pcmk_rc_ok;
if ((out == NULL) || (rsc == NULL) || (node == NULL)) {
return EINVAL;
}
if (rsc->variant != pcmk_rsc_variant_primitive) {
// Only primitives get operation digests
return EOPNOTSUPP;
}
// Find XML of operation history to use
xml_op = best_op(rsc, node);
// Generate an operation key
if (xml_op != NULL) {
task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
}
if (task == NULL) { // Assume start if no history is available
task = PCMK_ACTION_START;
interval_ms = 0;
}
// Calculate and show digests
digests = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
overrides, true, rsc->cluster);
rc = out->message(out, "digests", rsc, node, task, interval_ms, digests);
pe__free_digests(digests);
return rc;
}
+// @COMPAT The scheduler parameter is unused and can be removed at the next break
int
pcmk_resource_digests(xmlNodePtr *xml, pcmk_resource_t *rsc,
const pcmk_node_t *node, GHashTable *overrides,
pcmk_scheduler_t *scheduler)
{
pcmk__output_t *out = NULL;
int rc = pcmk_rc_ok;
rc = pcmk__xml_output_new(&out, xml);
if (rc != pcmk_rc_ok) {
return rc;
}
pcmk__register_lib_messages(out);
rc = pcmk__resource_digests(out, rsc, node, overrides);
pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
return rc;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 16, 12:38 AM (10 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2456670
Default Alt Text
(7 KB)

Event Timeline