pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
status.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 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 
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 /*
60  * Unpack everything
61  * At the end you'll have:
62  * - A list of nodes
63  * - A list of resources (each with any dependencies on other resources)
64  * - A list of constraints between resources and nodes
65  * - A list of constraints between start/stop actions
66  * - A list of nodes that need to be stonith'd
67  * - A list of nodes that need to be shutdown
68  * - A list of the possible stop/start actions (without dependencies)
69  */
70 gboolean
72 {
73  xmlNode *section = NULL;
74 
75  if ((scheduler == NULL) || (scheduler->input == NULL)) {
76  return FALSE;
77  }
78 
79  crm_trace("Beginning unpack");
80 
81  if (scheduler->failed != NULL) {
83  }
84  scheduler->failed = create_xml_node(NULL, "failed-ops");
85 
86  if (scheduler->now == NULL) {
87  scheduler->now = crm_time_new(NULL);
88  }
89 
90  if (scheduler->dc_uuid == NULL) {
93  }
94 
97  } else {
99  }
100 
105 
107  LOG_TRACE);
108  unpack_config(section, scheduler);
109 
110  if (!pcmk_any_flags_set(scheduler->flags,
113  crm_warn("Fencing and resource management disabled due to lack of quorum");
114  }
115 
117  LOG_TRACE);
118  unpack_nodes(section, scheduler);
119 
121  LOG_TRACE);
123  unpack_remote_nodes(section, scheduler);
124  }
125  unpack_resources(section, scheduler);
126 
128  LOG_NEVER);
129  unpack_tags(section, scheduler);
130 
133  LOG_TRACE);
134  unpack_status(section, scheduler);
135  }
136 
138  for (GList *item = scheduler->resources; item != NULL;
139  item = item->next) {
140  ((pcmk_resource_t *) (item->data))->fns->count(item->data);
141  }
142  crm_trace("Cluster resource count: %d (%d disabled, %d blocked)",
145  }
146 
148  return TRUE;
149 }
150 
162 static void
163 pe_free_resources(GList *resources)
164 {
165  pcmk_resource_t *rsc = NULL;
166  GList *iterator = resources;
167 
168  while (iterator != NULL) {
169  rsc = (pcmk_resource_t *) iterator->data;
170  iterator = iterator->next;
171  rsc->fns->free(rsc);
172  }
173  if (resources != NULL) {
174  g_list_free(resources);
175  }
176 }
177 
178 static void
179 pe_free_actions(GList *actions)
180 {
181  GList *iterator = actions;
182 
183  while (iterator != NULL) {
184  pe_free_action(iterator->data);
185  iterator = iterator->next;
186  }
187  if (actions != NULL) {
188  g_list_free(actions);
189  }
190 }
191 
192 static void
193 pe_free_nodes(GList *nodes)
194 {
195  for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) {
196  pcmk_node_t *node = (pcmk_node_t *) iterator->data;
197 
198  // Shouldn't be possible, but to be safe ...
199  if (node == NULL) {
200  continue;
201  }
202  if (node->details == NULL) {
203  free(node);
204  continue;
205  }
206 
207  /* This is called after pe_free_resources(), which means that we can't
208  * use node->details->uname for Pacemaker Remote nodes.
209  */
210  crm_trace("Freeing node %s", (pe__is_guest_or_remote_node(node)?
211  "(guest or remote)" : pe__node_name(node)));
212 
213  if (node->details->attrs != NULL) {
214  g_hash_table_destroy(node->details->attrs);
215  }
216  if (node->details->utilization != NULL) {
217  g_hash_table_destroy(node->details->utilization);
218  }
219  if (node->details->digest_cache != NULL) {
220  g_hash_table_destroy(node->details->digest_cache);
221  }
222  g_list_free(node->details->running_rsc);
223  g_list_free(node->details->allocated_rsc);
224  free(node->details);
225  free(node);
226  }
227  if (nodes != NULL) {
228  g_list_free(nodes);
229  }
230 }
231 
232 static void
233 pe__free_ordering(GList *constraints)
234 {
235  GList *iterator = constraints;
236 
237  while (iterator != NULL) {
238  pe__ordering_t *order = iterator->data;
239 
240  iterator = iterator->next;
241 
242  free(order->lh_action_task);
243  free(order->rh_action_task);
244  free(order);
245  }
246  if (constraints != NULL) {
247  g_list_free(constraints);
248  }
249 }
250 
251 static void
252 pe__free_location(GList *constraints)
253 {
254  GList *iterator = constraints;
255 
256  while (iterator != NULL) {
257  pe__location_t *cons = iterator->data;
258 
259  iterator = iterator->next;
260 
261  g_list_free_full(cons->node_list_rh, free);
262  free(cons->id);
263  free(cons);
264  }
265  if (constraints != NULL) {
266  g_list_free(constraints);
267  }
268 }
269 
278 void
280 {
281  if (scheduler == NULL) {
282  return;
283  }
284 
286  if (scheduler->config_hash != NULL) {
287  g_hash_table_destroy(scheduler->config_hash);
288  }
289 
290  if (scheduler->singletons != NULL) {
291  g_hash_table_destroy(scheduler->singletons);
292  }
293 
294  if (scheduler->tickets) {
295  g_hash_table_destroy(scheduler->tickets);
296  }
297 
299  g_hash_table_destroy(scheduler->template_rsc_sets);
300  }
301 
302  if (scheduler->tags) {
303  g_hash_table_destroy(scheduler->tags);
304  }
305 
306  free(scheduler->dc_uuid);
307 
308  crm_trace("deleting resources");
309  pe_free_resources(scheduler->resources);
310 
311  crm_trace("deleting actions");
312  pe_free_actions(scheduler->actions);
313 
314  crm_trace("deleting nodes");
315  pe_free_nodes(scheduler->nodes);
316 
318  g_list_free(scheduler->stop_needed);
323 
325 
327  );
329  );
330 }
331 
337 void
339 {
340  if (scheduler == NULL) {
341  return;
342  }
343 
344  crm_trace("Deleting %d ordering constraints",
345  g_list_length(scheduler->ordering_constraints));
346  pe__free_ordering(scheduler->ordering_constraints);
348 
349  crm_trace("Deleting %d location constraints",
350  g_list_length(scheduler->placement_constraints));
351  pe__free_location(scheduler->placement_constraints);
353 
354  crm_trace("Deleting %d colocation constraints",
355  g_list_length(scheduler->colocation_constraints));
356  g_list_free_full(scheduler->colocation_constraints, free);
358 
359  crm_trace("Deleting %d ticket constraints",
360  g_list_length(scheduler->ticket_constraints));
361  g_list_free_full(scheduler->ticket_constraints, free);
363 
365 }
366 
367 void
369 {
370  void *priv = scheduler->priv;
371 
372  memset(scheduler, 0, sizeof(pcmk_scheduler_t));
373 
374  scheduler->priv = priv;
375  scheduler->order_id = 1;
376  scheduler->action_id = 1;
378 
379  scheduler->flags = 0x0ULL;
380 
385  if (!strcmp(PCMK__CONCURRENT_FENCING_DEFAULT, "true")) {
387  }
388 }
389 
391 pe_find_resource(GList *rsc_list, const char *id)
392 {
394 }
395 
397 pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
398 {
399  GList *rIter = NULL;
400 
401  for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
402  pcmk_resource_t *parent = rIter->data;
403 
404  pcmk_resource_t *match =
405  parent->fns->find_rsc(parent, id, NULL, flags);
406  if (match != NULL) {
407  return match;
408  }
409  }
410  crm_trace("No match for %s", id);
411  return NULL;
412 }
413 
425 pcmk_node_t *
426 pe_find_node_any(const GList *nodes, const char *id, const char *uname)
427 {
428  pcmk_node_t *match = NULL;
429 
430  if (id != NULL) {
431  match = pe_find_node_id(nodes, id);
432  }
433  if ((match == NULL) && (uname != NULL)) {
434  match = pe_find_node(nodes, uname);
435  }
436  return match;
437 }
438 
447 pcmk_node_t *
448 pe_find_node_id(const GList *nodes, const char *id)
449 {
450  for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
451  pcmk_node_t *node = (pcmk_node_t *) iter->data;
452 
453  /* @TODO Whether node IDs should be considered case-sensitive should
454  * probably depend on the node type, so functionizing the comparison
455  * would be worthwhile
456  */
457  if (pcmk__str_eq(node->details->id, id, pcmk__str_casei)) {
458  return node;
459  }
460  }
461  return NULL;
462 }
463 
472 pcmk_node_t *
473 pe_find_node(const GList *nodes, const char *node_name)
474 {
475  for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
476  pcmk_node_t *node = (pcmk_node_t *) iter->data;
477 
478  if (pcmk__str_eq(node->details->uname, node_name, pcmk__str_casei)) {
479  return node;
480  }
481  }
482  return NULL;
483 }
GHashTable * tags
Configuration tags (ID -> pcmk_tag_t *)
Definition: scheduler.h:218
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
enum pe_quorum_policy no_quorum_policy
Response to loss of quorum.
Definition: scheduler.h:186
A dumping ground.
bool pe__is_guest_or_remote_node(const pcmk_node_t *node)
Definition: remote.c:41
xmlNode * failed
History entries of failed actions.
Definition: scheduler.h:205
GHashTable * attrs
Node attributes.
Definition: nodes.h:115
void pe_free_working_set(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition: status.c:50
Whether cluster is symmetric (via symmetric-cluster property)
Definition: scheduler.h:74
pe_find
Search options for resources (exact resource ID always matches)
Definition: resources.h:197
Whether partition has quorum (via have-quorum property)
Definition: scheduler.h:71
xmlNode * op_defaults
Configured operation defaults.
Definition: scheduler.h:206
pcmk_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition: status.c:397
pcmk_scheduler_t * pe_new_working_set(void)
Create a new object to hold scheduler data.
Definition: status.c:34
#define pe__set_working_set_flags(scheduler, flags_to_set)
Definition: internal.h:52
#define XML_ATTR_DC_UUID
Definition: msg_xml.h:162
Whether the CIB status section has been parsed yet.
Definition: scheduler.h:131
Whether concurrent fencing is allowed (via concurrent-fencing property)
Definition: scheduler.h:89
GList * actions
Scheduled actions.
Definition: scheduler.h:204
int order_id
ID to use for next created ordering.
Definition: scheduler.h:210
G_GNUC_INTERNAL gboolean unpack_remote_nodes(xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
Definition: unpack.c:674
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:905
GHashTable * tickets
Definition: scheduler.h:190
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:206
Implementation of pcmk_scheduler_t.
Definition: scheduler.h:172
#define LOG_NEVER
Definition: logging.h:48
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:211
G_GNUC_INTERNAL gboolean unpack_resources(const xmlNode *xml_resources, pcmk_scheduler_t *scheduler)
Definition: unpack.c:816
char * dc_uuid
Node ID of designated controller.
Definition: scheduler.h:177
int ninstances
Total number of resource instances.
Definition: scheduler.h:224
#define PCMK__CONCURRENT_FENCING_DEFAULT
Definition: config.h:556
GList * resources
Resources in cluster.
Definition: scheduler.h:196
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:448
GList * nodes
Nodes in cluster.
Definition: scheduler.h:195
Also match clone instance ID from resource history.
Definition: resources.h:199
G_GNUC_INTERNAL gboolean unpack_status(xmlNode *status, pcmk_scheduler_t *scheduler)
Definition: unpack.c:1319
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:205
GList * ticket_constraints
Definition: scheduler.h:202
#define crm_warn(fmt, args...)
Definition: logging.h:382
void(* free)(pcmk_resource_t *rsc)
Free all memory used by a resource.
Definition: resources.h:347
Implementation of pcmk_resource_t.
Definition: resources.h:399
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:644
gboolean cluster_status(pcmk_scheduler_t *scheduler)
Definition: status.c:71
void pe__free_param_checks(pcmk_scheduler_t *scheduler)
Definition: remote.c:268
xmlNode * rsc_defaults
Configured resource defaults.
Definition: scheduler.h:207
void set_working_set_defaults(pcmk_scheduler_t *scheduler)
Definition: status.c:368
#define crm_trace(fmt, args...)
Definition: logging.h:387
void * priv
For Pacemaker use only.
Definition: scheduler.h:229
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:99
int blocked_resources
Number of blocked resources in cluster.
Definition: scheduler.h:219
int action_id
ID to use for next created action.
Definition: scheduler.h:211
struct pe_node_shared_s * details
Basic node information.
Definition: nodes.h:134
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:145
const char * uname
Node name in cluster.
Definition: nodes.h:68
Wrappers for and extensions to libxml2.
GHashTable * config_hash
Cluster properties.
Definition: scheduler.h:187
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:638
G_GNUC_INTERNAL gboolean unpack_nodes(xmlNode *xml_nodes, pcmk_scheduler_t *scheduler)
Definition: unpack.c:597
void free_xml(xmlNode *child)
Definition: xml.c:783
void cleanup_calculations(pcmk_scheduler_t *scheduler)
Reset scheduler data to defaults without freeing it or constraints.
Definition: status.c:279
Implementation of pcmk_node_t.
Definition: nodes.h:130
xmlNode * input
CIB XML.
Definition: scheduler.h:175
const char * id
Node ID at the cluster layer.
Definition: nodes.h:67
GList * running_rsc
List of resources active on node.
Definition: nodes.h:113
GList * ordering_constraints
Ordering constraints.
Definition: scheduler.h:198
pcmk_rsc_methods_t * fns
Resource object methods.
Definition: resources.h:416
pcmk_scheduler_t * scheduler
int disabled_resources
Number of disabled resources in cluster.
Definition: scheduler.h:220
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:109
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:208
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:210
GList * colocation_constraints
Colocation constraints.
Definition: scheduler.h:199
void pe_free_action(pcmk_action_t *action)
Definition: pe_actions.c:1382
GHashTable * utilization
Node utilization attributes.
Definition: nodes.h:116
char uname[MAX_NAME]
Definition: cpg.c:50
Skip counting of total, disabled, and blocked resource instances.
Definition: scheduler.h:149
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:426
GHashTable * digest_cache
Cache of calculated resource digests.
Definition: nodes.h:117
GList * placement_constraints
Location constraints.
Definition: scheduler.h:197
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:204
#define XML_CIB_TAG_TAGS
Definition: msg_xml.h:449
G_GNUC_INTERNAL gboolean unpack_config(xmlNode *config, pcmk_scheduler_t *scheduler)
Definition: unpack.c:212
GHashTable * singletons
Actions for which there can be only one (such as "fence node X")
Definition: scheduler.h:193
unsigned long long flags
Group of enum pcmk_scheduler_flags.
Definition: scheduler.h:183
GList * allocated_rsc
List of resources assigned to node.
Definition: nodes.h:114
const char * parent
Definition: cib.c:27
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
Definition: status.c:391
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:209
void pe_reset_working_set(pcmk_scheduler_t *scheduler)
Reset scheduler data to default state without freeing it.
Definition: status.c:338
crm_time_t * now
Current time for evaluation purposes.
Definition: scheduler.h:176
GHashTable * template_rsc_sets
Mappings of template ID to resource ID.
Definition: scheduler.h:213
#define pe__clear_working_set_flags(scheduler, flags_to_clear)
Definition: internal.h:58
uint64_t flags
Definition: remote.c:215
G_GNUC_INTERNAL gboolean unpack_tags(xmlNode *xml_tags, pcmk_scheduler_t *scheduler)
Definition: unpack.c:884
GList * stop_needed
Containers that need stop actions.
Definition: scheduler.h:222
xmlNode * graph
Transition graph.
Definition: scheduler.h:212
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:473