root/lib/pengine/common.c

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

DEFINITIONS

This source file includes following definitions.
  1. check_health
  2. check_stonith_action
  3. check_placement_strategy
  4. pe_metadata
  5. verify_pe_options
  6. pe_pref
  7. fail2text
  8. text2task
  9. task2text
  10. role2text
  11. text2role
  12. merge_weights
  13. add_hash_param
  14. pe_node_attribute_calculated
  15. pe_node_attribute_raw

   1 /* 
   2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   3  * 
   4  * This library is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2.1 of the License, or (at your option) any later version.
   8  * 
   9  * This library is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  * 
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 #include <crm_internal.h>
  19 #include <crm/crm.h>
  20 #include <crm/msg_xml.h>
  21 #include <crm/common/xml.h>
  22 #include <crm/common/util.h>
  23 
  24 #include <glib.h>
  25 
  26 #include <crm/pengine/internal.h>
  27 
  28 gboolean was_processing_error = FALSE;
  29 gboolean was_processing_warning = FALSE;
  30 
  31 static gboolean
  32 check_health(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34     if (safe_str_eq(value, "none")) {
  35         return TRUE;
  36 
  37     } else if (safe_str_eq(value, "custom")) {
  38         return TRUE;
  39 
  40     } else if (safe_str_eq(value, "only-green")) {
  41         return TRUE;
  42 
  43     } else if (safe_str_eq(value, "progressive")) {
  44         return TRUE;
  45 
  46     } else if (safe_str_eq(value, "migrate-on-red")) {
  47         return TRUE;
  48     }
  49     return FALSE;
  50 }
  51 
  52 static gboolean
  53 check_stonith_action(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55     if (safe_str_eq(value, "reboot")) {
  56         return TRUE;
  57 
  58     } else if (safe_str_eq(value, "poweroff")) {
  59         return TRUE;
  60 
  61     } else if (safe_str_eq(value, "off")) {
  62         return TRUE;
  63     }
  64     return FALSE;
  65 }
  66 
  67 static gboolean
  68 check_placement_strategy(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70     if (safe_str_eq(value, "default")) {
  71         return TRUE;
  72 
  73     } else if (safe_str_eq(value, "utilization")) {
  74         return TRUE;
  75 
  76     } else if (safe_str_eq(value, "minimal")) {
  77         return TRUE;
  78 
  79     } else if (safe_str_eq(value, "balanced")) {
  80         return TRUE;
  81     }
  82     return FALSE;
  83 }
  84 
  85 /* *INDENT-OFF* */
  86 pe_cluster_option pe_opts[] = {
  87         /* name, old-name, validate, default, description */
  88         { "no-quorum-policy", "no_quorum_policy", "enum", "stop, freeze, ignore, suicide", "stop", &check_quorum,
  89           "What to do when the cluster does not have quorum", NULL },
  90         { "symmetric-cluster", "symmetric_cluster", "boolean", NULL, "true", &check_boolean,
  91           "All resources can run anywhere by default", NULL },
  92     { "default-resource-stickiness", "default_resource_stickiness", "integer",
  93       NULL, NULL, &check_number,
  94       "Deprecated (use resource-stickiness in rsc_defaults instead)", NULL },
  95     { "is-managed-default", "is_managed_default", "boolean", NULL, NULL,
  96       &check_boolean, "Deprecated (use is-managed in rsc_defaults instead)",
  97       NULL },
  98         { "maintenance-mode", NULL, "boolean", NULL, "false", &check_boolean,
  99           "Should the cluster monitor resources and start/stop them as required", NULL },
 100         { "start-failure-is-fatal", NULL, "boolean", NULL, "true", &check_boolean, "Always treat start failures as fatal",
 101           "When set to TRUE, the cluster will immediately ban a resource from a node if it fails to start there. When FALSE, the cluster will instead check the resource's fail count against its migration-threshold." },
 102         { "enable-startup-probes", NULL, "boolean", NULL, "true", &check_boolean,
 103           "Should the cluster check for active resources during startup", NULL },
 104 
 105         /* Stonith Options */
 106         { "stonith-enabled", "stonith_enabled", "boolean", NULL, "true", &check_boolean,
 107           "Failed nodes are STONITH'd", NULL },
 108         { "stonith-action", "stonith_action", "enum", "reboot, poweroff, off", "reboot", &check_stonith_action,
 109           "Action to send to STONITH device", NULL },
 110         { "stonith-timeout", NULL, "time", NULL, "60s", &check_timer,
 111           "How long to wait for the STONITH action (reboot,on,off) to complete", NULL },
 112         { XML_ATTR_HAVE_WATCHDOG, NULL, "boolean", NULL, "false", &check_boolean,
 113           "Enable watchdog integration", "Set automatically by the cluster if SBD is detected.  User configured values are ignored." },
 114         { "concurrent-fencing", NULL, "boolean", NULL, "false", &check_boolean,
 115           "Allow performing fencing operations in parallel", NULL },
 116         { "startup-fencing", "startup_fencing", "boolean", NULL, "true", &check_boolean,
 117           "STONITH unseen nodes", "Advanced Use Only!  Not using the default is very unsafe!" },
 118 
 119         /* Timeouts etc */
 120         { "cluster-delay", "transition_idle_timeout", "time", NULL, "60s", &check_time,
 121           "Round trip delay over the network (excluding action execution)",
 122           "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
 123         { "batch-limit", NULL, "integer", NULL, "0", &check_number,
 124           "The number of jobs that the TE is allowed to execute in parallel",
 125           "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
 126         { "migration-limit", NULL, "integer", NULL, "-1", &check_number,
 127           "The number of migration jobs that the TE is allowed to execute in parallel on a node"},
 128     { "default-action-timeout", "default_action_timeout", "time", NULL, NULL,
 129       &check_time, "Deprecated (use 'timeout' in op_defaults instead)", NULL },
 130 
 131         /* Orphans and stopping */
 132         { "stop-all-resources", NULL, "boolean", NULL, "false", &check_boolean,
 133           "Should the cluster stop all active resources (except those needed for fencing)", NULL },
 134         { "stop-orphan-resources", "stop_orphan_resources", "boolean", NULL, "true", &check_boolean,
 135           "Should deleted resources be stopped", NULL },
 136         { "stop-orphan-actions", "stop_orphan_actions", "boolean", NULL, "true", &check_boolean,
 137           "Should deleted actions be cancelled", NULL },
 138         { "remove-after-stop", "remove_after_stop", "boolean", NULL, "false", &check_boolean,
 139           "Remove resources from the LRM after they are stopped",
 140           "Always set this to false.  Other values are, at best, poorly tested and potentially dangerous." },
 141 /*      { "", "", , "0", "", NULL }, */
 142 
 143         /* Storing inputs */
 144         { "pe-error-series-max", NULL, "integer", NULL, "-1", &check_number,
 145           "The number of PE inputs resulting in ERRORs to save", "Zero to disable, -1 to store unlimited." },
 146         { "pe-warn-series-max",  NULL, "integer", NULL, "5000", &check_number,
 147           "The number of PE inputs resulting in WARNINGs to save", "Zero to disable, -1 to store unlimited." },
 148         { "pe-input-series-max", NULL, "integer", NULL, "4000", &check_number,
 149           "The number of other PE inputs to save", "Zero to disable, -1 to store unlimited." },
 150 
 151         /* Node health */
 152         { "node-health-strategy", NULL, "enum", "none, migrate-on-red, only-green, progressive, custom", "none", &check_health,
 153           "The strategy combining node attributes to determine overall node health.",
 154           "Requires external entities to create node attributes (named with the prefix '#health') with values: 'red', 'yellow' or 'green'."},
 155         { "node-health-base", NULL, "integer", NULL, "0", &check_number,
 156           "The base score assigned to a node",
 157           "Only used when node-health-strategy is set to progressive." },
 158         { "node-health-green", NULL, "integer", NULL, "0", &check_number,
 159           "The score 'green' translates to in rsc_location constraints",
 160           "Only used when node-health-strategy is set to custom or progressive." },
 161         { "node-health-yellow", NULL, "integer", NULL, "0", &check_number,
 162           "The score 'yellow' translates to in rsc_location constraints",
 163           "Only used when node-health-strategy is set to custom or progressive." },
 164         { "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number,
 165           "The score 'red' translates to in rsc_location constraints",
 166           "Only used when node-health-strategy is set to custom or progressive." },
 167 
 168         /*Placement Strategy*/
 169         { "placement-strategy", NULL, "enum", "default, utilization, minimal, balanced", "default", &check_placement_strategy,
 170           "The strategy to determine resource placement", NULL},
 171 };
 172 /* *INDENT-ON* */
 173 
 174 void
 175 pe_metadata(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177     config_metadata("Policy Engine", "1.0",
 178                     "Policy Engine Options",
 179                     "This is a fake resource that details the options that can be configured for the Policy Engine.",
 180                     pe_opts, DIMOF(pe_opts));
 181 }
 182 
 183 void
 184 verify_pe_options(GHashTable * options)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186     verify_all_options(options, pe_opts, DIMOF(pe_opts));
 187 }
 188 
 189 const char *
 190 pe_pref(GHashTable * options, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192     return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name);
 193 }
 194 
 195 const char *
 196 fail2text(enum action_fail_response fail)
     /* [previous][next][first][last][top][bottom][index][help] */
 197 {
 198     const char *result = "<unknown>";
 199 
 200     switch (fail) {
 201         case action_fail_ignore:
 202             result = "ignore";
 203             break;
 204         case action_fail_block:
 205             result = "block";
 206             break;
 207         case action_fail_recover:
 208             result = "recover";
 209             break;
 210         case action_fail_migrate:
 211             result = "migrate";
 212             break;
 213         case action_fail_stop:
 214             result = "stop";
 215             break;
 216         case action_fail_fence:
 217             result = "fence";
 218             break;
 219         case action_fail_standby:
 220             result = "standby";
 221             break;
 222         case action_fail_restart_container:
 223             result = "restart-container";
 224             break;
 225         case action_fail_reset_remote:
 226             result = "reset-remote";
 227             break;
 228     }
 229     return result;
 230 }
 231 
 232 enum action_tasks
 233 text2task(const char *task)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235     if (safe_str_eq(task, CRMD_ACTION_STOP)) {
 236         return stop_rsc;
 237     } else if (safe_str_eq(task, CRMD_ACTION_STOPPED)) {
 238         return stopped_rsc;
 239     } else if (safe_str_eq(task, CRMD_ACTION_START)) {
 240         return start_rsc;
 241     } else if (safe_str_eq(task, CRMD_ACTION_STARTED)) {
 242         return started_rsc;
 243     } else if (safe_str_eq(task, CRM_OP_SHUTDOWN)) {
 244         return shutdown_crm;
 245     } else if (safe_str_eq(task, CRM_OP_FENCE)) {
 246         return stonith_node;
 247     } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
 248         return monitor_rsc;
 249     } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) {
 250         return action_notify;
 251     } else if (safe_str_eq(task, CRMD_ACTION_NOTIFIED)) {
 252         return action_notified;
 253     } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
 254         return action_promote;
 255     } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
 256         return action_demote;
 257     } else if (safe_str_eq(task, CRMD_ACTION_PROMOTED)) {
 258         return action_promoted;
 259     } else if (safe_str_eq(task, CRMD_ACTION_DEMOTED)) {
 260         return action_demoted;
 261     }
 262 #if SUPPORT_TRACING
 263     if (safe_str_eq(task, CRMD_ACTION_CANCEL)) {
 264         return no_action;
 265     } else if (safe_str_eq(task, CRMD_ACTION_DELETE)) {
 266         return no_action;
 267     } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
 268         return no_action;
 269     } else if (safe_str_eq(task, CRM_OP_PROBED)) {
 270         return no_action;
 271     } else if (safe_str_eq(task, CRM_OP_LRM_REFRESH)) {
 272         return no_action;
 273     } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
 274         return no_action;
 275     } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
 276         return no_action;
 277     } else if (safe_str_eq(task, "fail")) {
 278         return no_action;
 279     } else if (safe_str_eq(task, "stonith_up")) {
 280         return no_action;
 281     } else if (safe_str_eq(task, "stonith_complete")) {
 282         return no_action;
 283     } else if (safe_str_eq(task, "all_stopped")) {
 284         return no_action;
 285     }
 286     crm_trace("Unsupported action: %s", task);
 287 #endif
 288 
 289     return no_action;
 290 }
 291 
 292 const char *
 293 task2text(enum action_tasks task)
     /* [previous][next][first][last][top][bottom][index][help] */
 294 {
 295     const char *result = "<unknown>";
 296 
 297     switch (task) {
 298         case no_action:
 299             result = "no_action";
 300             break;
 301         case stop_rsc:
 302             result = CRMD_ACTION_STOP;
 303             break;
 304         case stopped_rsc:
 305             result = CRMD_ACTION_STOPPED;
 306             break;
 307         case start_rsc:
 308             result = CRMD_ACTION_START;
 309             break;
 310         case started_rsc:
 311             result = CRMD_ACTION_STARTED;
 312             break;
 313         case shutdown_crm:
 314             result = CRM_OP_SHUTDOWN;
 315             break;
 316         case stonith_node:
 317             result = CRM_OP_FENCE;
 318             break;
 319         case monitor_rsc:
 320             result = CRMD_ACTION_STATUS;
 321             break;
 322         case action_notify:
 323             result = CRMD_ACTION_NOTIFY;
 324             break;
 325         case action_notified:
 326             result = CRMD_ACTION_NOTIFIED;
 327             break;
 328         case action_promote:
 329             result = CRMD_ACTION_PROMOTE;
 330             break;
 331         case action_promoted:
 332             result = CRMD_ACTION_PROMOTED;
 333             break;
 334         case action_demote:
 335             result = CRMD_ACTION_DEMOTE;
 336             break;
 337         case action_demoted:
 338             result = CRMD_ACTION_DEMOTED;
 339             break;
 340     }
 341 
 342     return result;
 343 }
 344 
 345 const char *
 346 role2text(enum rsc_role_e role)
     /* [previous][next][first][last][top][bottom][index][help] */
 347 {
 348     switch (role) {
 349         case RSC_ROLE_UNKNOWN:
 350             return RSC_ROLE_UNKNOWN_S;
 351         case RSC_ROLE_STOPPED:
 352             return RSC_ROLE_STOPPED_S;
 353         case RSC_ROLE_STARTED:
 354             return RSC_ROLE_STARTED_S;
 355         case RSC_ROLE_SLAVE:
 356             return RSC_ROLE_SLAVE_S;
 357         case RSC_ROLE_MASTER:
 358             return RSC_ROLE_MASTER_S;
 359     }
 360     CRM_CHECK(role >= RSC_ROLE_UNKNOWN, return RSC_ROLE_UNKNOWN_S);
 361     CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S);
 362     // coverity[dead_error_line]
 363     return RSC_ROLE_UNKNOWN_S;
 364 }
 365 
 366 enum rsc_role_e
 367 text2role(const char *role)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369     CRM_ASSERT(role != NULL);
 370     if (safe_str_eq(role, RSC_ROLE_STOPPED_S)) {
 371         return RSC_ROLE_STOPPED;
 372     } else if (safe_str_eq(role, RSC_ROLE_STARTED_S)) {
 373         return RSC_ROLE_STARTED;
 374     } else if (safe_str_eq(role, RSC_ROLE_SLAVE_S)) {
 375         return RSC_ROLE_SLAVE;
 376     } else if (safe_str_eq(role, RSC_ROLE_MASTER_S)) {
 377         return RSC_ROLE_MASTER;
 378     } else if (safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) {
 379         return RSC_ROLE_UNKNOWN;
 380     }
 381     crm_err("Unknown role: %s", role);
 382     return RSC_ROLE_UNKNOWN;
 383 }
 384 
 385 int
 386 merge_weights(int w1, int w2)
     /* [previous][next][first][last][top][bottom][index][help] */
 387 {
 388     int result = w1 + w2;
 389 
 390     if (w1 <= -INFINITY || w2 <= -INFINITY) {
 391         if (w1 >= INFINITY || w2 >= INFINITY) {
 392             crm_trace("-INFINITY + INFINITY == -INFINITY");
 393         }
 394         return -INFINITY;
 395 
 396     } else if (w1 >= INFINITY || w2 >= INFINITY) {
 397         return INFINITY;
 398     }
 399 
 400     /* detect wrap-around */
 401     if (result > 0) {
 402         if (w1 <= 0 && w2 < 0) {
 403             result = -INFINITY;
 404         }
 405 
 406     } else if (w1 > 0 && w2 > 0) {
 407         result = INFINITY;
 408     }
 409 
 410     /* detect +/- INFINITY */
 411     if (result >= INFINITY) {
 412         result = INFINITY;
 413 
 414     } else if (result <= -INFINITY) {
 415         result = -INFINITY;
 416     }
 417 
 418     crm_trace("%d + %d = %d", w1, w2, result);
 419     return result;
 420 }
 421 
 422 void
 423 add_hash_param(GHashTable * hash, const char *name, const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
 424 {
 425     CRM_CHECK(hash != NULL, return);
 426 
 427     crm_trace("adding: name=%s value=%s", crm_str(name), crm_str(value));
 428     if (name == NULL || value == NULL) {
 429         return;
 430 
 431     } else if (safe_str_eq(value, "#default")) {
 432         return;
 433 
 434     } else if (g_hash_table_lookup(hash, name) == NULL) {
 435         g_hash_table_insert(hash, strdup(name), strdup(value));
 436     }
 437 }
 438 
 439 const char *
 440 pe_node_attribute_calculated(pe_node_t *node, const char *name, resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442     const char *source;
 443 
 444     if(node == NULL) {
 445         return NULL;
 446 
 447     } else if(rsc == NULL) {
 448         return g_hash_table_lookup(node->details->attrs, name);
 449     }
 450 
 451     source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
 452     if(source == NULL || safe_str_eq("host", source) == FALSE) {
 453         return g_hash_table_lookup(node->details->attrs, name);
 454     }
 455 
 456     /* Use attributes set for the containers location
 457      * instead of for the container itself
 458      *
 459      * Useful when the container is using the host's local
 460      * storage
 461      */
 462 
 463     CRM_ASSERT(node->details->remote_rsc);
 464     CRM_ASSERT(node->details->remote_rsc->container);
 465 
 466     if(node->details->remote_rsc->container->running_on) {
 467         pe_node_t *host = node->details->remote_rsc->container->running_on->data;
 468         pe_rsc_trace(rsc, "%s: Looking for %s on the container host %s", rsc->id, name, host->details->uname);
 469         return g_hash_table_lookup(host->details->attrs, name);
 470     }
 471 
 472     pe_rsc_trace(rsc, "%s: Not looking for %s on the container host: %s is inactive",
 473                  rsc->id, name, node->details->remote_rsc->container->id);
 474     return NULL;
 475 }
 476 
 477 const char *
 478 pe_node_attribute_raw(pe_node_t *node, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480     if(node == NULL) {
 481         return NULL;
 482     }
 483     return g_hash_table_lookup(node->details->attrs, name);
 484 }

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