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         free_xml(data->params_all);
  39         free_xml(data->params_secure);
  40         free_xml(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->details->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 = calculate_operation_digest(data->params_all,
 165                                                        op_version);
 166 }
 167 
 168 // Return true if XML attribute name is a Pacemaker-defined fencing parameter
 169 static bool
 170 is_fence_param(xmlAttrPtr attr, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172     return pcmk_stonith_param((const char *) attr->name);
 173 }
 174 
 175 /*!
 176  * \internal
 177  * \brief Add secure digest to a digest cache entry
 178  *
 179  * \param[out] data        Digest cache entry to modify
 180  * \param[in]  rsc         Resource that action was for
 181  * \param[in]  params      Resource parameters evaluated for node
 182  * \param[in]  xml_op      XML of operation in CIB status (if available)
 183  * \param[in]  op_version  CRM feature set to use for digest calculation
 184  * \param[in]  overrides   Key/value hash table to override resource parameters
 185  */
 186 static void
 187 calculate_secure_digest(pcmk__op_digest_t *data, const pcmk_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 188                         GHashTable *params, const xmlNode *xml_op,
 189                         const char *op_version, GHashTable *overrides)
 190 {
 191     const char *class = crm_element_value(rsc->xml, PCMK_XA_CLASS);
 192     const char *secure_list = NULL;
 193     bool old_version = (compare_version(op_version, "3.16.0") < 0);
 194 
 195     if (xml_op == NULL) {
 196         secure_list = " passwd password user ";
 197     } else {
 198         secure_list = crm_element_value(xml_op, PCMK__XA_OP_SECURE_PARAMS);
 199     }
 200 
 201     if (old_version) {
 202         data->params_secure = pcmk__xe_create(NULL, PCMK_XE_PARAMETERS);
 203         if (overrides != NULL) {
 204             g_hash_table_foreach(overrides, hash2field, data->params_secure);
 205         }
 206 
 207         g_hash_table_foreach(params, hash2field, data->params_secure);
 208 
 209     } else {
 210         // Start with a copy of all parameters
 211         data->params_secure = pcmk__xml_copy(NULL, data->params_all);
 212     }
 213 
 214     if (secure_list != NULL) {
 215         pcmk__xe_remove_matching_attrs(data->params_secure, attr_in_string,
 216                                        (void *) secure_list);
 217     }
 218     if (old_version
 219         && pcmk_is_set(pcmk_get_ra_caps(class),
 220                        pcmk_ra_cap_fence_params)) {
 221         /* For stonith resources, Pacemaker adds special parameters,
 222          * but these are not listed in fence agent meta-data, so with older
 223          * versions of DC, the controller will not hash them. That means we have
 224          * to filter them out before calculating our hash for comparison.
 225          */
 226         pcmk__xe_remove_matching_attrs(data->params_secure, is_fence_param,
 227                                        NULL);
 228     }
 229     pcmk__filter_op_for_digest(data->params_secure);
 230 
 231     /* CRM_meta_timeout *should* be part of a digest for recurring operations.
 232      * However, with older versions of DC, the controller does not add timeout
 233      * to secure digests, because it only includes parameters declared by the
 234      * resource agent.
 235      * Remove any timeout that made it this far, to match.
 236      */
 237     if (old_version) {
 238         pcmk__xe_remove_attr(data->params_secure,
 239                              CRM_META "_" PCMK_META_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(pcmk__op_digest_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, PCMK__XA_OP_RESTART_DIGEST) == NULL) {
 270         return;
 271     }
 272 
 273     // Start with a copy of all parameters
 274     data->params_restart = pcmk__xml_copy(NULL, data->params_all);
 275 
 276     // Then filter out reloadable parameters, if any
 277     value = crm_element_value(xml_op, PCMK__XA_OP_FORCE_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, PCMK_XA_CRM_FEATURE_SET);
 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 pcmk__op_digest_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     pcmk__op_digest_t *data = NULL;
 312     const char *op_version = NULL;
 313     GHashTable *params = NULL;
 314 
 315     CRM_CHECK(scheduler != NULL, return NULL);
 316 
 317     data = calloc(1, sizeof(pcmk__op_digest_t));
 318     if (data == NULL) {
 319         pcmk__sched_err("Could not allocate memory for operation digest");
 320         return NULL;
 321     }
 322 
 323     data->rc = pcmk__digest_match;
 324 
 325     if (xml_op != NULL) {
 326         op_version = crm_element_value(xml_op, PCMK_XA_CRM_FEATURE_SET);
 327     }
 328 
 329     if ((op_version == NULL) && (scheduler->input != NULL)) {
 330         op_version = crm_element_value(scheduler->input,
 331                                        PCMK_XA_CRM_FEATURE_SET);
 332     }
 333 
 334     if (op_version == NULL) {
 335         op_version = CRM_FEATURE_SET;
 336     }
 337 
 338     params = pe_rsc_params(rsc, node, scheduler);
 339     calculate_main_digest(data, rsc, node, params, task, interval_ms, xml_op,
 340                           op_version, overrides, scheduler);
 341     if (calc_secure) {
 342         calculate_secure_digest(data, rsc, params, xml_op, op_version,
 343                                 overrides);
 344     }
 345     calculate_restart_digest(data, xml_op, op_version);
 346     return data;
 347 }
 348 
 349 /*!
 350  * \internal
 351  * \brief Calculate action digests and store in node's digest cache
 352  *
 353  * \param[in,out] rsc          Resource that action was for
 354  * \param[in]     task         Name of action performed
 355  * \param[in]     interval_ms  Action's interval
 356  * \param[in,out] node         Node action was performed on
 357  * \param[in]     xml_op       XML of operation in CIB status (if available)
 358  * \param[in]     calc_secure  Whether to calculate secure digest
 359  * \param[in,out] scheduler    Scheduler data
 360  *
 361  * \return Pointer to node's digest cache entry
 362  */
 363 static pcmk__op_digest_t *
 364 rsc_action_digest(pcmk_resource_t *rsc, const char *task, guint interval_ms,
     /* [previous][next][first][last][top][bottom][index][help] */
 365                   pcmk_node_t *node, const xmlNode *xml_op,
 366                   bool calc_secure, pcmk_scheduler_t *scheduler)
 367 {
 368     pcmk__op_digest_t *data = NULL;
 369     char *key = pcmk__op_key(rsc->id, task, interval_ms);
 370 
 371     data = g_hash_table_lookup(node->details->digest_cache, key);
 372     if (data == NULL) {
 373         data = pe__calculate_digests(rsc, task, &interval_ms, node, xml_op,
 374                                      NULL, calc_secure, scheduler);
 375         CRM_ASSERT(data != NULL);
 376         g_hash_table_insert(node->details->digest_cache, strdup(key), data);
 377     }
 378     free(key);
 379     return data;
 380 }
 381 
 382 /*!
 383  * \internal
 384  * \brief Calculate operation digests and compare against an XML history entry
 385  *
 386  * \param[in,out] rsc        Resource to check
 387  * \param[in]     xml_op     Resource history XML
 388  * \param[in,out] node       Node to use for digest calculation
 389  * \param[in,out] scheduler  Scheduler data
 390  *
 391  * \return Pointer to node's digest cache entry, with comparison result set
 392  */
 393 pcmk__op_digest_t *
 394 rsc_action_digest_cmp(pcmk_resource_t *rsc, const xmlNode *xml_op,
     /* [previous][next][first][last][top][bottom][index][help] */
 395                       pcmk_node_t *node, pcmk_scheduler_t *scheduler)
 396 {
 397     pcmk__op_digest_t *data = NULL;
 398     guint interval_ms = 0;
 399 
 400     const char *op_version;
 401     const char *task = crm_element_value(xml_op, PCMK_XA_OPERATION);
 402     const char *digest_all;
 403     const char *digest_restart;
 404 
 405     CRM_ASSERT(node != NULL);
 406 
 407     op_version = crm_element_value(xml_op, PCMK_XA_CRM_FEATURE_SET);
 408     digest_all = crm_element_value(xml_op, PCMK__XA_OP_DIGEST);
 409     digest_restart = crm_element_value(xml_op, PCMK__XA_OP_RESTART_DIGEST);
 410 
 411     crm_element_value_ms(xml_op, PCMK_META_INTERVAL, &interval_ms);
 412     data = rsc_action_digest(rsc, task, interval_ms, node, xml_op,
 413                              pcmk_is_set(scheduler->flags,
 414                                          pcmk_sched_sanitized),
 415                              scheduler);
 416 
 417     if (digest_restart && data->digest_restart_calc && strcmp(data->digest_restart_calc, digest_restart) != 0) {
 418         pcmk__rsc_info(rsc,
 419                        "Parameters to %ums-interval %s action for %s on %s "
 420                        "changed: hash was %s vs. now %s (restart:%s) %s",
 421                        interval_ms, task, rsc->id, pcmk__node_name(node),
 422                        pcmk__s(digest_restart, "missing"),
 423                        data->digest_restart_calc, op_version,
 424                        crm_element_value(xml_op, PCMK__XA_TRANSITION_MAGIC));
 425         data->rc = pcmk__digest_restart;
 426 
 427     } else if (digest_all == NULL) {
 428         /* it is unknown what the previous op digest was */
 429         data->rc = pcmk__digest_unknown;
 430 
 431     } else if (strcmp(digest_all, data->digest_all_calc) != 0) {
 432         /* Given a non-recurring operation with extra parameters configured,
 433          * in case that the main digest doesn't match, even if the restart
 434          * digest matches, enforce a restart rather than a reload-agent anyway.
 435          * So that it ensures any changes of the extra parameters get applied
 436          * for this specific operation, and the digests calculated for the
 437          * resulting PCMK__XE_LRM_RSC_OP will be correct.
 438          * Preserve the implied rc pcmk__digest_restart for the case that the
 439          * main digest doesn't match.
 440          */
 441         if ((interval_ms == 0) && (data->rc == pcmk__digest_restart)) {
 442             pcmk__rsc_info(rsc,
 443                            "Parameters containing extra ones to %ums-interval"
 444                            " %s action for %s on %s "
 445                            "changed: hash was %s vs. now %s (restart:%s) %s",
 446                            interval_ms, task, rsc->id, pcmk__node_name(node),
 447                            pcmk__s(digest_all, "missing"),
 448                            data->digest_all_calc, op_version,
 449                            crm_element_value(xml_op,
 450                                              PCMK__XA_TRANSITION_MAGIC));
 451 
 452         } else {
 453             pcmk__rsc_info(rsc,
 454                            "Parameters to %ums-interval %s action for %s on %s "
 455                            "changed: hash was %s vs. now %s (%s:%s) %s",
 456                            interval_ms, task, rsc->id, pcmk__node_name(node),
 457                            pcmk__s(digest_all, "missing"),
 458                            data->digest_all_calc,
 459                            (interval_ms > 0)? "reschedule" : "reload",
 460                            op_version,
 461                            crm_element_value(xml_op,
 462                                              PCMK__XA_TRANSITION_MAGIC));
 463             data->rc = pcmk__digest_mismatch;
 464         }
 465 
 466     } else {
 467         data->rc = pcmk__digest_match;
 468     }
 469     return data;
 470 }
 471 
 472 /*!
 473  * \internal
 474  * \brief Create an unfencing summary for use in special node attribute
 475  *
 476  * Create a string combining a fence device's resource ID, agent type, and
 477  * parameter digest (whether for all parameters or just non-private parameters).
 478  * This can be stored in a special node attribute, allowing us to detect changes
 479  * in either the agent type or parameters, to know whether unfencing must be
 480  * redone or can be safely skipped when the device's history is cleaned.
 481  *
 482  * \param[in] rsc_id        Fence device resource ID
 483  * \param[in] agent_type    Fence device agent
 484  * \param[in] param_digest  Fence device parameter digest
 485  *
 486  * \return Newly allocated string with unfencing digest
 487  * \note The caller is responsible for freeing the result.
 488  */
 489 static inline char *
 490 create_unfencing_summary(const char *rsc_id, const char *agent_type,
     /* [previous][next][first][last][top][bottom][index][help] */
 491                          const char *param_digest)
 492 {
 493     return crm_strdup_printf("%s:%s:%s", rsc_id, agent_type, param_digest);
 494 }
 495 
 496 /*!
 497  * \internal
 498  * \brief Check whether a node can skip unfencing
 499  *
 500  * Check whether a fence device's current definition matches a node's
 501  * stored summary of when it was last unfenced by the device.
 502  *
 503  * \param[in] rsc_id        Fence device's resource ID
 504  * \param[in] agent         Fence device's agent type
 505  * \param[in] digest_calc   Fence device's current parameter digest
 506  * \param[in] node_summary  Value of node's special unfencing node attribute
 507  *                          (a comma-separated list of unfencing summaries for
 508  *                          all devices that have unfenced this node)
 509  *
 510  * \return TRUE if digest matches, FALSE otherwise
 511  */
 512 static bool
 513 unfencing_digest_matches(const char *rsc_id, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 514                          const char *digest_calc, const char *node_summary)
 515 {
 516     bool matches = FALSE;
 517 
 518     if (rsc_id && agent && digest_calc && node_summary) {
 519         char *search_secure = create_unfencing_summary(rsc_id, agent,
 520                                                        digest_calc);
 521 
 522         /* The digest was calculated including the device ID and agent,
 523          * so there is no risk of collision using strstr().
 524          */
 525         matches = (strstr(node_summary, search_secure) != NULL);
 526         crm_trace("Calculated unfencing digest '%s' %sfound in '%s'",
 527                   search_secure, matches? "" : "not ", node_summary);
 528         free(search_secure);
 529     }
 530     return matches;
 531 }
 532 
 533 /* Magic string to use as action name for digest cache entries used for
 534  * unfencing checks. This is not a real action name (i.e. "on"), so
 535  * pcmk__check_action_config() won't confuse these entries with real actions.
 536  */
 537 #define STONITH_DIGEST_TASK "stonith-on"
 538 
 539 /*!
 540  * \internal
 541  * \brief Calculate fence device digests and digest comparison result
 542  *
 543  * \param[in,out] rsc        Fence device resource
 544  * \param[in]     agent      Fence device's agent type
 545  * \param[in,out] node       Node with digest cache to use
 546  * \param[in,out] scheduler  Scheduler data
 547  *
 548  * \return Node's digest cache entry
 549  */
 550 pcmk__op_digest_t *
 551 pe__compare_fencing_digest(pcmk_resource_t *rsc, const char *agent,
     /* [previous][next][first][last][top][bottom][index][help] */
 552                            pcmk_node_t *node, pcmk_scheduler_t *scheduler)
 553 {
 554     const char *node_summary = NULL;
 555 
 556     // Calculate device's current parameter digests
 557     pcmk__op_digest_t *data = rsc_action_digest(rsc, STONITH_DIGEST_TASK, 0U,
 558                                                 node, NULL, TRUE, scheduler);
 559 
 560     // Check whether node has special unfencing summary node attribute
 561     node_summary = pcmk__node_attr(node, CRM_ATTR_DIGESTS_ALL, NULL,
 562                                    pcmk__rsc_node_current);
 563     if (node_summary == NULL) {
 564         data->rc = pcmk__digest_unknown;
 565         return data;
 566     }
 567 
 568     // Check whether full parameter digest matches
 569     if (unfencing_digest_matches(rsc->id, agent, data->digest_all_calc,
 570                                  node_summary)) {
 571         data->rc = pcmk__digest_match;
 572         return data;
 573     }
 574 
 575     // Check whether secure parameter digest matches
 576     node_summary = pcmk__node_attr(node, CRM_ATTR_DIGESTS_SECURE, NULL,
 577                                    pcmk__rsc_node_current);
 578     if (unfencing_digest_matches(rsc->id, agent, data->digest_secure_calc,
 579                                  node_summary)) {
 580         data->rc = pcmk__digest_match;
 581         if (!pcmk__is_daemon && scheduler->priv != NULL) {
 582             pcmk__output_t *out = scheduler->priv;
 583             out->info(out, "Only 'private' parameters to %s "
 584                       "for unfencing %s changed", rsc->id,
 585                       pcmk__node_name(node));
 586         }
 587         return data;
 588     }
 589 
 590     // Parameters don't match
 591     data->rc = pcmk__digest_mismatch;
 592     if (pcmk_is_set(scheduler->flags, pcmk_sched_sanitized)
 593         && (data->digest_secure_calc != NULL)) {
 594 
 595         if (scheduler->priv != NULL) {
 596             pcmk__output_t *out = scheduler->priv;
 597             char *digest = create_unfencing_summary(rsc->id, agent,
 598                                                     data->digest_secure_calc);
 599 
 600             out->info(out, "Parameters to %s for unfencing "
 601                       "%s changed, try '%s'", rsc->id,
 602                       pcmk__node_name(node), digest);
 603             free(digest);
 604         } else if (!pcmk__is_daemon) {
 605             char *digest = create_unfencing_summary(rsc->id, agent,
 606                                                     data->digest_secure_calc);
 607 
 608             printf("Parameters to %s for unfencing %s changed, try '%s'\n",
 609                    rsc->id, pcmk__node_name(node), digest);
 610             free(digest);
 611         }
 612     }
 613     return data;
 614 }

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