root/lib/pengine/pe_digest.c

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

DEFINITIONS

This source file includes following definitions.
  1. pe__free_digests
  2. attr_not_in_string
  3. attr_in_string
  4. calculate_main_digest
  5. is_fence_param
  6. calculate_secure_digest
  7. calculate_restart_digest
  8. pe__calculate_digests
  9. rsc_action_digest
  10. rsc_action_digest_cmp
  11. create_unfencing_summary
  12. unfencing_digest_matches
  13. pe__compare_fencing_digest

   1 /*
   2  * Copyright 2004-2022 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 Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <glib.h>
  13 #include <stdbool.h>
  14 
  15 #include <crm/crm.h>
  16 #include <crm/msg_xml.h>
  17 #include <crm/common/xml.h>
  18 #include <crm/common/xml_internal.h>
  19 #include <crm/pengine/internal.h>
  20 #include "pe_status_private.h"
  21 
  22 extern bool pcmk__is_daemon;
  23 
  24 /*!
  25  * \internal
  26  * \brief Free an operation digest cache entry
  27  *
  28  * \param[in,out] ptr  Pointer to cache entry to free
  29  *
  30  * \note The argument is a gpointer so this can be used as a hash table
  31  *       free function.
  32  */
  33 void
  34 pe__free_digests(gpointer ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36     op_digest_cache_t *data = ptr;
  37 
  38     if (data != NULL) {
  39         free_xml(data->params_all);
  40         free_xml(data->params_secure);
  41         free_xml(data->params_restart);
  42 
  43         free(data->digest_all_calc);
  44         free(data->digest_restart_calc);
  45         free(data->digest_secure_calc);
  46 
  47         free(data);
  48     }
  49 }
  50 
  51 // Return true if XML attribute name is not substring of a given string
  52 static bool
  53 attr_not_in_string(xmlAttrPtr a, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55     bool filter = false;
  56     char *name = crm_strdup_printf(" %s ", (const char *) a->name);
  57 
  58     if (strstr((const char *) user_data, name) == NULL) {
  59         crm_trace("Filtering %s (not found in '%s')",
  60                   (const char *) a->name, (const char *) user_data);
  61         filter = true;
  62     }
  63     free(name);
  64     return filter;
  65 }
  66 
  67 // Return true if XML attribute name is substring of a given string
  68 static bool
  69 attr_in_string(xmlAttrPtr a, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71     bool filter = false;
  72     char *name = crm_strdup_printf(" %s ", (const char *) a->name);
  73 
  74     if (strstr((const char *) user_data, name) != NULL) {
  75         crm_trace("Filtering %s (found in '%s')",
  76                   (const char *) a->name, (const char *) user_data);
  77         filter = true;
  78     }
  79     free(name);
  80     return filter;
  81 }
  82 
  83 /*!
  84  * \internal
  85  * \brief Add digest of all parameters to a digest cache entry
  86  *
  87  * \param[out]    data         Digest cache entry to modify
  88  * \param[in,out] rsc          Resource that action was for
  89  * \param[in]     node         Node action was performed on
  90  * \param[in]     params       Resource parameters evaluated for node
  91  * \param[in]     task         Name of action performed
  92  * \param[in,out] interval_ms  Action's interval (will be reset if in overrides)
  93  * \param[in]     xml_op       Unused
  94  * \param[in]     op_version   CRM feature set to use for digest calculation
  95  * \param[in]     overrides    Key/value table to override resource parameters
  96  * \param[in,out] data_set     Cluster working set
  97  */
  98 static void
  99 calculate_main_digest(op_digest_cache_t *data, pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 100                       const pe_node_t *node, GHashTable *params,
 101                       const char *task, guint *interval_ms,
 102                       const xmlNode *xml_op, const char *op_version,
 103                       GHashTable *overrides, pe_working_set_t *data_set)
 104 {
 105     pe_action_t *action = NULL;
 106 
 107     data->params_all = create_xml_node(NULL, XML_TAG_PARAMS);
 108 
 109     /* REMOTE_CONTAINER_HACK: Allow Pacemaker Remote nodes to run containers
 110      * that themselves are Pacemaker Remote nodes
 111      */
 112     (void) pe__add_bundle_remote_name(rsc, data_set, data->params_all,
 113                                       XML_RSC_ATTR_REMOTE_RA_ADDR);
 114 
 115     // If interval was overridden, reset it
 116     if (overrides != NULL) {
 117         const char *interval_s = g_hash_table_lookup(overrides, CRM_META "_"
 118                                                      XML_LRM_ATTR_INTERVAL);
 119 
 120         if (interval_s != NULL) {
 121             long long value_ll;
 122 
 123             if ((pcmk__scan_ll(interval_s, &value_ll, 0LL) == pcmk_rc_ok)
 124                 && (value_ll >= 0) && (value_ll <= G_MAXUINT)) {
 125                 *interval_ms = (guint) value_ll;
 126             }
 127         }
 128     }
 129 
 130     action = custom_action(rsc, pcmk__op_key(rsc->id, task, *interval_ms),
 131                            task, node, TRUE, FALSE, data_set);
 132     if (overrides != NULL) {
 133         g_hash_table_foreach(overrides, hash2field, data->params_all);
 134     }
 135     g_hash_table_foreach(params, hash2field, data->params_all);
 136     g_hash_table_foreach(action->extra, hash2field, data->params_all);
 137     g_hash_table_foreach(action->meta, hash2metafield, data->params_all);
 138 
 139     pcmk__filter_op_for_digest(data->params_all);
 140 
 141     /* Given a non-recurring operation with extra parameters configured,
 142      * in case that the main digest doesn't match, even if the restart
 143      * digest matches, enforce a restart rather than a reload-agent anyway.
 144      * So that it ensures any changes of the extra parameters get applied
 145      * for this specific operation, and the digests calculated for the
 146      * resulting lrm_rsc_op will be correct.
 147      * Mark the implied rc RSC_DIGEST_RESTART for the case that the main
 148      * digest doesn't match.
 149      */
 150     if (*interval_ms == 0
 151         && g_hash_table_size(action->extra) > 0) {
 152         data->rc = RSC_DIGEST_RESTART;
 153     }
 154 
 155     pe_free_action(action);
 156 
 157     data->digest_all_calc = calculate_operation_digest(data->params_all,
 158                                                        op_version);
 159 }
 160 
 161 // Return true if XML attribute name is a Pacemaker-defined fencing parameter
 162 static bool
 163 is_fence_param(xmlAttrPtr attr, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 164 {
 165     return pcmk_stonith_param((const char *) attr->name);
 166 }
 167 
 168 /*!
 169  * \internal
 170  * \brief Add secure digest to a digest cache entry
 171  *
 172  * \param[out] data        Digest cache entry to modify
 173  * \param[in]  rsc         Resource that action was for
 174  * \param[in]  params      Resource parameters evaluated for node
 175  * \param[in]  xml_op      XML of operation in CIB status (if available)
 176  * \param[in]  op_version  CRM feature set to use for digest calculation
 177  * \param[in]  overrides   Key/value hash table to override resource parameters
 178  */
 179 static void
 180 calculate_secure_digest(op_digest_cache_t *data, const pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 181                         GHashTable *params, const xmlNode *xml_op,
 182                         const char *op_version, GHashTable *overrides)
 183 {
 184     const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 185     const char *secure_list = NULL;
 186     bool old_version = (compare_version(op_version, "3.16.0") < 0);
 187 
 188     if (xml_op == NULL) {
 189         secure_list = " passwd password user ";
 190     } else {
 191         secure_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_SECURE);
 192     }
 193 
 194     if (old_version) {
 195         data->params_secure = create_xml_node(NULL, XML_TAG_PARAMS);
 196         if (overrides != NULL) {
 197             g_hash_table_foreach(overrides, hash2field, data->params_secure);
 198         }
 199 
 200         g_hash_table_foreach(params, hash2field, data->params_secure);
 201 
 202     } else {
 203         // Start with a copy of all parameters
 204         data->params_secure = copy_xml(data->params_all);
 205     }
 206 
 207     if (secure_list != NULL) {
 208         pcmk__xe_remove_matching_attrs(data->params_secure, attr_in_string,
 209                                        (void *) secure_list);
 210     }
 211     if (old_version
 212         && pcmk_is_set(pcmk_get_ra_caps(class),
 213                        pcmk_ra_cap_fence_params)) {
 214         /* For stonith resources, Pacemaker adds special parameters,
 215          * but these are not listed in fence agent meta-data, so with older
 216          * versions of DC, the controller will not hash them. That means we have
 217          * to filter them out before calculating our hash for comparison.
 218          */
 219         pcmk__xe_remove_matching_attrs(data->params_secure, is_fence_param,
 220                                        NULL);
 221     }
 222     pcmk__filter_op_for_digest(data->params_secure);
 223 
 224     /* CRM_meta_timeout *should* be part of a digest for recurring operations.
 225      * However, with older versions of DC, the controller does not add timeout
 226      * to secure digests, because it only includes parameters declared by the
 227      * resource agent.
 228      * Remove any timeout that made it this far, to match.
 229      */
 230     if (old_version) {
 231         xml_remove_prop(data->params_secure, CRM_META "_" XML_ATTR_TIMEOUT);
 232     }
 233 
 234     data->digest_secure_calc = calculate_operation_digest(data->params_secure,
 235                                                           op_version);
 236 }
 237 
 238 /*!
 239  * \internal
 240  * \brief Add restart digest to a digest cache entry
 241  *
 242  * \param[out] data        Digest cache entry to modify
 243  * \param[in]  xml_op      XML of operation in CIB status (if available)
 244  * \param[in]  op_version  CRM feature set to use for digest calculation
 245  *
 246  * \note This function doesn't need to handle overrides because it starts with
 247  *       data->params_all, which already has overrides applied.
 248  */
 249 static void
 250 calculate_restart_digest(op_digest_cache_t *data, const xmlNode *xml_op,
     /* [previous][next][first][last][top][bottom][index][help] */
 251                          const char *op_version)
 252 {
 253     const char *value = NULL;
 254 
 255     // We must have XML of resource operation history
 256     if (xml_op == NULL) {
 257         return;
 258     }
 259 
 260     // And the history must have a restart digest to compare against
 261     if (crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST) == NULL) {
 262         return;
 263     }
 264 
 265     // Start with a copy of all parameters
 266     data->params_restart = copy_xml(data->params_all);
 267 
 268     // Then filter out reloadable parameters, if any
 269     value = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);
 270     if (value != NULL) {
 271         pcmk__xe_remove_matching_attrs(data->params_restart, attr_not_in_string,
 272                                        (void *) value);
 273     }
 274 
 275     value = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
 276     data->digest_restart_calc = calculate_operation_digest(data->params_restart,
 277                                                            value);
 278 }
 279 
 280 /*!
 281  * \internal
 282  * \brief Create a new digest cache entry with calculated digests
 283  *
 284  * \param[in,out] rsc          Resource that action was for
 285  * \param[in]     task         Name of action performed
 286  * \param[in,out] interval_ms  Action's interval (will be reset if in overrides)
 287  * \param[in]     node         Node action was performed on
 288  * \param[in]     xml_op       XML of operation in CIB status (if available)
 289  * \param[in]     overrides    Key/value table to override resource parameters
 290  * \param[in]     calc_secure  Whether to calculate secure digest
 291  * \param[in,out] data_set     Cluster working set
 292  *
 293  * \return Pointer to new digest cache entry (or NULL on memory error)
 294  * \note It is the caller's responsibility to free the result using
 295  *       pe__free_digests().
 296  */
 297 op_digest_cache_t *
 298 pe__calculate_digests(pe_resource_t *rsc, const char *task, guint *interval_ms,
     /* [previous][next][first][last][top][bottom][index][help] */
 299                       const pe_node_t *node, const xmlNode *xml_op,
 300                       GHashTable *overrides, bool calc_secure,
 301                       pe_working_set_t *data_set)
 302 {
 303     op_digest_cache_t *data = calloc(1, sizeof(op_digest_cache_t));
 304     const char *op_version = NULL;
 305     GHashTable *params = NULL;
 306 
 307     if (data == NULL) {
 308         return NULL;
 309     }
 310 
 311     data->rc = RSC_DIGEST_MATCH;
 312 
 313     if (xml_op != NULL) {
 314         op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
 315     }
 316 
 317     if (op_version == NULL && data_set != NULL && data_set->input != NULL) {
 318         op_version = crm_element_value(data_set->input, XML_ATTR_CRM_VERSION);
 319     }
 320 
 321     if (op_version == NULL) {
 322         op_version = CRM_FEATURE_SET;
 323     }
 324 
 325     params = pe_rsc_params(rsc, node, data_set);
 326     calculate_main_digest(data, rsc, node, params, task, interval_ms, xml_op,
 327                           op_version, overrides, data_set);
 328     if (calc_secure) {
 329         calculate_secure_digest(data, rsc, params, xml_op, op_version,
 330                                 overrides);
 331     }
 332     calculate_restart_digest(data, xml_op, op_version);
 333     return data;
 334 }
 335 
 336 /*!
 337  * \internal
 338  * \brief Calculate action digests and store in node's digest cache
 339  *
 340  * \param[in,out] rsc          Resource that action was for
 341  * \param[in]     task         Name of action performed
 342  * \param[in]     interval_ms  Action's interval
 343  * \param[in,out] node         Node action was performed on
 344  * \param[in]     xml_op       XML of operation in CIB status (if available)
 345  * \param[in]     calc_secure  Whether to calculate secure digest
 346  * \param[in,out] data_set     Cluster working set
 347  *
 348  * \return Pointer to node's digest cache entry
 349  */
 350 static op_digest_cache_t *
 351 rsc_action_digest(pe_resource_t *rsc, const char *task, guint interval_ms,
     /* [previous][next][first][last][top][bottom][index][help] */
 352                   pe_node_t *node, const xmlNode *xml_op,
 353                   bool calc_secure, pe_working_set_t *data_set)
 354 {
 355     op_digest_cache_t *data = NULL;
 356     char *key = pcmk__op_key(rsc->id, task, interval_ms);
 357 
 358     data = g_hash_table_lookup(node->details->digest_cache, key);
 359     if (data == NULL) {
 360         data = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
 361                                      NULL, calc_secure, data_set);
 362         CRM_ASSERT(data != NULL);
 363         g_hash_table_insert(node->details->digest_cache, strdup(key), data);
 364     }
 365     free(key);
 366     return data;
 367 }
 368 
 369 /*!
 370  * \internal
 371  * \brief Calculate operation digests and compare against an XML history entry
 372  *
 373  * \param[in,out] rsc       Resource to check
 374  * \param[in]     xml_op    Resource history XML
 375  * \param[in,out] node      Node to use for digest calculation
 376  * \param[in,out] data_set  Cluster working set
 377  *
 378  * \return Pointer to node's digest cache entry, with comparison result set
 379  */
 380 op_digest_cache_t *
 381 rsc_action_digest_cmp(pe_resource_t *rsc, const xmlNode *xml_op,
     /* [previous][next][first][last][top][bottom][index][help] */
 382                       pe_node_t *node, pe_working_set_t *data_set)
 383 {
 384     op_digest_cache_t *data = NULL;
 385     guint interval_ms = 0;
 386 
 387     const char *op_version;
 388     const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
 389     const char *digest_all;
 390     const char *digest_restart;
 391 
 392     CRM_ASSERT(node != NULL);
 393 
 394     op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
 395     digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
 396     digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
 397 
 398     crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
 399     data = rsc_action_digest(rsc, task, interval_ms, node, xml_op,
 400                              pcmk_is_set(data_set->flags, pe_flag_sanitized),
 401                              data_set);
 402 
 403     if (digest_restart && data->digest_restart_calc && strcmp(data->digest_restart_calc, digest_restart) != 0) {
 404         pe_rsc_info(rsc, "Parameters to %ums-interval %s action for %s on %s "
 405                          "changed: hash was %s vs. now %s (restart:%s) %s",
 406                     interval_ms, task, rsc->id, pe__node_name(node),
 407                     pcmk__s(digest_restart, "missing"),
 408                     data->digest_restart_calc,
 409                     op_version,
 410                     crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 411         data->rc = RSC_DIGEST_RESTART;
 412 
 413     } else if (digest_all == NULL) {
 414         /* it is unknown what the previous op digest was */
 415         data->rc = RSC_DIGEST_UNKNOWN;
 416 
 417     } else if (strcmp(digest_all, data->digest_all_calc) != 0) {
 418         /* Given a non-recurring operation with extra parameters configured,
 419          * in case that the main digest doesn't match, even if the restart
 420          * digest matches, enforce a restart rather than a reload-agent anyway.
 421          * So that it ensures any changes of the extra parameters get applied
 422          * for this specific operation, and the digests calculated for the
 423          * resulting lrm_rsc_op will be correct.
 424          * Preserve the implied rc RSC_DIGEST_RESTART for the case that the main
 425          * digest doesn't match.
 426          */
 427         if (interval_ms == 0
 428             && data->rc == RSC_DIGEST_RESTART) {
 429             pe_rsc_info(rsc, "Parameters containing extra ones to %ums-interval"
 430                              " %s action for %s on %s "
 431                              "changed: hash was %s vs. now %s (restart:%s) %s",
 432                         interval_ms, task, rsc->id, pe__node_name(node),
 433                         pcmk__s(digest_all, "missing"), data->digest_all_calc,
 434                         op_version,
 435                         crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 436 
 437         } else {
 438             pe_rsc_info(rsc, "Parameters to %ums-interval %s action for %s on %s "
 439                              "changed: hash was %s vs. now %s (%s:%s) %s",
 440                         interval_ms, task, rsc->id, pe__node_name(node),
 441                         pcmk__s(digest_all, "missing"), data->digest_all_calc,
 442                         (interval_ms > 0)? "reschedule" : "reload",
 443                         op_version,
 444                         crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 445             data->rc = RSC_DIGEST_ALL;
 446         }
 447 
 448     } else {
 449         data->rc = RSC_DIGEST_MATCH;
 450     }
 451     return data;
 452 }
 453 
 454 /*!
 455  * \internal
 456  * \brief Create an unfencing summary for use in special node attribute
 457  *
 458  * Create a string combining a fence device's resource ID, agent type, and
 459  * parameter digest (whether for all parameters or just non-private parameters).
 460  * This can be stored in a special node attribute, allowing us to detect changes
 461  * in either the agent type or parameters, to know whether unfencing must be
 462  * redone or can be safely skipped when the device's history is cleaned.
 463  *
 464  * \param[in] rsc_id        Fence device resource ID
 465  * \param[in] agent_type    Fence device agent
 466  * \param[in] param_digest  Fence device parameter digest
 467  *
 468  * \return Newly allocated string with unfencing digest
 469  * \note The caller is responsible for freeing the result.
 470  */
 471 static inline char *
 472 create_unfencing_summary(const char *rsc_id, const char *agent_type,
     /* [previous][next][first][last][top][bottom][index][help] */
 473                          const char *param_digest)
 474 {
 475     return crm_strdup_printf("%s:%s:%s", rsc_id, agent_type, param_digest);
 476 }
 477 
 478 /*!
 479  * \internal
 480  * \brief Check whether a node can skip unfencing
 481  *
 482  * Check whether a fence device's current definition matches a node's
 483  * stored summary of when it was last unfenced by the device.
 484  *
 485  * \param[in] rsc_id        Fence device's resource ID
 486  * \param[in] agent         Fence device's agent type
 487  * \param[in] digest_calc   Fence device's current parameter digest
 488  * \param[in] node_summary  Value of node's special unfencing node attribute
 489  *                          (a comma-separated list of unfencing summaries for
 490  *                          all devices that have unfenced this node)
 491  *
 492  * \return TRUE if digest matches, FALSE otherwise
 493  */
 494 static bool
 495 unfencing_digest_matches(const char *rsc_id, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 496                          const char *digest_calc, const char *node_summary)
 497 {
 498     bool matches = FALSE;
 499 
 500     if (rsc_id && agent && digest_calc && node_summary) {
 501         char *search_secure = create_unfencing_summary(rsc_id, agent,
 502                                                        digest_calc);
 503 
 504         /* The digest was calculated including the device ID and agent,
 505          * so there is no risk of collision using strstr().
 506          */
 507         matches = (strstr(node_summary, search_secure) != NULL);
 508         crm_trace("Calculated unfencing digest '%s' %sfound in '%s'",
 509                   search_secure, matches? "" : "not ", node_summary);
 510         free(search_secure);
 511     }
 512     return matches;
 513 }
 514 
 515 /* Magic string to use as action name for digest cache entries used for
 516  * unfencing checks. This is not a real action name (i.e. "on"), so
 517  * pcmk__check_action_config() won't confuse these entries with real actions.
 518  */
 519 #define STONITH_DIGEST_TASK "stonith-on"
 520 
 521 /*!
 522  * \internal
 523  * \brief Calculate fence device digests and digest comparison result
 524  *
 525  * \param[in,out] rsc       Fence device resource
 526  * \param[in]     agent     Fence device's agent type
 527  * \param[in,out] node      Node with digest cache to use
 528  * \param[in,out] data_set  Cluster working set
 529  *
 530  * \return Node's digest cache entry
 531  */
 532 op_digest_cache_t *
 533 pe__compare_fencing_digest(pe_resource_t *rsc, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 534                            pe_node_t *node, pe_working_set_t *data_set)
 535 {
 536     const char *node_summary = NULL;
 537 
 538     // Calculate device's current parameter digests
 539     op_digest_cache_t *data = rsc_action_digest(rsc, STONITH_DIGEST_TASK, 0U,
 540                                                 node, NULL, TRUE, data_set);
 541 
 542     // Check whether node has special unfencing summary node attribute
 543     node_summary = pe_node_attribute_raw(node, CRM_ATTR_DIGESTS_ALL);
 544     if (node_summary == NULL) {
 545         data->rc = RSC_DIGEST_UNKNOWN;
 546         return data;
 547     }
 548 
 549     // Check whether full parameter digest matches
 550     if (unfencing_digest_matches(rsc->id, agent, data->digest_all_calc,
 551                                  node_summary)) {
 552         data->rc = RSC_DIGEST_MATCH;
 553         return data;
 554     }
 555 
 556     // Check whether secure parameter digest matches
 557     node_summary = pe_node_attribute_raw(node, CRM_ATTR_DIGESTS_SECURE);
 558     if (unfencing_digest_matches(rsc->id, agent, data->digest_secure_calc,
 559                                  node_summary)) {
 560         data->rc = RSC_DIGEST_MATCH;
 561         if (!pcmk__is_daemon && data_set->priv != NULL) {
 562             pcmk__output_t *out = data_set->priv;
 563             out->info(out, "Only 'private' parameters to %s "
 564                       "for unfencing %s changed", rsc->id,
 565                       pe__node_name(node));
 566         }
 567         return data;
 568     }
 569 
 570     // Parameters don't match
 571     data->rc = RSC_DIGEST_ALL;
 572     if (pcmk_is_set(data_set->flags, pe_flag_sanitized) && data->digest_secure_calc) {
 573         if (data_set->priv != NULL) {
 574             pcmk__output_t *out = data_set->priv;
 575             char *digest = create_unfencing_summary(rsc->id, agent,
 576                                                     data->digest_secure_calc);
 577 
 578             out->info(out, "Parameters to %s for unfencing "
 579                       "%s changed, try '%s'", rsc->id,
 580                       pe__node_name(node), digest);
 581             free(digest);
 582         } else if (!pcmk__is_daemon) {
 583             char *digest = create_unfencing_summary(rsc->id, agent,
 584                                                     data->digest_secure_calc);
 585 
 586             printf("Parameters to %s for unfencing %s changed, try '%s'\n",
 587                    rsc->id, pe__node_name(node), digest);
 588             free(digest);
 589         }
 590     }
 591     return data;
 592 }

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