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] 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]     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       XML of operation in CIB status (if available)
  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]     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                       pe_node_t *node, GHashTable *params,
 101                       const char *task, guint *interval_ms,
 102                       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, pe_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 181                         GHashTable *params, 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, 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]     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]     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                       pe_node_t *node, xmlNode *xml_op, GHashTable *overrides,
 300                       bool calc_secure, pe_working_set_t *data_set)
 301 {
 302     op_digest_cache_t *data = calloc(1, sizeof(op_digest_cache_t));
 303     const char *op_version = NULL;
 304     GHashTable *params = NULL;
 305 
 306     if (data == NULL) {
 307         return NULL;
 308     }
 309 
 310     data->rc = RSC_DIGEST_MATCH;
 311 
 312     if (xml_op != NULL) {
 313         op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
 314     }
 315 
 316     if (op_version == NULL && data_set != NULL && data_set->input != NULL) {
 317         op_version = crm_element_value(data_set->input, XML_ATTR_CRM_VERSION);
 318     }
 319 
 320     if (op_version == NULL) {
 321         op_version = CRM_FEATURE_SET;
 322     }
 323 
 324     params = pe_rsc_params(rsc, node, data_set);
 325     calculate_main_digest(data, rsc, node, params, task, interval_ms, xml_op,
 326                           op_version, overrides, data_set);
 327     if (calc_secure) {
 328         calculate_secure_digest(data, rsc, params, xml_op, op_version,
 329                                 overrides);
 330     }
 331     calculate_restart_digest(data, xml_op, op_version);
 332     return data;
 333 }
 334 
 335 /*!
 336  * \internal
 337  * \brief Calculate action digests and store in node's digest cache
 338  *
 339  * \param[in] rsc          Resource that action was for
 340  * \param[in] task         Name of action performed
 341  * \param[in] interval_ms  Action's interval
 342  * \param[in] node         Node action was performed on
 343  * \param[in] xml_op       XML of operation in CIB status (if available)
 344  * \param[in] calc_secure  Whether to calculate secure digest
 345  * \param[in] data_set     Cluster working set
 346  *
 347  * \return Pointer to node's digest cache entry
 348  */
 349 static op_digest_cache_t *
 350 rsc_action_digest(pe_resource_t *rsc, const char *task, guint interval_ms,
     /* [previous][next][first][last][top][bottom][index][help] */
 351                   pe_node_t *node, xmlNode *xml_op, bool calc_secure,
 352                   pe_working_set_t *data_set)
 353 {
 354     op_digest_cache_t *data = NULL;
 355     char *key = pcmk__op_key(rsc->id, task, interval_ms);
 356 
 357     data = g_hash_table_lookup(node->details->digest_cache, key);
 358     if (data == NULL) {
 359         data = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
 360                                      NULL, calc_secure, data_set);
 361         CRM_ASSERT(data != NULL);
 362         g_hash_table_insert(node->details->digest_cache, strdup(key), data);
 363     }
 364     free(key);
 365     return data;
 366 }
 367 
 368 /*!
 369  * \internal
 370  * \brief Calculate operation digests and compare against an XML history entry
 371  *
 372  * \param[in] rsc       Resource to check
 373  * \param[in] xml_op    Resource history XML
 374  * \param[in] node      Node to use for digest calculation
 375  * \param[in] data_set  Cluster working set
 376  *
 377  * \return Pointer to node's digest cache entry, with comparison result set
 378  */
 379 op_digest_cache_t *
 380 rsc_action_digest_cmp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * node,
     /* [previous][next][first][last][top][bottom][index][help] */
 381                       pe_working_set_t * data_set)
 382 {
 383     op_digest_cache_t *data = NULL;
 384     guint interval_ms = 0;
 385 
 386     const char *op_version;
 387     const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
 388     const char *digest_all;
 389     const char *digest_restart;
 390 
 391     CRM_ASSERT(node != NULL);
 392 
 393     op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);
 394     digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
 395     digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
 396 
 397     crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
 398     data = rsc_action_digest(rsc, task, interval_ms, node, xml_op,
 399                              pcmk_is_set(data_set->flags, pe_flag_sanitized),
 400                              data_set);
 401 
 402     if (digest_restart && data->digest_restart_calc && strcmp(data->digest_restart_calc, digest_restart) != 0) {
 403         pe_rsc_info(rsc, "Parameters to %ums-interval %s action for %s on %s "
 404                          "changed: hash was %s vs. now %s (restart:%s) %s",
 405                     interval_ms, task, rsc->id, pe__node_name(node),
 406                     pcmk__s(digest_restart, "missing"),
 407                     data->digest_restart_calc,
 408                     op_version,
 409                     crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 410         data->rc = RSC_DIGEST_RESTART;
 411 
 412     } else if (digest_all == NULL) {
 413         /* it is unknown what the previous op digest was */
 414         data->rc = RSC_DIGEST_UNKNOWN;
 415 
 416     } else if (strcmp(digest_all, data->digest_all_calc) != 0) {
 417         /* Given a non-recurring operation with extra parameters configured,
 418          * in case that the main digest doesn't match, even if the restart
 419          * digest matches, enforce a restart rather than a reload-agent anyway.
 420          * So that it ensures any changes of the extra parameters get applied
 421          * for this specific operation, and the digests calculated for the
 422          * resulting lrm_rsc_op will be correct.
 423          * Preserve the implied rc RSC_DIGEST_RESTART for the case that the main
 424          * digest doesn't match.
 425          */
 426         if (interval_ms == 0
 427             && data->rc == RSC_DIGEST_RESTART) {
 428             pe_rsc_info(rsc, "Parameters containing extra ones to %ums-interval"
 429                              " %s action for %s on %s "
 430                              "changed: hash was %s vs. now %s (restart:%s) %s",
 431                         interval_ms, task, rsc->id, pe__node_name(node),
 432                         pcmk__s(digest_all, "missing"), data->digest_all_calc,
 433                         op_version,
 434                         crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 435 
 436         } else {
 437             pe_rsc_info(rsc, "Parameters to %ums-interval %s action for %s on %s "
 438                              "changed: hash was %s vs. now %s (%s:%s) %s",
 439                         interval_ms, task, rsc->id, pe__node_name(node),
 440                         pcmk__s(digest_all, "missing"), data->digest_all_calc,
 441                         (interval_ms > 0)? "reschedule" : "reload",
 442                         op_version,
 443                         crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
 444             data->rc = RSC_DIGEST_ALL;
 445         }
 446 
 447     } else {
 448         data->rc = RSC_DIGEST_MATCH;
 449     }
 450     return data;
 451 }
 452 
 453 /*!
 454  * \internal
 455  * \brief Create an unfencing summary for use in special node attribute
 456  *
 457  * Create a string combining a fence device's resource ID, agent type, and
 458  * parameter digest (whether for all parameters or just non-private parameters).
 459  * This can be stored in a special node attribute, allowing us to detect changes
 460  * in either the agent type or parameters, to know whether unfencing must be
 461  * redone or can be safely skipped when the device's history is cleaned.
 462  *
 463  * \param[in] rsc_id        Fence device resource ID
 464  * \param[in] agent_type    Fence device agent
 465  * \param[in] param_digest  Fence device parameter digest
 466  *
 467  * \return Newly allocated string with unfencing digest
 468  * \note The caller is responsible for freeing the result.
 469  */
 470 static inline char *
 471 create_unfencing_summary(const char *rsc_id, const char *agent_type,
     /* [previous][next][first][last][top][bottom][index][help] */
 472                          const char *param_digest)
 473 {
 474     return crm_strdup_printf("%s:%s:%s", rsc_id, agent_type, param_digest);
 475 }
 476 
 477 /*!
 478  * \internal
 479  * \brief Check whether a node can skip unfencing
 480  *
 481  * Check whether a fence device's current definition matches a node's
 482  * stored summary of when it was last unfenced by the device.
 483  *
 484  * \param[in] rsc_id        Fence device's resource ID
 485  * \param[in] agent         Fence device's agent type
 486  * \param[in] digest_calc   Fence device's current parameter digest
 487  * \param[in] node_summary  Value of node's special unfencing node attribute
 488  *                          (a comma-separated list of unfencing summaries for
 489  *                          all devices that have unfenced this node)
 490  *
 491  * \return TRUE if digest matches, FALSE otherwise
 492  */
 493 static bool
 494 unfencing_digest_matches(const char *rsc_id, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 495                          const char *digest_calc, const char *node_summary)
 496 {
 497     bool matches = FALSE;
 498 
 499     if (rsc_id && agent && digest_calc && node_summary) {
 500         char *search_secure = create_unfencing_summary(rsc_id, agent,
 501                                                        digest_calc);
 502 
 503         /* The digest was calculated including the device ID and agent,
 504          * so there is no risk of collision using strstr().
 505          */
 506         matches = (strstr(node_summary, search_secure) != NULL);
 507         crm_trace("Calculated unfencing digest '%s' %sfound in '%s'",
 508                   search_secure, matches? "" : "not ", node_summary);
 509         free(search_secure);
 510     }
 511     return matches;
 512 }
 513 
 514 /* Magic string to use as action name for digest cache entries used for
 515  * unfencing checks. This is not a real action name (i.e. "on"), so
 516  * pcmk__check_action_config() won't confuse these entries with real actions.
 517  */
 518 #define STONITH_DIGEST_TASK "stonith-on"
 519 
 520 /*!
 521  * \internal
 522  * \brief Calculate fence device digests and digest comparison result
 523  *
 524  * \param[in] rsc       Fence device resource
 525  * \param[in] agent     Fence device's agent type
 526  * \param[in] node      Node with digest cache to use
 527  * \param[in] data_set  Cluster working set
 528  *
 529  * \return Node's digest cache entry
 530  */
 531 op_digest_cache_t *
 532 pe__compare_fencing_digest(pe_resource_t *rsc, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 533                            pe_node_t *node, pe_working_set_t *data_set)
 534 {
 535     const char *node_summary = NULL;
 536 
 537     // Calculate device's current parameter digests
 538     op_digest_cache_t *data = rsc_action_digest(rsc, STONITH_DIGEST_TASK, 0U,
 539                                                 node, NULL, TRUE, data_set);
 540 
 541     // Check whether node has special unfencing summary node attribute
 542     node_summary = pe_node_attribute_raw(node, CRM_ATTR_DIGESTS_ALL);
 543     if (node_summary == NULL) {
 544         data->rc = RSC_DIGEST_UNKNOWN;
 545         return data;
 546     }
 547 
 548     // Check whether full parameter digest matches
 549     if (unfencing_digest_matches(rsc->id, agent, data->digest_all_calc,
 550                                  node_summary)) {
 551         data->rc = RSC_DIGEST_MATCH;
 552         return data;
 553     }
 554 
 555     // Check whether secure parameter digest matches
 556     node_summary = pe_node_attribute_raw(node, CRM_ATTR_DIGESTS_SECURE);
 557     if (unfencing_digest_matches(rsc->id, agent, data->digest_secure_calc,
 558                                  node_summary)) {
 559         data->rc = RSC_DIGEST_MATCH;
 560         if (!pcmk__is_daemon && data_set->priv != NULL) {
 561             pcmk__output_t *out = data_set->priv;
 562             out->info(out, "Only 'private' parameters to %s "
 563                       "for unfencing %s changed", rsc->id,
 564                       pe__node_name(node));
 565         }
 566         return data;
 567     }
 568 
 569     // Parameters don't match
 570     data->rc = RSC_DIGEST_ALL;
 571     if (pcmk_is_set(data_set->flags, pe_flag_sanitized) && data->digest_secure_calc) {
 572         if (data_set->priv != NULL) {
 573             pcmk__output_t *out = data_set->priv;
 574             char *digest = create_unfencing_summary(rsc->id, agent,
 575                                                     data->digest_secure_calc);
 576 
 577             out->info(out, "Parameters to %s for unfencing "
 578                       "%s changed, try '%s'", rsc->id,
 579                       pe__node_name(node), digest);
 580             free(digest);
 581         } else if (!pcmk__is_daemon) {
 582             char *digest = create_unfencing_summary(rsc->id, agent,
 583                                                     data->digest_secure_calc);
 584 
 585             printf("Parameters to %s for unfencing %s changed, try '%s'\n",
 586                    rsc->id, pe__node_name(node), digest);
 587             free(digest);
 588         }
 589     }
 590     return data;
 591 }

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