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

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