root/lib/pengine/status.c

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

DEFINITIONS

This source file includes following definitions.
  1. pe_new_working_set
  2. pe_free_working_set
  3. cluster_status
  4. pe_free_resources
  5. pe_free_actions
  6. pe_free_nodes
  7. pe__free_ordering
  8. pe__free_location
  9. cleanup_calculations
  10. pe_reset_working_set
  11. set_working_set_defaults
  12. pe_find_resource
  13. pe_find_resource_with_flags
  14. pe_find_node_any
  15. pe_find_node_id
  16. pe_find_node

   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 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 <sys/param.h>
  13 
  14 #include <crm/crm.h>
  15 #include <crm/msg_xml.h>
  16 #include <crm/common/xml.h>
  17 
  18 #include <glib.h>
  19 
  20 #include <crm/pengine/internal.h>
  21 #include <pe_status_private.h>
  22 
  23 /*!
  24  * \brief Create a new working set
  25  *
  26  * \return New, initialized working set on success, else NULL (and set errno)
  27  * \note Only pe_working_set_t objects created with this function (as opposed
  28  *       to statically declared or directly allocated) should be used with the
  29  *       functions in this library, to allow for future extensions to the
  30  *       data type. The caller is responsible for freeing the memory with
  31  *       pe_free_working_set() when the instance is no longer needed.
  32  */
  33 pe_working_set_t *
  34 pe_new_working_set()
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36     pe_working_set_t *data_set = calloc(1, sizeof(pe_working_set_t));
  37 
  38     if (data_set != NULL) {
  39         set_working_set_defaults(data_set);
  40     }
  41     return data_set;
  42 }
  43 
  44 /*!
  45  * \brief Free a working set
  46  *
  47  * \param[in] data_set  Working set to free
  48  */
  49 void
  50 pe_free_working_set(pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52     if (data_set != NULL) {
  53         pe_reset_working_set(data_set);
  54         free(data_set);
  55     }
  56 }
  57 
  58 /*
  59  * Unpack everything
  60  * At the end you'll have:
  61  *  - A list of nodes
  62  *  - A list of resources (each with any dependencies on other resources)
  63  *  - A list of constraints between resources and nodes
  64  *  - A list of constraints between start/stop actions
  65  *  - A list of nodes that need to be stonith'd
  66  *  - A list of nodes that need to be shutdown
  67  *  - A list of the possible stop/start actions (without dependencies)
  68  */
  69 gboolean
  70 cluster_status(pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72     xmlNode *config = get_xpath_object("//"XML_CIB_TAG_CRMCONFIG, data_set->input, LOG_TRACE);
  73     xmlNode *cib_nodes = get_xpath_object("//"XML_CIB_TAG_NODES, data_set->input, LOG_TRACE);
  74     xmlNode *cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
  75     xmlNode *cib_status = get_xpath_object("//"XML_CIB_TAG_STATUS, data_set->input, LOG_TRACE);
  76     xmlNode *cib_tags = get_xpath_object("//" XML_CIB_TAG_TAGS, data_set->input,
  77                                          LOG_NEVER);
  78     const char *value = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
  79 
  80     crm_trace("Beginning unpack");
  81 
  82     /* reset remaining global variables */
  83     data_set->failed = create_xml_node(NULL, "failed-ops");
  84 
  85     if (data_set->input == NULL) {
  86         return FALSE;
  87     }
  88 
  89     if (data_set->now == NULL) {
  90         data_set->now = crm_time_new(NULL);
  91     }
  92 
  93     if (data_set->dc_uuid == NULL) {
  94         data_set->dc_uuid = crm_element_value_copy(data_set->input,
  95                                                    XML_ATTR_DC_UUID);
  96     }
  97 
  98     if (crm_is_true(value)) {
  99         pe__set_working_set_flags(data_set, pe_flag_have_quorum);
 100     } else {
 101         pe__clear_working_set_flags(data_set, pe_flag_have_quorum);
 102     }
 103 
 104     data_set->op_defaults = get_xpath_object("//" XML_CIB_TAG_OPCONFIG,
 105                                              data_set->input, LOG_NEVER);
 106     data_set->rsc_defaults = get_xpath_object("//" XML_CIB_TAG_RSCCONFIG,
 107                                               data_set->input, LOG_NEVER);
 108 
 109     unpack_config(config, data_set);
 110 
 111    if (!pcmk_any_flags_set(data_set->flags,
 112                            pe_flag_quick_location|pe_flag_have_quorum)
 113        && (data_set->no_quorum_policy != no_quorum_ignore)) {
 114         crm_warn("Fencing and resource management disabled due to lack of quorum");
 115     }
 116 
 117     unpack_nodes(cib_nodes, data_set);
 118 
 119     if (!pcmk_is_set(data_set->flags, pe_flag_quick_location)) {
 120         unpack_remote_nodes(cib_resources, data_set);
 121     }
 122 
 123     unpack_resources(cib_resources, data_set);
 124     unpack_tags(cib_tags, data_set);
 125 
 126     if (!pcmk_is_set(data_set->flags, pe_flag_quick_location)) {
 127         unpack_status(cib_status, data_set);
 128     }
 129 
 130     if (!pcmk_is_set(data_set->flags, pe_flag_no_counts)) {
 131         for (GList *item = data_set->resources; item != NULL;
 132              item = item->next) {
 133             ((pe_resource_t *) (item->data))->fns->count(item->data);
 134         }
 135     }
 136 
 137     pe__set_working_set_flags(data_set, pe_flag_have_status);
 138     return TRUE;
 139 }
 140 
 141 /*!
 142  * \internal
 143  * \brief Free a list of pe_resource_t
 144  *
 145  * \param[in] resources  List to free
 146  *
 147  * \note When a working set's resource list is freed, that includes the original
 148  *       storage for the uname and id of any Pacemaker Remote nodes in the
 149  *       working set's node list, so take care not to use those afterward.
 150  * \todo Refactor pe_node_t to strdup() the node name.
 151  */
 152 static void
 153 pe_free_resources(GListPtr resources)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155     pe_resource_t *rsc = NULL;
 156     GListPtr iterator = resources;
 157 
 158     while (iterator != NULL) {
 159         rsc = (pe_resource_t *) iterator->data;
 160         iterator = iterator->next;
 161         rsc->fns->free(rsc);
 162     }
 163     if (resources != NULL) {
 164         g_list_free(resources);
 165     }
 166 }
 167 
 168 static void
 169 pe_free_actions(GListPtr actions)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171     GListPtr iterator = actions;
 172 
 173     while (iterator != NULL) {
 174         pe_free_action(iterator->data);
 175         iterator = iterator->next;
 176     }
 177     if (actions != NULL) {
 178         g_list_free(actions);
 179     }
 180 }
 181 
 182 static void
 183 pe_free_nodes(GListPtr nodes)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185     for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) {
 186         pe_node_t *node = (pe_node_t *) iterator->data;
 187 
 188         // Shouldn't be possible, but to be safe ...
 189         if (node == NULL) {
 190             continue;
 191         }
 192         if (node->details == NULL) {
 193             free(node);
 194             continue;
 195         }
 196 
 197         /* This is called after pe_free_resources(), which means that we can't
 198          * use node->details->uname for Pacemaker Remote nodes.
 199          */
 200         crm_trace("Freeing node %s", (pe__is_guest_or_remote_node(node)?
 201                   "(guest or remote)" : node->details->uname));
 202 
 203         if (node->details->attrs != NULL) {
 204             g_hash_table_destroy(node->details->attrs);
 205         }
 206         if (node->details->utilization != NULL) {
 207             g_hash_table_destroy(node->details->utilization);
 208         }
 209         if (node->details->digest_cache != NULL) {
 210             g_hash_table_destroy(node->details->digest_cache);
 211         }
 212         g_list_free(node->details->running_rsc);
 213         g_list_free(node->details->allocated_rsc);
 214         free(node->details);
 215         free(node);
 216     }
 217     if (nodes != NULL) {
 218         g_list_free(nodes);
 219     }
 220 }
 221 
 222 static void
 223 pe__free_ordering(GListPtr constraints)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225     GListPtr iterator = constraints;
 226 
 227     while (iterator != NULL) {
 228         pe__ordering_t *order = iterator->data;
 229 
 230         iterator = iterator->next;
 231 
 232         free(order->lh_action_task);
 233         free(order->rh_action_task);
 234         free(order);
 235     }
 236     if (constraints != NULL) {
 237         g_list_free(constraints);
 238     }
 239 }
 240 
 241 static void
 242 pe__free_location(GListPtr constraints)
     /* [previous][next][first][last][top][bottom][index][help] */
 243 {
 244     GListPtr iterator = constraints;
 245 
 246     while (iterator != NULL) {
 247         pe__location_t *cons = iterator->data;
 248 
 249         iterator = iterator->next;
 250 
 251         g_list_free_full(cons->node_list_rh, free);
 252         free(cons->id);
 253         free(cons);
 254     }
 255     if (constraints != NULL) {
 256         g_list_free(constraints);
 257     }
 258 }
 259 
 260 /*!
 261  * \brief Reset working set to default state without freeing it or constraints
 262  *
 263  * \param[in,out] data_set  Working set to reset
 264  *
 265  * \deprecated This function is deprecated as part of the API;
 266  *             pe_reset_working_set() should be used instead.
 267  */
 268 void
 269 cleanup_calculations(pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271     if (data_set == NULL) {
 272         return;
 273     }
 274 
 275     pe__clear_working_set_flags(data_set, pe_flag_have_status);
 276     if (data_set->config_hash != NULL) {
 277         g_hash_table_destroy(data_set->config_hash);
 278     }
 279 
 280     if (data_set->singletons != NULL) {
 281         g_hash_table_destroy(data_set->singletons);
 282     }
 283 
 284     if (data_set->tickets) {
 285         g_hash_table_destroy(data_set->tickets);
 286     }
 287 
 288     if (data_set->template_rsc_sets) {
 289         g_hash_table_destroy(data_set->template_rsc_sets);
 290     }
 291 
 292     if (data_set->tags) {
 293         g_hash_table_destroy(data_set->tags);
 294     }
 295 
 296     free(data_set->dc_uuid);
 297 
 298     crm_trace("deleting resources");
 299     pe_free_resources(data_set->resources);
 300 
 301     crm_trace("deleting actions");
 302     pe_free_actions(data_set->actions);
 303 
 304     crm_trace("deleting nodes");
 305     pe_free_nodes(data_set->nodes);
 306 
 307     pe__free_param_checks(data_set);
 308     g_list_free(data_set->stop_needed);
 309     free_xml(data_set->graph);
 310     crm_time_free(data_set->now);
 311     free_xml(data_set->input);
 312     free_xml(data_set->failed);
 313 
 314     set_working_set_defaults(data_set);
 315 
 316     CRM_CHECK(data_set->ordering_constraints == NULL,;
 317         );
 318     CRM_CHECK(data_set->placement_constraints == NULL,;
 319         );
 320 }
 321 
 322 /*!
 323  * \brief Reset a working set to default state without freeing it
 324  *
 325  * \param[in,out] data_set  Working set to reset
 326  */
 327 void
 328 pe_reset_working_set(pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 329 {
 330     if (data_set == NULL) {
 331         return;
 332     }
 333 
 334     crm_trace("Deleting %d ordering constraints",
 335               g_list_length(data_set->ordering_constraints));
 336     pe__free_ordering(data_set->ordering_constraints);
 337     data_set->ordering_constraints = NULL;
 338 
 339     crm_trace("Deleting %d location constraints",
 340               g_list_length(data_set->placement_constraints));
 341     pe__free_location(data_set->placement_constraints);
 342     data_set->placement_constraints = NULL;
 343 
 344     crm_trace("Deleting %d colocation constraints",
 345               g_list_length(data_set->colocation_constraints));
 346     g_list_free_full(data_set->colocation_constraints, free);
 347     data_set->colocation_constraints = NULL;
 348 
 349     crm_trace("Deleting %d ticket constraints",
 350               g_list_length(data_set->ticket_constraints));
 351     g_list_free_full(data_set->ticket_constraints, free);
 352     data_set->ticket_constraints = NULL;
 353 
 354     cleanup_calculations(data_set);
 355 }
 356 
 357 void
 358 set_working_set_defaults(pe_working_set_t * data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 359 {
 360     memset(data_set, 0, sizeof(pe_working_set_t));
 361 
 362     data_set->order_id = 1;
 363     data_set->action_id = 1;
 364     data_set->no_quorum_policy = no_quorum_stop;
 365 
 366     data_set->flags = 0x0ULL;
 367 
 368 #ifdef DEFAULT_CONCURRENT_FENCING_TRUE
 369     pe__set_working_set_flags(data_set,
 370                               pe_flag_stop_rsc_orphans
 371                               |pe_flag_symmetric_cluster
 372                               |pe_flag_stop_action_orphans
 373                               |pe_flag_concurrent_fencing);
 374 #else
 375     pe__set_working_set_flags(data_set,
 376                               pe_flag_stop_rsc_orphans
 377                               |pe_flag_symmetric_cluster
 378                               |pe_flag_stop_action_orphans);
 379 #endif
 380 }
 381 
 382 pe_resource_t *
 383 pe_find_resource(GListPtr rsc_list, const char *id)
     /* [previous][next][first][last][top][bottom][index][help] */
 384 {
 385     return pe_find_resource_with_flags(rsc_list, id, pe_find_renamed);
 386 }
 387 
 388 pe_resource_t *
 389 pe_find_resource_with_flags(GListPtr rsc_list, const char *id, enum pe_find flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 390 {
 391     GListPtr rIter = NULL;
 392 
 393     for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
 394         pe_resource_t *parent = rIter->data;
 395 
 396         pe_resource_t *match =
 397             parent->fns->find_rsc(parent, id, NULL, flags);
 398         if (match != NULL) {
 399             return match;
 400         }
 401     }
 402     crm_trace("No match for %s", id);
 403     return NULL;
 404 }
 405 
 406 pe_node_t *
 407 pe_find_node_any(GListPtr nodes, const char *id, const char *uname)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409     pe_node_t *match = pe_find_node_id(nodes, id);
 410 
 411     if (match) {
 412         return match;
 413     }
 414     crm_trace("Looking up %s via its uname instead", uname);
 415     return pe_find_node(nodes, uname);
 416 }
 417 
 418 pe_node_t *
 419 pe_find_node_id(GListPtr nodes, const char *id)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421     GListPtr gIter = nodes;
 422 
 423     for (; gIter != NULL; gIter = gIter->next) {
 424         pe_node_t *node = (pe_node_t *) gIter->data;
 425 
 426         if (node && pcmk__str_eq(node->details->id, id, pcmk__str_casei)) {
 427             return node;
 428         }
 429     }
 430     /* error */
 431     return NULL;
 432 }
 433 
 434 pe_node_t *
 435 pe_find_node(GListPtr nodes, const char *uname)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437     GListPtr gIter = nodes;
 438 
 439     for (; gIter != NULL; gIter = gIter->next) {
 440         pe_node_t *node = (pe_node_t *) gIter->data;
 441 
 442         if (node && pcmk__str_eq(node->details->uname, uname, pcmk__str_casei)) {
 443             return node;
 444         }
 445     }
 446     /* error */
 447     return NULL;
 448 }

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