pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
status.c
Go to the documentation of this file.
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 <sys/param.h>
13 
14 #include <crm/crm.h>
15 #include <crm/common/xml.h>
17 
18 #include <glib.h>
19 
20 #include <crm/pengine/internal.h>
21 #include <pe_status_private.h>
22 
35 {
36  pcmk_scheduler_t *scheduler = calloc(1, sizeof(pcmk_scheduler_t));
37 
38  if (scheduler != NULL) {
40  }
41  return scheduler;
42 }
43 
49 void
51 {
52  if (scheduler != NULL) {
54  scheduler->priv = NULL;
55  free(scheduler);
56  }
57 }
58 
59 #define XPATH_DEPRECATED_RULES \
60  "//" PCMK_XE_OP_DEFAULTS "//" PCMK_XE_EXPRESSION \
61  "|//" PCMK_XE_OP "//" PCMK_XE_EXPRESSION
62 
69 static void
70 check_for_deprecated_rules(pcmk_scheduler_t *scheduler)
71 {
72  // @COMPAT Drop this function when support for the syntax is dropped
73  xmlNode *deprecated = get_xpath_object(XPATH_DEPRECATED_RULES,
75 
76  if (deprecated != NULL) {
78  "Support for rules with node attribute expressions in "
79  PCMK_XE_OP " or " PCMK_XE_OP_DEFAULTS " is deprecated "
80  "and will be dropped in a future release");
81  }
82 }
83 
84 /*
85  * Unpack everything
86  * At the end you'll have:
87  * - A list of nodes
88  * - A list of resources (each with any dependencies on other resources)
89  * - A list of constraints between resources and nodes
90  * - A list of constraints between start/stop actions
91  * - A list of nodes that need to be stonith'd
92  * - A list of nodes that need to be shutdown
93  * - A list of the possible stop/start actions (without dependencies)
94  */
95 gboolean
97 {
98  const char *new_version = NULL;
99  xmlNode *section = NULL;
100 
101  if ((scheduler == NULL) || (scheduler->input == NULL)) {
102  return FALSE;
103  }
104 
106 
107  if (pcmk__check_feature_set(new_version) != pcmk_rc_ok) {
108  pcmk__config_err("Can't process CIB with feature set '%s' greater than our own '%s'",
109  new_version, CRM_FEATURE_SET);
110  return FALSE;
111  }
112 
113  crm_trace("Beginning unpack");
114 
115  if (scheduler->failed != NULL) {
117  }
118  scheduler->failed = pcmk__xe_create(NULL, "failed-ops");
119 
120  if (scheduler->now == NULL) {
121  scheduler->now = crm_time_new(NULL);
122  }
123 
124  if (scheduler->dc_uuid == NULL) {
127  }
128 
131  } else {
133  }
134 
137  check_for_deprecated_rules(scheduler);
138 
141 
143  LOG_TRACE);
144  unpack_config(section, scheduler);
145 
146  if (!pcmk_any_flags_set(scheduler->flags,
149  pcmk__sched_warn("Fencing and resource management disabled "
150  "due to lack of quorum");
151  }
152 
154  unpack_nodes(section, scheduler);
155 
157  LOG_TRACE);
159  unpack_remote_nodes(section, scheduler);
160  }
161  unpack_resources(section, scheduler);
162 
164  LOG_TRACE);
166 
168  unpack_tags(section, scheduler);
169 
172  LOG_TRACE);
173  unpack_status(section, scheduler);
174  }
175 
177  for (GList *item = scheduler->resources; item != NULL;
178  item = item->next) {
179  ((pcmk_resource_t *) (item->data))->fns->count(item->data);
180  }
181  crm_trace("Cluster resource count: %d (%d disabled, %d blocked)",
184  }
185 
187  return TRUE;
188 }
189 
201 static void
202 pe_free_resources(GList *resources)
203 {
204  pcmk_resource_t *rsc = NULL;
205  GList *iterator = resources;
206 
207  while (iterator != NULL) {
208  rsc = (pcmk_resource_t *) iterator->data;
209  iterator = iterator->next;
210  rsc->fns->free(rsc);
211  }
212  if (resources != NULL) {
213  g_list_free(resources);
214  }
215 }
216 
217 static void
218 pe_free_actions(GList *actions)
219 {
220  GList *iterator = actions;
221 
222  while (iterator != NULL) {
223  pe_free_action(iterator->data);
224  iterator = iterator->next;
225  }
226  if (actions != NULL) {
227  g_list_free(actions);
228  }
229 }
230 
231 static void
232 pe_free_nodes(GList *nodes)
233 {
234  for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) {
235  pcmk_node_t *node = (pcmk_node_t *) iterator->data;
236 
237  // Shouldn't be possible, but to be safe ...
238  if (node == NULL) {
239  continue;
240  }
241  if (node->details == NULL) {
242  free(node);
243  continue;
244  }
245 
246  /* This is called after pe_free_resources(), which means that we can't
247  * use node->details->uname for Pacemaker Remote nodes.
248  */
249  crm_trace("Freeing node %s", (pcmk__is_pacemaker_remote_node(node)?
250  "(guest or remote)" : pcmk__node_name(node)));
251 
252  if (node->details->attrs != NULL) {
253  g_hash_table_destroy(node->details->attrs);
254  }
255  if (node->details->utilization != NULL) {
256  g_hash_table_destroy(node->details->utilization);
257  }
258  if (node->details->digest_cache != NULL) {
259  g_hash_table_destroy(node->details->digest_cache);
260  }
261  g_list_free(node->details->running_rsc);
262  g_list_free(node->details->allocated_rsc);
263  free(node->details);
264  free(node);
265  }
266  if (nodes != NULL) {
267  g_list_free(nodes);
268  }
269 }
270 
271 static void
272 pe__free_ordering(GList *constraints)
273 {
274  GList *iterator = constraints;
275 
276  while (iterator != NULL) {
277  pcmk__action_relation_t *order = iterator->data;
278 
279  iterator = iterator->next;
280 
281  free(order->task1);
282  free(order->task2);
283  free(order);
284  }
285  if (constraints != NULL) {
286  g_list_free(constraints);
287  }
288 }
289 
290 static void
291 pe__free_location(GList *constraints)
292 {
293  GList *iterator = constraints;
294 
295  while (iterator != NULL) {
296  pcmk__location_t *cons = iterator->data;
297 
298  iterator = iterator->next;
299 
300  g_list_free_full(cons->nodes, free);
301  free(cons->id);
302  free(cons);
303  }
304  if (constraints != NULL) {
305  g_list_free(constraints);
306  }
307 }
308 
317 void
319 {
320  if (scheduler == NULL) {
321  return;
322  }
323 
325  if (scheduler->config_hash != NULL) {
326  g_hash_table_destroy(scheduler->config_hash);
327  }
328 
329  if (scheduler->singletons != NULL) {
330  g_hash_table_destroy(scheduler->singletons);
331  }
332 
333  if (scheduler->tickets) {
334  g_hash_table_destroy(scheduler->tickets);
335  }
336 
338  g_hash_table_destroy(scheduler->template_rsc_sets);
339  }
340 
341  if (scheduler->tags) {
342  g_hash_table_destroy(scheduler->tags);
343  }
344 
345  free(scheduler->dc_uuid);
346 
347  crm_trace("deleting resources");
348  pe_free_resources(scheduler->resources);
349 
350  crm_trace("deleting actions");
351  pe_free_actions(scheduler->actions);
352 
353  crm_trace("deleting nodes");
354  pe_free_nodes(scheduler->nodes);
355 
357  g_list_free(scheduler->stop_needed);
362 
364 
366  );
368  );
369 }
370 
376 void
378 {
379  if (scheduler == NULL) {
380  return;
381  }
382 
383  crm_trace("Deleting %d ordering constraints",
384  g_list_length(scheduler->ordering_constraints));
385  pe__free_ordering(scheduler->ordering_constraints);
387 
388  crm_trace("Deleting %d location constraints",
389  g_list_length(scheduler->placement_constraints));
390  pe__free_location(scheduler->placement_constraints);
392 
393  crm_trace("Deleting %d colocation constraints",
394  g_list_length(scheduler->colocation_constraints));
395  g_list_free_full(scheduler->colocation_constraints, free);
397 
398  crm_trace("Deleting %d ticket constraints",
399  g_list_length(scheduler->ticket_constraints));
400  g_list_free_full(scheduler->ticket_constraints, free);
402 
404 }
405 
406 void
408 {
409  void *priv = scheduler->priv;
410 
411  memset(scheduler, 0, sizeof(pcmk_scheduler_t));
412 
413  scheduler->priv = priv;
414  scheduler->order_id = 1;
415  scheduler->action_id = 1;
417 
418  scheduler->flags = 0x0ULL;
419 
420 #if PCMK__CONCURRENT_FENCING_DEFAULT_TRUE
426 #else
431 #endif
432 }
433 
435 pe_find_resource(GList *rsc_list, const char *id)
436 {
438 }
439 
441 pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
442 {
443  GList *rIter = NULL;
444 
445  for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
446  pcmk_resource_t *parent = rIter->data;
447 
448  pcmk_resource_t *match =
449  parent->fns->find_rsc(parent, id, NULL, flags);
450  if (match != NULL) {
451  return match;
452  }
453  }
454  crm_trace("No match for %s", id);
455  return NULL;
456 }
457 
469 pcmk_node_t *
470 pe_find_node_any(const GList *nodes, const char *id, const char *uname)
471 {
472  pcmk_node_t *match = NULL;
473 
474  if (id != NULL) {
475  match = pe_find_node_id(nodes, id);
476  }
477  if ((match == NULL) && (uname != NULL)) {
478  match = pcmk__find_node_in_list(nodes, uname);
479  }
480  return match;
481 }
482 
491 pcmk_node_t *
492 pe_find_node_id(const GList *nodes, const char *id)
493 {
494  for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
495  pcmk_node_t *node = (pcmk_node_t *) iter->data;
496 
497  /* @TODO Whether node IDs should be considered case-sensitive should
498  * probably depend on the node type, so functionizing the comparison
499  * would be worthwhile
500  */
501  if (pcmk__str_eq(node->details->id, id, pcmk__str_casei)) {
502  return node;
503  }
504  }
505  return NULL;
506 }
507 
508 // Deprecated functions kept only for backward API compatibility
509 // LCOV_EXCL_START
510 
512 
521 pcmk_node_t *
522 pe_find_node(const GList *nodes, const char *node_name)
523 {
524  return pcmk__find_node_in_list(nodes, node_name);
525 }
526 
527 // LCOV_EXCL_STOP
528 // End deprecated API
GHashTable * tags
Definition: scheduler.h:253
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
enum pe_quorum_policy no_quorum_policy
Definition: scheduler.h:217
#define PCMK_XE_FENCING_TOPOLOGY
Definition: xml_names.h:118
A dumping ground.
xmlNode * failed
Definition: scheduler.h:240
GHashTable * attrs
Definition: nodes.h:143
#define PCMK_XE_OP_DEFAULTS
Definition: xml_names.h:147
void pe_free_working_set(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition: status.c:50
#define PCMK_XE_STATUS
Definition: xml_names.h:204
pe_find
Search options for resources (exact resource ID always matches)
Definition: resources.h:183
xmlNode * op_defaults
Definition: scheduler.h:241
#define PCMK_XE_RSC_DEFAULTS
Definition: xml_names.h:186
pcmk_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition: status.c:441
#define CRM_FEATURE_SET
Definition: crm.h:72
#define pcmk__config_err(fmt...)
#define PCMK_XA_HAVE_QUORUM
Definition: xml_names.h:295
pcmk_scheduler_t * pe_new_working_set(void)
Create a new object to hold scheduler data.
Definition: status.c:34
GList * actions
Definition: scheduler.h:239
G_GNUC_INTERNAL gboolean unpack_remote_nodes(xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
Definition: unpack.c:727
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:1020
GHashTable * tickets
Definition: scheduler.h:222
#define LOG_NEVER
Definition: logging.h:48
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:189
G_GNUC_INTERNAL gboolean unpack_resources(const xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
Definition: unpack.c:871
GList * resources
Definition: scheduler.h:231
pcmk_node_t * pe_find_node_id(const GList *nodes, const char *id)
Find a node by ID in a list of nodes.
Definition: status.c:492
Also match clone instance ID from resource history.
Definition: resources.h:185
G_GNUC_INTERNAL gboolean unpack_status(xmlNode *status, pcmk_scheduler_t *scheduler)
Definition: unpack.c:1437
GList * ticket_constraints
Definition: scheduler.h:237
void(* free)(pcmk_resource_t *rsc)
Definition: resources.h:336
pcmk_node_t * pcmk__find_node_in_list(const GList *nodes, const char *node_name)
Definition: nodes.c:150
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:758
gboolean cluster_status(pcmk_scheduler_t *scheduler)
Definition: status.c:96
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:458
void pe__free_param_checks(pcmk_scheduler_t *scheduler)
Definition: remote.c:232
xmlNode * rsc_defaults
Definition: scheduler.h:242
void set_working_set_defaults(pcmk_scheduler_t *scheduler)
Definition: status.c:407
#define crm_trace(fmt, args...)
Definition: logging.h:404
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:94
#define pcmk__clear_scheduler_flags(scheduler, flags_to_clear)
struct pe_node_shared_s * details
Definition: nodes.h:168
Wrappers for and extensions to libxml2.
GHashTable * config_hash
Definition: scheduler.h:219
G_GNUC_INTERNAL gboolean unpack_nodes(xmlNode *xml_nodes, pcmk_scheduler_t *scheduler)
Definition: unpack.c:638
void free_xml(xmlNode *child)
Definition: xml.c:958
void cleanup_calculations(pcmk_scheduler_t *scheduler)
Reset scheduler data to defaults without freeing it or constraints.
Definition: status.c:318
xmlNode * input
Definition: scheduler.h:196
#define pcmk__warn_once(wo_flag, fmt...)
#define PCMK_XA_DC_UUID
Definition: xml_names.h:258
const char * id
Definition: nodes.h:73
#define PCMK_XE_TAGS
Definition: xml_names.h:209
#define PCMK_XA_CRM_FEATURE_SET
Definition: xml_names.h:254
GList * running_rsc
Definition: nodes.h:140
G_GNUC_INTERNAL void pcmk__unpack_fencing_topology(const xmlNode *xml_fencing_topology, pcmk_scheduler_t *scheduler)
Definition: unpack.c:946
#define PCMK_XE_OP
Definition: xml_names.h:146
GList * ordering_constraints
Definition: scheduler.h:233
pcmk_rsc_methods_t * fns
Definition: resources.h:412
pcmk_scheduler_t * scheduler
int disabled_resources
Definition: scheduler.h:255
Deprecated Pacemaker scheduler utilities.
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:112
GList * colocation_constraints
Definition: scheduler.h:234
#define pcmk__sched_warn(fmt...)
void pe_free_action(pcmk_action_t *action)
Definition: pe_actions.c:1396
GHashTable * utilization
Definition: nodes.h:144
char uname[MAX_NAME]
Definition: cpg.c:53
pcmk_node_t * pe_find_node_any(const GList *nodes, const char *id, const char *uname)
Find a node by name or ID in a list of nodes.
Definition: status.c:470
GHashTable * digest_cache
Definition: nodes.h:145
GList * placement_constraints
Definition: scheduler.h:232
#define PCMK_XE_NODES
Definition: xml_names.h:142
G_GNUC_INTERNAL gboolean unpack_config(xmlNode *config, pcmk_scheduler_t *scheduler)
Definition: unpack.c:214
Location constraint object.
GHashTable * singletons
Definition: scheduler.h:225
unsigned long long flags
Definition: scheduler.h:211
GList * allocated_rsc
Definition: nodes.h:142
const char * parent
Definition: cib.c:27
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml.c:770
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
Definition: status.c:435
void pe_reset_working_set(pcmk_scheduler_t *scheduler)
Reset scheduler data to default state without freeing it.
Definition: status.c:377
crm_time_t * now
Definition: scheduler.h:198
#define PCMK_XE_RESOURCES
Definition: xml_names.h:179
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
GHashTable * template_rsc_sets
Definition: scheduler.h:248
uint64_t flags
Definition: remote.c:215
G_GNUC_INTERNAL gboolean unpack_tags(xmlNode *xml_tags, pcmk_scheduler_t *scheduler)
Definition: unpack.c:973
#define XPATH_DEPRECATED_RULES
Definition: status.c:59
#define PCMK_XE_CRM_CONFIG
Definition: xml_names.h:91
GList * stop_needed
Definition: scheduler.h:257
int pcmk__check_feature_set(const char *cib_version)
Definition: cib.c:184
xmlNode * graph
Definition: scheduler.h:247
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:150
pcmk_node_t * pe_find_node(const GList *nodes, const char *node_name)
Find a node by name in a list of nodes.
Definition: status.c:522