root/tools/crm_resource_print.c

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

DEFINITIONS

This source file includes following definitions.
  1. cli_resource_print_cts_constraints
  2. cli_resource_print_cts
  3. cli_resource_print_raw
  4. cli_resource_print_list
  5. cli_resource_print_operations
  6. cli_resource_print_location
  7. cli_resource_print_colocation
  8. cli_resource_print
  9. cli_resource_print_attribute
  10. cli_resource_print_property

   1 /*
   2  * Copyright 2004-2020 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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_resource.h>
  11 #include <crm/common/xml_internal.h>
  12 
  13 #define cons_string(x) x?x:"NA"
  14 void
  15 cli_resource_print_cts_constraints(pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
  16 {
  17     xmlNode *xml_obj = NULL;
  18     xmlNode *lifetime = NULL;
  19     xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input);
  20 
  21     for (xml_obj = pcmk__xe_first_child(cib_constraints); xml_obj != NULL;
  22          xml_obj = pcmk__xe_next(xml_obj)) {
  23         const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
  24 
  25         if (id == NULL) {
  26             continue;
  27         }
  28 
  29         // @COMPAT lifetime is deprecated
  30         lifetime = first_named_child(xml_obj, "lifetime");
  31         if (pe_evaluate_rules(lifetime, NULL, data_set->now, NULL) == FALSE) {
  32             continue;
  33         }
  34 
  35         if (pcmk__str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj), pcmk__str_casei)) {
  36             printf("Constraint %s %s %s %s %s %s %s\n",
  37                    crm_element_name(xml_obj),
  38                    cons_string(crm_element_value(xml_obj, XML_ATTR_ID)),
  39                    cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE)),
  40                    cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET)),
  41                    cons_string(crm_element_value(xml_obj, XML_RULE_ATTR_SCORE)),
  42                    cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE)),
  43                    cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_ROLE)));
  44 
  45         } else if (pcmk__str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj), pcmk__str_casei)) {
  46             /* unpack_location(xml_obj, data_set); */
  47         }
  48     }
  49 }
  50 
  51 void
  52 cli_resource_print_cts(pe_resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54     GListPtr lpc = NULL;
  55     const char *host = NULL;
  56     bool needs_quorum = TRUE;
  57     const char *rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE);
  58     const char *rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
  59     const char *rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
  60     pe_node_t *node = pe__current_node(rsc);
  61 
  62     if (pcmk__str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
  63         needs_quorum = FALSE;
  64     } else {
  65         // @TODO check requires in resource meta-data and rsc_defaults
  66     }
  67 
  68     if (node != NULL) {
  69         host = node->details->uname;
  70     }
  71 
  72     printf("Resource: %s %s %s %s %s %s %s %s %d %lld 0x%.16llx\n",
  73            crm_element_name(rsc->xml), rsc->id,
  74            rsc->clone_name ? rsc->clone_name : rsc->id, rsc->parent ? rsc->parent->id : "NA",
  75            rprov ? rprov : "NA", rclass, rtype, host ? host : "NA", needs_quorum, rsc->flags,
  76            rsc->flags);
  77 
  78     for (lpc = rsc->children; lpc != NULL; lpc = lpc->next) {
  79         pe_resource_t *child = (pe_resource_t *) lpc->data;
  80 
  81         cli_resource_print_cts(child);
  82     }
  83 }
  84 
  85 
  86 void
  87 cli_resource_print_raw(pe_resource_t * rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89     GListPtr lpc = NULL;
  90     GListPtr children = rsc->children;
  91 
  92     if (children == NULL) {
  93         printf("%s\n", rsc->id);
  94     }
  95 
  96     for (lpc = children; lpc != NULL; lpc = lpc->next) {
  97         pe_resource_t *child = (pe_resource_t *) lpc->data;
  98 
  99         cli_resource_print_raw(child);
 100     }
 101 }
 102 
 103 // \return Standard Pacemaker return code
 104 int
 105 cli_resource_print_list(pe_working_set_t * data_set, bool raw)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107     int found = 0;
 108 
 109     GListPtr lpc = NULL;
 110     int opts = pe_print_printf | pe_print_rsconly | pe_print_pending;
 111 
 112     for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
 113         pe_resource_t *rsc = (pe_resource_t *) lpc->data;
 114 
 115         if (pcmk_is_set(rsc->flags, pe_rsc_orphan)
 116             && rsc->fns->active(rsc, TRUE) == FALSE) {
 117             continue;
 118         }
 119         rsc->fns->print(rsc, NULL, opts, stdout);
 120         found++;
 121     }
 122 
 123     if (found == 0) {
 124         printf("NO resources configured\n");
 125         return ENXIO;
 126     }
 127 
 128     return pcmk_rc_ok;
 129 }
 130 
 131 // \return Standard Pacemaker return code
 132 int
 133 cli_resource_print_operations(const char *rsc_id, const char *host_uname, bool active,
     /* [previous][next][first][last][top][bottom][index][help] */
 134                          pe_working_set_t * data_set)
 135 {
 136     pe_resource_t *rsc = NULL;
 137     int opts = pe_print_printf | pe_print_rsconly | pe_print_suppres_nl | pe_print_pending;
 138     GListPtr ops = find_operations(rsc_id, host_uname, active, data_set);
 139     GListPtr lpc = NULL;
 140 
 141     for (lpc = ops; lpc != NULL; lpc = lpc->next) {
 142         xmlNode *xml_op = (xmlNode *) lpc->data;
 143 
 144         const char *op_rsc = crm_element_value(xml_op, "resource");
 145         const char *status_s = crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS);
 146         const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY);
 147         int status = crm_parse_int(status_s, "0");
 148         time_t last_change = 0;
 149 
 150         rsc = pe_find_resource(data_set->resources, op_rsc);
 151         if(rsc) {
 152             rsc->fns->print(rsc, "", opts, stdout);
 153         } else {
 154             fprintf(stdout, "Unknown resource %s", op_rsc);
 155         }
 156 
 157         fprintf(stdout, ": %s (node=%s, call=%s, rc=%s",
 158                 op_key ? op_key : ID(xml_op),
 159                 crm_element_value(xml_op, XML_ATTR_UNAME),
 160                 crm_element_value(xml_op, XML_LRM_ATTR_CALLID),
 161                 crm_element_value(xml_op, XML_LRM_ATTR_RC));
 162 
 163         if (crm_element_value_epoch(xml_op, XML_RSC_OP_LAST_CHANGE,
 164                                     &last_change) == pcmk_ok) {
 165             fprintf(stdout, ", " XML_RSC_OP_LAST_CHANGE "=%s, exec=%sms",
 166                     crm_strip_trailing_newline(ctime(&last_change)),
 167                     crm_element_value(xml_op, XML_RSC_OP_T_EXEC));
 168         }
 169         fprintf(stdout, "): %s\n", services_lrm_status_str(status));
 170     }
 171     return pcmk_rc_ok;
 172 }
 173 
 174 void
 175 cli_resource_print_location(pe_resource_t * rsc, const char *prefix)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177     GListPtr lpc = NULL;
 178     GListPtr list = rsc->rsc_location;
 179     int offset = 0;
 180 
 181     if (prefix) {
 182         offset = strlen(prefix) - 2;
 183     }
 184 
 185     for (lpc = list; lpc != NULL; lpc = lpc->next) {
 186         pe__location_t *cons = lpc->data;
 187 
 188         GListPtr lpc2 = NULL;
 189 
 190         for (lpc2 = cons->node_list_rh; lpc2 != NULL; lpc2 = lpc2->next) {
 191             pe_node_t *node = (pe_node_t *) lpc2->data;
 192             char *score = score2char(node->weight);
 193 
 194             fprintf(stdout, "%s: Node %-*s (score=%s, id=%s)\n",
 195                     prefix ? prefix : "  ", 71 - offset, node->details->uname, score, cons->id);
 196             free(score);
 197         }
 198     }
 199 }
 200 
 201 void
 202 cli_resource_print_colocation(pe_resource_t * rsc, bool dependents, bool recursive, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204     char *prefix = NULL;
 205     GListPtr lpc = NULL;
 206     GListPtr list = rsc->rsc_cons;
 207 
 208     prefix = calloc(1, (offset * 4) + 1);
 209     memset(prefix, ' ', offset * 4);
 210 
 211     if (dependents) {
 212         list = rsc->rsc_cons_lhs;
 213     }
 214 
 215     if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
 216         /* Break colocation loops */
 217         printf("loop %s\n", rsc->id);
 218         free(prefix);
 219         return;
 220     }
 221 
 222     pe__set_resource_flags(rsc, pe_rsc_allocating);
 223     for (lpc = list; lpc != NULL; lpc = lpc->next) {
 224         rsc_colocation_t *cons = (rsc_colocation_t *) lpc->data;
 225 
 226         char *score = NULL;
 227         pe_resource_t *peer = cons->rsc_rh;
 228 
 229         if (dependents) {
 230             peer = cons->rsc_lh;
 231         }
 232 
 233         if (pcmk_is_set(peer->flags, pe_rsc_allocating)) {
 234             if (dependents == FALSE) {
 235                 fprintf(stdout, "%s%-*s (id=%s - loop)\n", prefix, 80 - (4 * offset), peer->id,
 236                         cons->id);
 237             }
 238             continue;
 239         }
 240 
 241         if (dependents && recursive) {
 242             cli_resource_print_colocation(peer, dependents, recursive, offset + 1);
 243         }
 244 
 245         score = score2char(cons->score);
 246         if (cons->role_rh > RSC_ROLE_STARTED) {
 247             fprintf(stdout, "%s%-*s (score=%s, %s role=%s, id=%s)\n", prefix, 80 - (4 * offset),
 248                     peer->id, score, dependents ? "needs" : "with", role2text(cons->role_rh),
 249                     cons->id);
 250         } else {
 251             fprintf(stdout, "%s%-*s (score=%s, id=%s)\n", prefix, 80 - (4 * offset),
 252                     peer->id, score, cons->id);
 253         }
 254         cli_resource_print_location(peer, prefix);
 255         free(score);
 256 
 257         if (!dependents && recursive) {
 258             cli_resource_print_colocation(peer, dependents, recursive, offset + 1);
 259         }
 260     }
 261     free(prefix);
 262 }
 263 
 264 // \return Standard Pacemaker return code
 265 int
 266 cli_resource_print(pe_resource_t *rsc, pe_working_set_t *data_set, bool expanded)
     /* [previous][next][first][last][top][bottom][index][help] */
 267 {
 268     char *rsc_xml = NULL;
 269     int opts = pe_print_printf | pe_print_pending;
 270 
 271     rsc->fns->print(rsc, NULL, opts, stdout);
 272 
 273     rsc_xml = dump_xml_formatted((!expanded && rsc->orig_xml)?
 274                                  rsc->orig_xml : rsc->xml);
 275     fprintf(stdout, "%sxml:\n%s\n", expanded ? "" : "raw ", rsc_xml);
 276     free(rsc_xml);
 277     return pcmk_rc_ok;
 278 }
 279 
 280 // \return Standard Pacemaker return code
 281 int
 282 cli_resource_print_attribute(pe_resource_t *rsc, const char *attr, const char *attr_set_type,
     /* [previous][next][first][last][top][bottom][index][help] */
 283                              pe_working_set_t * data_set)
 284 {
 285     int rc = ENXIO;
 286     unsigned int count = 0;
 287     GHashTable *params = NULL;
 288     const char *value = NULL;
 289     pe_node_t *current = pe__find_active_on(rsc, &count, NULL);
 290 
 291     if (count > 1) {
 292         CMD_ERR("%s is active on more than one node,"
 293                 " returning the default value for %s", rsc->id, crm_str(attr));
 294         current = NULL;
 295     }
 296 
 297     params = crm_str_table_new();
 298 
 299     if (pcmk__str_eq(attr_set_type, XML_TAG_ATTR_SETS, pcmk__str_casei)) {
 300         get_rsc_attributes(params, rsc, current, data_set);
 301 
 302     } else if (pcmk__str_eq(attr_set_type, XML_TAG_META_SETS, pcmk__str_casei)) {
 303         /* No need to redirect to the parent */
 304         get_meta_attributes(params, rsc, current, data_set);
 305 
 306     } else {
 307         pe__unpack_dataset_nvpairs(rsc->xml, XML_TAG_UTILIZATION, NULL, params,
 308                                    NULL, FALSE, data_set);
 309     }
 310 
 311     crm_debug("Looking up %s in %s", attr, rsc->id);
 312     value = g_hash_table_lookup(params, attr);
 313     if (value != NULL) {
 314         fprintf(stdout, "%s\n", value);
 315         rc = pcmk_rc_ok;
 316 
 317     } else {
 318         CMD_ERR("Attribute '%s' not found for '%s'", attr, rsc->id);
 319     }
 320 
 321     g_hash_table_destroy(params);
 322     return rc;
 323 }
 324 
 325 // \return Standard Pacemaker return code
 326 int
 327 cli_resource_print_property(pe_resource_t *rsc, const char *attr, pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329     const char *value = crm_element_value(rsc->xml, attr);
 330 
 331     if (value != NULL) {
 332         fprintf(stdout, "%s\n", value);
 333         return pcmk_rc_ok;
 334     }
 335     return ENXIO;
 336 }

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