root/lib/pacemaker/pcmk_resource.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. best_op
  2. pcmk__resource_digests
  3. pcmk_resource_digests

   1 /*
   2  * Copyright 2021 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <errno.h>
  13 #include <glib.h>
  14 #include <libxml/tree.h>
  15 
  16 #include <crm/common/mainloop.h>
  17 #include <crm/common/results.h>
  18 #include <crm/common/output_internal.h>
  19 #include <crm/pengine/internal.h>
  20 
  21 #include <pacemaker.h>
  22 #include <pacemaker-internal.h>
  23 
  24 // Search path for resource operation history (takes node name and resource ID)
  25 #define XPATH_OP_HISTORY "//" XML_CIB_TAG_STATUS                            \
  26                          "/" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']" \
  27                          "/" XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES      \
  28                          "/" XML_LRM_TAG_RESOURCE "[@" XML_ATTR_ID "='%s']"
  29 
  30 static xmlNode *
  31 best_op(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33     char *xpath = NULL;
  34     xmlNode *history = NULL;
  35     xmlNode *best = NULL;
  36 
  37     // Find node's resource history
  38     xpath = crm_strdup_printf(XPATH_OP_HISTORY, node->details->uname, rsc->id);
  39     history = get_xpath_object(xpath, data_set->input, LOG_NEVER);
  40     free(xpath);
  41 
  42     // Examine each history entry
  43     for (xmlNode *lrm_rsc_op = first_named_child(history, XML_LRM_TAG_RSC_OP);
  44          lrm_rsc_op != NULL; lrm_rsc_op = crm_next_same_xml(lrm_rsc_op)) {
  45 
  46         const char *digest = crm_element_value(lrm_rsc_op,
  47                                                XML_LRM_ATTR_RESTART_DIGEST);
  48         guint interval_ms = 0;
  49 
  50         crm_element_value_ms(lrm_rsc_op, XML_LRM_ATTR_INTERVAL, &interval_ms);
  51 
  52         if (pcmk__ends_with(ID(lrm_rsc_op), "_last_failure_0")
  53             || (interval_ms != 0)) {
  54 
  55             // Only use last failure or recurring op if nothing else available
  56             if (best == NULL) {
  57                 best = lrm_rsc_op;
  58             }
  59             continue;
  60         }
  61 
  62         best = lrm_rsc_op;
  63         if (digest != NULL) {
  64             // Any non-recurring action with a restart digest is sufficient
  65             break;
  66         }
  67     }
  68     return best;
  69 }
  70 
  71 /*!
  72  * \internal
  73  * \brief Calculate and output resource operation digests
  74  *
  75  * \param[in]  out        Output object
  76  * \param[in]  rsc        Resource to calculate digests for
  77  * \param[in]  node       Node whose operation history should be used
  78  * \param[in]  overrides  Hash table of configuration parameters to override
  79  * \param[in]  data_set   Cluster working set (with status)
  80  *
  81  * \return Standard Pacemaker return code
  82  */
  83 int
  84 pcmk__resource_digests(pcmk__output_t *out, pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
  85                        pe_node_t *node, GHashTable *overrides,
  86                        pe_working_set_t *data_set)
  87 {
  88     const char *task = NULL;
  89     xmlNode *xml_op = NULL;
  90     op_digest_cache_t *digests = NULL;
  91     guint interval_ms = 0;
  92     int rc = pcmk_rc_ok;
  93 
  94     if ((out == NULL) || (rsc == NULL) || (node == NULL) || (data_set == NULL)) {
  95         return EINVAL;
  96     }
  97     if (rsc->variant != pe_native) {
  98         // Only primitives get operation digests
  99         return EOPNOTSUPP;
 100     }
 101 
 102     // Find XML of operation history to use
 103     xml_op = best_op(rsc, node, data_set);
 104 
 105     // Generate an operation key
 106     if (xml_op != NULL) {
 107         task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
 108         crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
 109     }
 110     if (task == NULL) { // Assume start if no history is available
 111         task = RSC_START;
 112         interval_ms = 0;
 113     }
 114 
 115     // Calculate and show digests
 116     digests = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
 117                                     overrides, true, data_set);
 118     rc = out->message(out, "digests", rsc, node, task, interval_ms, digests);
 119 
 120     pe__free_digests(digests);
 121     return rc;
 122 }
 123 
 124 int
 125 pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 126                       pe_node_t *node, GHashTable *overrides,
 127                       pe_working_set_t *data_set)
 128 {
 129     pcmk__output_t *out = NULL;
 130     int rc = pcmk_rc_ok;
 131 
 132     rc = pcmk__out_prologue(&out, xml);
 133     if (rc != pcmk_rc_ok) {
 134         return rc;
 135     }
 136     pcmk__register_lib_messages(out);
 137     rc = pcmk__resource_digests(out, rsc, node, overrides, data_set);
 138     pcmk__out_epilogue(out, xml, rc);
 139     return rc;
 140 }

/* [previous][next][first][last][top][bottom][index][help] */