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

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