root/lib/pengine/native.c

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

DEFINITIONS

This source file includes following definitions.
  1. native_add_running
  2. native_unpack
  3. rsc_is_on_node
  4. native_find_rsc
  5. native_parameter
  6. native_active
  7. native_print_attr
  8. native_pending_state
  9. native_pending_task
  10. native_displayable_role
  11. native_displayable_state
  12. native_print_xml
  13. comma_if
  14. common_print
  15. native_print
  16. native_free
  17. native_resource_state
  18. native_location
  19. get_rscs_brief
  20. destroy_node_table
  21. print_rscs_brief

   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 
  19 #include <crm_internal.h>
  20 
  21 #include <crm/pengine/rules.h>
  22 #include <crm/pengine/status.h>
  23 #include <crm/pengine/complex.h>
  24 #include <crm/pengine/internal.h>
  25 #include <unpack.h>
  26 #include <crm/msg_xml.h>
  27 
  28 #define VARIANT_NATIVE 1
  29 #include "./variant.h"
  30 
  31 void
  32 native_add_running(resource_t * rsc, node_t * node, pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34     GListPtr gIter = rsc->running_on;
  35 
  36     CRM_CHECK(node != NULL, return);
  37     for (; gIter != NULL; gIter = gIter->next) {
  38         node_t *a_node = (node_t *) gIter->data;
  39 
  40         CRM_CHECK(a_node != NULL, return);
  41         if (safe_str_eq(a_node->details->id, node->details->id)) {
  42             return;
  43         }
  44     }
  45 
  46     pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname,
  47                  is_set(rsc->flags, pe_rsc_managed)?"":"(unmanaged)");
  48 
  49     rsc->running_on = g_list_append(rsc->running_on, node);
  50     if (rsc->variant == pe_native) {
  51         node->details->running_rsc = g_list_append(node->details->running_rsc, rsc);
  52     }
  53 
  54     if (rsc->variant == pe_native && node->details->maintenance) {
  55         clear_bit(rsc->flags, pe_rsc_managed);
  56     }
  57 
  58     if (is_not_set(rsc->flags, pe_rsc_managed)) {
  59         resource_t *p = rsc->parent;
  60 
  61         pe_rsc_info(rsc, "resource %s isn't managed", rsc->id);
  62         resource_location(rsc, node, INFINITY, "not_managed_default", data_set);
  63 
  64         while(p && node->details->online) {
  65             /* add without the additional location constraint */
  66             p->running_on = g_list_append(p->running_on, node);
  67             p = p->parent;
  68         }
  69         return;
  70     }
  71 
  72     if (rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) {
  73         switch (rsc->recovery_type) {
  74             case recovery_stop_only:
  75                 {
  76                     GHashTableIter gIter;
  77                     node_t *local_node = NULL;
  78 
  79                     /* make sure it doesn't come up again */
  80                     g_hash_table_destroy(rsc->allowed_nodes);
  81                     rsc->allowed_nodes = node_hash_from_list(data_set->nodes);
  82                     g_hash_table_iter_init(&gIter, rsc->allowed_nodes);
  83                     while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) {
  84                         local_node->weight = -INFINITY;
  85                     }
  86                 }
  87                 break;
  88             case recovery_stop_start:
  89                 break;
  90             case recovery_block:
  91                 clear_bit(rsc->flags, pe_rsc_managed);
  92                 set_bit(rsc->flags, pe_rsc_block);
  93 
  94                 /* If the resource belongs to a group or bundle configured with
  95                  * multiple-active=block, block the entire entity.
  96                  */
  97                 if (rsc->parent
  98                     && (rsc->parent->variant == pe_group || rsc->parent->variant == pe_container)
  99                     && rsc->parent->recovery_type == recovery_block) {
 100                     GListPtr gIter = rsc->parent->children;
 101 
 102                     for (; gIter != NULL; gIter = gIter->next) {
 103                         resource_t *child = (resource_t *) gIter->data;
 104 
 105                         clear_bit(child->flags, pe_rsc_managed);
 106                         set_bit(child->flags, pe_rsc_block);
 107                     }
 108                 }
 109                 break;
 110         }
 111         crm_debug("%s is active on %d nodes including %s: %s",
 112                   rsc->id, g_list_length(rsc->running_on), node->details->uname,
 113                   recovery2text(rsc->recovery_type));
 114 
 115     } else {
 116         pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname);
 117     }
 118 
 119     if (rsc->parent != NULL) {
 120         native_add_running(rsc->parent, node, data_set);
 121     }
 122 }
 123 
 124 extern void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set);
 125 
 126 gboolean
 127 native_unpack(resource_t * rsc, pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129     resource_t *parent = uber_parent(rsc);
 130     native_variant_data_t *native_data = NULL;
 131     const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 132 
 133     pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
 134 
 135     native_data = calloc(1, sizeof(native_variant_data_t));
 136     rsc->variant_opaque = native_data;
 137 
 138     if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) {
 139 
 140         if (safe_str_eq(class, PCMK_RESOURCE_CLASS_LSB)) {
 141             resource_t *top = uber_parent(rsc);
 142 
 143             force_non_unique_clone(top, rsc->id, data_set);
 144         }
 145     }
 146 
 147     if (safe_str_eq(class, PCMK_RESOURCE_CLASS_OCF) == FALSE) {
 148         const char *stateful = g_hash_table_lookup(parent->meta, "stateful");
 149 
 150         if (safe_str_eq(stateful, XML_BOOLEAN_TRUE)) {
 151             pe_err
 152                 ("Resource %s is of type %s and therefore cannot be used as a master/slave resource",
 153                  rsc->id, class);
 154             return FALSE;
 155         }
 156     }
 157 
 158     return TRUE;
 159 }
 160 
 161 static bool
 162 rsc_is_on_node(resource_t *rsc, node_t *node, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 163 {
 164     pe_rsc_trace(rsc, "Checking whether %s is on %s",
 165                  rsc->id, node->details->uname);
 166 
 167     if (is_set(flags, pe_find_current) && rsc->running_on) {
 168 
 169         for (GListPtr iter = rsc->running_on; iter; iter = iter->next) {
 170             node_t *loc = (node_t *) iter->data;
 171 
 172             if (loc->details == node->details) {
 173                 return TRUE;
 174             }
 175         }
 176 
 177     } else if (is_set(flags, pe_find_inactive) && (rsc->running_on == NULL)) {
 178         return TRUE;
 179 
 180     } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to
 181                && (rsc->allocated_to->details == node->details)) {
 182         return TRUE;
 183     }
 184     return FALSE;
 185 }
 186 
 187 resource_t *
 188 native_find_rsc(resource_t * rsc, const char *id, node_t * on_node, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190     bool match = FALSE;
 191     resource_t *result = NULL;
 192 
 193     CRM_CHECK(id && rsc && rsc->id, return NULL);
 194 
 195     if (flags & pe_find_clone) {
 196         const char *rid = ID(rsc->xml);
 197 
 198         if (!pe_rsc_is_clone(uber_parent(rsc))) {
 199             match = FALSE;
 200 
 201         } else if (!strcmp(id, rsc->id) || safe_str_eq(id, rid)) {
 202             match = TRUE;
 203         }
 204 
 205     } else if (!strcmp(id, rsc->id)) {
 206         match = TRUE;
 207 
 208     } else if (is_set(flags, pe_find_renamed)
 209                && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
 210         match = TRUE;
 211 
 212     } else if (is_set(flags, pe_find_any)
 213                || (is_set(flags, pe_find_anon)
 214                    && is_not_set(rsc->flags, pe_rsc_unique))) {
 215         match = pe_base_name_eq(rsc, id);
 216     }
 217 
 218     if (match && on_node) {
 219         bool match_node = rsc_is_on_node(rsc, on_node, flags);
 220 
 221         if (match_node == FALSE) {
 222             match = FALSE;
 223         }
 224     }
 225 
 226     if (match) {
 227         return rsc;
 228     }
 229 
 230     for (GListPtr gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
 231         resource_t *child = (resource_t *) gIter->data;
 232 
 233         result = rsc->fns->find_rsc(child, id, on_node, flags);
 234         if (result) {
 235             return result;
 236         }
 237     }
 238     return NULL;
 239 }
 240 
 241 char *
 242 native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name,
     /* [previous][next][first][last][top][bottom][index][help] */
 243                  pe_working_set_t * data_set)
 244 {
 245     char *value_copy = NULL;
 246     const char *value = NULL;
 247     GHashTable *hash = rsc->parameters;
 248     GHashTable *local_hash = NULL;
 249 
 250     CRM_CHECK(rsc != NULL, return NULL);
 251     CRM_CHECK(name != NULL && strlen(name) != 0, return NULL);
 252 
 253     pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id);
 254 
 255     if (create || g_hash_table_size(rsc->parameters) == 0) {
 256         if (node != NULL) {
 257             pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname);
 258         } else {
 259             pe_rsc_trace(rsc, "Creating default hash");
 260         }
 261 
 262         local_hash = crm_str_table_new();
 263 
 264         get_rsc_attributes(local_hash, rsc, node, data_set);
 265 
 266         hash = local_hash;
 267     }
 268 
 269     value = g_hash_table_lookup(hash, name);
 270     if (value == NULL) {
 271         /* try meta attributes instead */
 272         value = g_hash_table_lookup(rsc->meta, name);
 273     }
 274 
 275     if (value != NULL) {
 276         value_copy = strdup(value);
 277     }
 278     if (local_hash != NULL) {
 279         g_hash_table_destroy(local_hash);
 280     }
 281     return value_copy;
 282 }
 283 
 284 gboolean
 285 native_active(resource_t * rsc, gboolean all)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287     GListPtr gIter = rsc->running_on;
 288 
 289     for (; gIter != NULL; gIter = gIter->next) {
 290         node_t *a_node = (node_t *) gIter->data;
 291 
 292         if (a_node->details->unclean) {
 293             crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname);
 294             return TRUE;
 295         } else if (a_node->details->online == FALSE) {
 296             crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname);
 297         } else {
 298             crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname);
 299             return TRUE;
 300         }
 301     }
 302 
 303     return FALSE;
 304 }
 305 
 306 struct print_data_s {
 307     long options;
 308     void *print_data;
 309 };
 310 
 311 static void
 312 native_print_attr(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 313 {
 314     long options = ((struct print_data_s *)user_data)->options;
 315     void *print_data = ((struct print_data_s *)user_data)->print_data;
 316 
 317     status_print("Option: %s = %s\n", (char *)key, (char *)value);
 318 }
 319 
 320 static const char *
 321 native_pending_state(resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 322 {
 323     const char *pending_state = NULL;
 324 
 325     if (safe_str_eq(rsc->pending_task, CRMD_ACTION_START)) {
 326         pending_state = "Starting";
 327 
 328     } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STOP)) {
 329         pending_state = "Stopping";
 330 
 331     } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE)) {
 332         pending_state = "Migrating";
 333 
 334     } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED)) {
 335        /* Work might be done in here. */
 336         pending_state = "Migrating";
 337 
 338     } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE)) {
 339         pending_state = "Promoting";
 340 
 341     } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE)) {
 342         pending_state = "Demoting";
 343     }
 344 
 345     return pending_state;
 346 }
 347 
 348 static const char *
 349 native_pending_task(resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351     const char *pending_task = NULL;
 352 
 353     if (safe_str_eq(rsc->pending_task, CRMD_ACTION_NOTIFY)) {
 354         /* "Notifying" is not very useful to be shown. */
 355         pending_task = NULL;
 356 
 357     } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STATUS)) {
 358         pending_task = "Monitoring";
 359 
 360     /* Pending probes are not printed, even if pending
 361      * operations are requested. If someone ever requests that
 362      * behavior, uncomment this and the corresponding part of
 363      * unpack.c:unpack_rsc_op().
 364      */
 365     /*
 366     } else if (safe_str_eq(rsc->pending_task, "probe")) {
 367         pending_task = "Checking";
 368     */
 369     }
 370 
 371     return pending_task;
 372 }
 373 
 374 static enum rsc_role_e
 375 native_displayable_role(resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 376 {
 377     enum rsc_role_e role = rsc->role;
 378 
 379     if ((role == RSC_ROLE_STARTED)
 380         && (uber_parent(rsc)->variant == pe_master)) {
 381 
 382         role = RSC_ROLE_SLAVE;
 383     }
 384     return role;
 385 }
 386 
 387 static const char *
 388 native_displayable_state(resource_t *rsc, long options)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390     const char *rsc_state = NULL;
 391 
 392     if (options & pe_print_pending) {
 393         rsc_state = native_pending_state(rsc);
 394     }
 395     if (rsc_state == NULL) {
 396         rsc_state = role2text(native_displayable_role(rsc));
 397     }
 398     return rsc_state;
 399 }
 400 
 401 static void
 402 native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 403 {
 404     const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 405     const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
 406     const char *rsc_state = native_displayable_state(rsc, options);
 407     const char *target_role = NULL;
 408 
 409     /* resource information. */
 410     status_print("%s<resource ", pre_text);
 411     status_print("id=\"%s\" ", rsc_printable_id(rsc));
 412     status_print("resource_agent=\"%s%s%s:%s\" ",
 413                  class,
 414                  prov ? "::" : "", prov ? prov : "", crm_element_value(rsc->xml, XML_ATTR_TYPE));
 415 
 416     status_print("role=\"%s\" ", rsc_state);
 417     if (rsc->meta) {
 418         target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
 419     }
 420     if (target_role) {
 421         status_print("target_role=\"%s\" ", target_role);
 422     }
 423     status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false");
 424     status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false");
 425     status_print("blocked=\"%s\" ", is_set(rsc->flags, pe_rsc_block) ? "true" : "false");
 426     status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false");
 427     status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false");
 428     status_print("failure_ignored=\"%s\" ",
 429                  is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false");
 430     status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on));
 431 
 432     if (options & pe_print_pending) {
 433         const char *pending_task = native_pending_task(rsc);
 434 
 435         if (pending_task) {
 436             status_print("pending=\"%s\" ", pending_task);
 437         }
 438     }
 439 
 440     if (options & pe_print_dev) {
 441         status_print("provisional=\"%s\" ",
 442                      is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false");
 443         status_print("runnable=\"%s\" ", is_set(rsc->flags, pe_rsc_runnable) ? "true" : "false");
 444         status_print("priority=\"%f\" ", (double)rsc->priority);
 445         status_print("variant=\"%s\" ", crm_element_name(rsc->xml));
 446     }
 447 
 448     /* print out the nodes this resource is running on */
 449     if (options & pe_print_rsconly) {
 450         status_print("/>\n");
 451         /* do nothing */
 452     } else if (g_list_length(rsc->running_on) > 0) {
 453         GListPtr gIter = rsc->running_on;
 454 
 455         status_print(">\n");
 456         for (; gIter != NULL; gIter = gIter->next) {
 457             node_t *node = (node_t *) gIter->data;
 458 
 459             status_print("%s    <node name=\"%s\" id=\"%s\" cached=\"%s\"/>\n", pre_text,
 460                          node->details->uname, node->details->id,
 461                          node->details->online ? "false" : "true");
 462         }
 463         status_print("%s</resource>\n", pre_text);
 464     } else {
 465         status_print("/>\n");
 466     }
 467 }
 468 
 469 /* making this inline rather than a macro prevents a coverity "unreachable"
 470  * warning on the first usage
 471  */
 472 static inline const char *
 473 comma_if(int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 474 {
 475     return i? ", " : "";
 476 }
 477 
 478 void
 479 common_print(resource_t * rsc, const char *pre_text, const char *name, node_t *node, long options, void *print_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 480 {
 481     const char *desc = NULL;
 482     const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 483     const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
 484     const char *target_role = NULL;
 485     enum rsc_role_e role = native_displayable_role(rsc);
 486 
 487     int offset = 0;
 488     int flagOffset = 0;
 489     char buffer[LINE_MAX];
 490     char flagBuffer[LINE_MAX];
 491 
 492     CRM_ASSERT(rsc->variant == pe_native);
 493     CRM_ASSERT(kind != NULL);
 494 
 495     if (rsc->meta) {
 496         const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC);
 497         if (crm_is_true(is_internal) && is_not_set(options, pe_print_implicit)) {
 498             crm_trace("skipping print of internal resource %s", rsc->id);
 499             return;
 500         }
 501         target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
 502     }
 503 
 504     if (pre_text == NULL && (options & pe_print_printf)) {
 505         pre_text = " ";
 506     }
 507 
 508     if (options & pe_print_xml) {
 509         native_print_xml(rsc, pre_text, options, print_data);
 510         return;
 511     }
 512 
 513     if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
 514         node = NULL;
 515     }
 516 
 517     if (options & pe_print_html) {
 518         if (is_not_set(rsc->flags, pe_rsc_managed)) {
 519             status_print("<font color=\"yellow\">");
 520 
 521         } else if (is_set(rsc->flags, pe_rsc_failed)) {
 522             status_print("<font color=\"red\">");
 523 
 524         } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) {
 525             status_print("<font color=\"red\">");
 526 
 527         } else if (g_list_length(rsc->running_on) > 1) {
 528             status_print("<font color=\"orange\">");
 529 
 530         } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) {
 531             status_print("<font color=\"yellow\">");
 532 
 533         } else {
 534             status_print("<font color=\"green\">");
 535         }
 536     }
 537 
 538     if(pre_text) {
 539         offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text);
 540     }
 541     offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", name);
 542     offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class);
 543     if (crm_provider_required(class)) {
 544         const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
 545         offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
 546     }
 547     offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind);
 548     if(is_set(rsc->flags, pe_rsc_orphan)) {
 549         offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
 550     }
 551     if(role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
 552         offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(role));
 553     } else if(is_set(rsc->flags, pe_rsc_failed)) {
 554         offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
 555     } else {
 556         const char *rsc_state = native_displayable_state(rsc, options);
 557 
 558         offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
 559     }
 560 
 561     if(node) {
 562         offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);
 563 
 564         if (node->details->online == FALSE && node->details->unclean) {
 565             flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 566                                    "%sUNCLEAN", comma_if(flagOffset));
 567         }
 568     }
 569 
 570     if (options & pe_print_pending) {
 571         const char *pending_task = native_pending_task(rsc);
 572 
 573         if (pending_task) {
 574             flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 575                                    "%s%s", comma_if(flagOffset), pending_task);
 576         }
 577     }
 578 
 579     if (target_role) {
 580         enum rsc_role_e target_role_e = text2role(target_role);
 581 
 582         /* Ignore target role Started, as it is the default anyways
 583          * (and would also allow a Master to be Master).
 584          * Show if target role limits our abilities. */
 585         if (target_role_e == RSC_ROLE_STOPPED) {
 586             flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 587                                    "%sdisabled", comma_if(flagOffset));
 588             rsc->cluster->disabled_resources++;
 589 
 590         } else if (uber_parent(rsc)->variant == pe_master
 591                    && target_role_e == RSC_ROLE_SLAVE) {
 592             flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 593                                    "%starget-role:%s", comma_if(flagOffset), target_role);
 594             rsc->cluster->disabled_resources++;
 595         }
 596     }
 597 
 598     if (is_set(rsc->flags, pe_rsc_block)) {
 599         flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 600                                "%sblocked", comma_if(flagOffset));
 601         rsc->cluster->blocked_resources++;
 602 
 603     } else if (is_not_set(rsc->flags, pe_rsc_managed)) {
 604         flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 605                                "%sunmanaged", comma_if(flagOffset));
 606     }
 607 
 608     if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
 609         flagOffset += snprintf(flagBuffer + flagOffset, LINE_MAX - flagOffset,
 610                                "%sfailure ignored", comma_if(flagOffset));
 611     }
 612 
 613     if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
 614         desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
 615     }
 616 
 617     CRM_LOG_ASSERT(offset > 0);
 618     if(flagOffset > 0) {
 619         status_print("%s (%s)%s%s", buffer, flagBuffer, desc?" ":"", desc?desc:"");
 620     } else {
 621         status_print("%s%s%s", buffer, desc?" ":"", desc?desc:"");
 622     }
 623 
 624 #if CURSES_ENABLED
 625     if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
 626         /* Done */
 627 
 628     } else if (options & pe_print_ncurses) {
 629         /* coverity[negative_returns] False positive */
 630         move(-1, 0);
 631     }
 632 #endif
 633 
 634     if (options & pe_print_html) {
 635         status_print(" </font> ");
 636     }
 637 
 638     if ((options & pe_print_rsconly)) {
 639 
 640     } else if (g_list_length(rsc->running_on) > 1) {
 641         GListPtr gIter = rsc->running_on;
 642         int counter = 0;
 643 
 644         if (options & pe_print_html) {
 645             status_print("<ul>\n");
 646         } else if ((options & pe_print_printf)
 647                    || (options & pe_print_ncurses)) {
 648             status_print("[");
 649         }
 650 
 651         for (; gIter != NULL; gIter = gIter->next) {
 652             node_t *n = (node_t *) gIter->data;
 653 
 654             counter++;
 655 
 656             if (options & pe_print_html) {
 657                 status_print("<li>\n%s", n->details->uname);
 658 
 659             } else if ((options & pe_print_printf)
 660                        || (options & pe_print_ncurses)) {
 661                 status_print(" %s", n->details->uname);
 662 
 663             } else if ((options & pe_print_log)) {
 664                 status_print("\t%d : %s", counter, n->details->uname);
 665 
 666             } else {
 667                 status_print("%s", n->details->uname);
 668             }
 669             if (options & pe_print_html) {
 670                 status_print("</li>\n");
 671 
 672             }
 673         }
 674 
 675         if (options & pe_print_html) {
 676             status_print("</ul>\n");
 677         } else if ((options & pe_print_printf)
 678                    || (options & pe_print_ncurses)) {
 679             status_print(" ]");
 680         }
 681     }
 682 
 683     if (options & pe_print_html) {
 684         status_print("<br/>\n");
 685     } else if (options & pe_print_suppres_nl) {
 686         /* nothing */
 687     } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) {
 688         status_print("\n");
 689     }
 690 
 691     if (options & pe_print_details) {
 692         struct print_data_s pdata;
 693 
 694         pdata.options = options;
 695         pdata.print_data = print_data;
 696         g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata);
 697     }
 698 
 699     if (options & pe_print_dev) {
 700         GHashTableIter iter;
 701         node_t *n = NULL;
 702 
 703         status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text,
 704                      is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "",
 705                      is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ",
 706                      crm_element_name(rsc->xml), (double)rsc->priority);
 707         status_print("%s\tAllowed Nodes", pre_text);
 708         g_hash_table_iter_init(&iter, rsc->allowed_nodes);
 709         while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
 710             status_print("%s\t * %s %d", pre_text, n->details->uname, n->weight);
 711         }
 712     }
 713 
 714     if (options & pe_print_max_details) {
 715         GHashTableIter iter;
 716         node_t *n = NULL;
 717 
 718         status_print("%s\t=== Allowed Nodes\n", pre_text);
 719         g_hash_table_iter_init(&iter, rsc->allowed_nodes);
 720         while (g_hash_table_iter_next(&iter, NULL, (void **)&n)) {
 721             print_node("\t", n, FALSE);
 722         }
 723     }
 724 }
 725 
 726 void
 727 native_print(resource_t * rsc, const char *pre_text, long options, void *print_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 728 {
 729     node_t *node = NULL;
 730 
 731     CRM_ASSERT(rsc->variant == pe_native);
 732     if (options & pe_print_xml) {
 733         native_print_xml(rsc, pre_text, options, print_data);
 734         return;
 735     }
 736 
 737     if (rsc->running_on != NULL) {
 738         node = rsc->running_on->data;
 739     }
 740     common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
 741 }
 742 
 743 void
 744 native_free(resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 745 {
 746     pe_rsc_trace(rsc, "Freeing resource action list (not the data)");
 747     common_free(rsc);
 748 }
 749 
 750 enum rsc_role_e
 751 native_resource_state(const resource_t * rsc, gboolean current)
     /* [previous][next][first][last][top][bottom][index][help] */
 752 {
 753     enum rsc_role_e role = rsc->next_role;
 754 
 755     if (current) {
 756         role = rsc->role;
 757     }
 758     pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role));
 759     return role;
 760 }
 761 
 762 node_t *
 763 native_location(resource_t * rsc, GListPtr * list, gboolean current)
     /* [previous][next][first][last][top][bottom][index][help] */
 764 {
 765     node_t *one = NULL;
 766     GListPtr result = NULL;
 767 
 768     if (rsc->children) {
 769         GListPtr gIter = rsc->children;
 770 
 771         for (; gIter != NULL; gIter = gIter->next) {
 772             resource_t *child = (resource_t *) gIter->data;
 773 
 774             child->fns->location(child, &result, current);
 775         }
 776 
 777     } else if (current && rsc->running_on) {
 778         result = g_list_copy(rsc->running_on);
 779 
 780     } else if (current == FALSE && rsc->allocated_to) {
 781         result = g_list_append(NULL, rsc->allocated_to);
 782     }
 783 
 784     if (result && g_list_length(result) == 1) {
 785         one = g_list_nth_data(result, 0);
 786     }
 787 
 788     if (list) {
 789         GListPtr gIter = result;
 790 
 791         for (; gIter != NULL; gIter = gIter->next) {
 792             node_t *node = (node_t *) gIter->data;
 793 
 794             if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) {
 795                 *list = g_list_append(*list, node);
 796             }
 797         }
 798     }
 799 
 800     g_list_free(result);
 801     return one;
 802 }
 803 
 804 static void
 805 get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table)
     /* [previous][next][first][last][top][bottom][index][help] */
 806 {
 807     GListPtr gIter = rsc_list;
 808 
 809     for (; gIter != NULL; gIter = gIter->next) {
 810         resource_t *rsc = (resource_t *) gIter->data;
 811 
 812         const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 813         const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE);
 814 
 815         int offset = 0;
 816         char buffer[LINE_MAX];
 817 
 818         int *rsc_counter = NULL;
 819         int *active_counter = NULL;
 820 
 821         if (rsc->variant != pe_native) {
 822             continue;
 823         }
 824 
 825         offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class);
 826         if (crm_provider_required(class)) {
 827             const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
 828             offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov);
 829         }
 830         offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind);
 831         CRM_LOG_ASSERT(offset > 0);
 832 
 833         if (rsc_table) {
 834             rsc_counter = g_hash_table_lookup(rsc_table, buffer);
 835             if (rsc_counter == NULL) {
 836                 rsc_counter = calloc(1, sizeof(int));
 837                 *rsc_counter = 0;
 838                 g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter);
 839             }
 840             (*rsc_counter)++;
 841         }
 842 
 843         if (active_table) {
 844             GListPtr gIter2 = rsc->running_on;
 845 
 846             for (; gIter2 != NULL; gIter2 = gIter2->next) {
 847                 node_t *node = (node_t *) gIter2->data;
 848                 GHashTable *node_table = NULL;
 849 
 850                 if (node->details->unclean == FALSE && node->details->online == FALSE) {
 851                     continue;
 852                 }
 853 
 854                 node_table = g_hash_table_lookup(active_table, node->details->uname);
 855                 if (node_table == NULL) {
 856                     node_table = crm_str_table_new();
 857                     g_hash_table_insert(active_table, strdup(node->details->uname), node_table);
 858                 }
 859 
 860                 active_counter = g_hash_table_lookup(node_table, buffer);
 861                 if (active_counter == NULL) {
 862                     active_counter = calloc(1, sizeof(int));
 863                     *active_counter = 0;
 864                     g_hash_table_insert(node_table, strdup(buffer), active_counter);
 865                 }
 866                 (*active_counter)++;
 867             }
 868         }
 869     }
 870 }
 871 
 872 static void
 873 destroy_node_table(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 874 {
 875     GHashTable *node_table = data;
 876 
 877     if (node_table) {
 878         g_hash_table_destroy(node_table);
 879     }
 880 }
 881 
 882 void
 883 print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options,
     /* [previous][next][first][last][top][bottom][index][help] */
 884                  void *print_data, gboolean print_all)
 885 {
 886     GHashTable *rsc_table = crm_str_table_new();
 887     GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal,
 888                                                      free, destroy_node_table);
 889     GHashTableIter hash_iter;
 890     char *type = NULL;
 891     int *rsc_counter = NULL;
 892 
 893     get_rscs_brief(rsc_list, rsc_table, active_table);
 894 
 895     g_hash_table_iter_init(&hash_iter, rsc_table);
 896     while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) {
 897         GHashTableIter hash_iter2;
 898         char *node_name = NULL;
 899         GHashTable *node_table = NULL;
 900         int active_counter_all = 0;
 901 
 902         g_hash_table_iter_init(&hash_iter2, active_table);
 903         while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) {
 904             int *active_counter = g_hash_table_lookup(node_table, type);
 905 
 906             if (active_counter == NULL || *active_counter == 0) {
 907                 continue;
 908 
 909             } else {
 910                 active_counter_all += *active_counter;
 911             }
 912 
 913             if (options & pe_print_rsconly) {
 914                 node_name = NULL;
 915             }
 916 
 917             if (options & pe_print_html) {
 918                 status_print("<li>\n");
 919             }
 920 
 921             if (print_all) {
 922                 status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
 923                              active_counter ? *active_counter : 0,
 924                              rsc_counter ? *rsc_counter : 0, type,
 925                              active_counter && (*active_counter > 0) && node_name ? node_name : "");
 926             } else {
 927                 status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "",
 928                              active_counter ? *active_counter : 0, type,
 929                              active_counter && (*active_counter > 0) && node_name ? node_name : "");
 930             }
 931 
 932             if (options & pe_print_html) {
 933                 status_print("</li>\n");
 934             }
 935         }
 936 
 937         if (print_all && active_counter_all == 0) {
 938             if (options & pe_print_html) {
 939                 status_print("<li>\n");
 940             }
 941 
 942             status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "",
 943                          active_counter_all,
 944                          rsc_counter ? *rsc_counter : 0, type);
 945 
 946             if (options & pe_print_html) {
 947                 status_print("</li>\n");
 948             }
 949         }
 950     }
 951 
 952     if (rsc_table) {
 953         g_hash_table_destroy(rsc_table);
 954         rsc_table = NULL;
 955     }
 956     if (active_table) {
 957         g_hash_table_destroy(active_table);
 958         active_table = NULL;
 959     }
 960 }

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