pacemaker  2.1.2-ada5c3b36
Scalable High-Availability cluster resource manager
status.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2021 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  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 
49 void
51 {
52  if (data_set != NULL) {
53  pe_reset_working_set(data_set);
54  data_set->priv = NULL;
55  free(data_set);
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 *config = get_xpath_object("//"XML_CIB_TAG_CRMCONFIG, data_set->input, LOG_TRACE);
74  xmlNode *cib_nodes = get_xpath_object("//"XML_CIB_TAG_NODES, data_set->input, LOG_TRACE);
75  xmlNode *cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
76  xmlNode *cib_status = get_xpath_object("//"XML_CIB_TAG_STATUS, data_set->input, LOG_TRACE);
77  xmlNode *cib_tags = get_xpath_object("//" XML_CIB_TAG_TAGS, data_set->input,
78  LOG_NEVER);
79  const char *value = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
80 
81  crm_trace("Beginning unpack");
82 
83  /* reset remaining global variables */
84  data_set->failed = create_xml_node(NULL, "failed-ops");
85 
86  if (data_set->input == NULL) {
87  return FALSE;
88  }
89 
90  if (data_set->now == NULL) {
91  data_set->now = crm_time_new(NULL);
92  }
93 
94  if (data_set->dc_uuid == NULL) {
95  data_set->dc_uuid = crm_element_value_copy(data_set->input,
97  }
98 
99  if (crm_is_true(value)) {
101  } else {
103  }
104 
106  data_set->input, LOG_NEVER);
108  data_set->input, LOG_NEVER);
109 
110  unpack_config(config, data_set);
111 
112  if (!pcmk_any_flags_set(data_set->flags,
114  && (data_set->no_quorum_policy != no_quorum_ignore)) {
115  crm_warn("Fencing and resource management disabled due to lack of quorum");
116  }
117 
118  unpack_nodes(cib_nodes, data_set);
119 
120  if (!pcmk_is_set(data_set->flags, pe_flag_quick_location)) {
121  unpack_remote_nodes(cib_resources, data_set);
122  }
123 
124  unpack_resources(cib_resources, data_set);
125  unpack_tags(cib_tags, data_set);
126 
127  if (!pcmk_is_set(data_set->flags, pe_flag_quick_location)) {
128  unpack_status(cib_status, data_set);
129  }
130 
131  if (!pcmk_is_set(data_set->flags, pe_flag_no_counts)) {
132  for (GList *item = data_set->resources; item != NULL;
133  item = item->next) {
134  ((pe_resource_t *) (item->data))->fns->count(item->data);
135  }
136  }
137 
139  return TRUE;
140 }
141 
153 static void
154 pe_free_resources(GList *resources)
155 {
156  pe_resource_t *rsc = NULL;
157  GList *iterator = resources;
158 
159  while (iterator != NULL) {
160  rsc = (pe_resource_t *) iterator->data;
161  iterator = iterator->next;
162  rsc->fns->free(rsc);
163  }
164  if (resources != NULL) {
165  g_list_free(resources);
166  }
167 }
168 
169 static void
170 pe_free_actions(GList *actions)
171 {
172  GList *iterator = actions;
173 
174  while (iterator != NULL) {
175  pe_free_action(iterator->data);
176  iterator = iterator->next;
177  }
178  if (actions != NULL) {
179  g_list_free(actions);
180  }
181 }
182 
183 static void
184 pe_free_nodes(GList *nodes)
185 {
186  for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) {
187  pe_node_t *node = (pe_node_t *) iterator->data;
188 
189  // Shouldn't be possible, but to be safe ...
190  if (node == NULL) {
191  continue;
192  }
193  if (node->details == NULL) {
194  free(node);
195  continue;
196  }
197 
198  /* This is called after pe_free_resources(), which means that we can't
199  * use node->details->uname for Pacemaker Remote nodes.
200  */
201  crm_trace("Freeing node %s", (pe__is_guest_or_remote_node(node)?
202  "(guest or remote)" : node->details->uname));
203 
204  if (node->details->attrs != NULL) {
205  g_hash_table_destroy(node->details->attrs);
206  }
207  if (node->details->utilization != NULL) {
208  g_hash_table_destroy(node->details->utilization);
209  }
210  if (node->details->digest_cache != NULL) {
211  g_hash_table_destroy(node->details->digest_cache);
212  }
213  g_list_free(node->details->running_rsc);
214  g_list_free(node->details->allocated_rsc);
215  free(node->details);
216  free(node);
217  }
218  if (nodes != NULL) {
219  g_list_free(nodes);
220  }
221 }
222 
223 static void
224 pe__free_ordering(GList *constraints)
225 {
226  GList *iterator = constraints;
227 
228  while (iterator != NULL) {
229  pe__ordering_t *order = iterator->data;
230 
231  iterator = iterator->next;
232 
233  free(order->lh_action_task);
234  free(order->rh_action_task);
235  free(order);
236  }
237  if (constraints != NULL) {
238  g_list_free(constraints);
239  }
240 }
241 
242 static void
243 pe__free_location(GList *constraints)
244 {
245  GList *iterator = constraints;
246 
247  while (iterator != NULL) {
248  pe__location_t *cons = iterator->data;
249 
250  iterator = iterator->next;
251 
252  g_list_free_full(cons->node_list_rh, free);
253  free(cons->id);
254  free(cons);
255  }
256  if (constraints != NULL) {
257  g_list_free(constraints);
258  }
259 }
260 
269 void
271 {
272  if (data_set == NULL) {
273  return;
274  }
275 
277  if (data_set->config_hash != NULL) {
278  g_hash_table_destroy(data_set->config_hash);
279  }
280 
281  if (data_set->singletons != NULL) {
282  g_hash_table_destroy(data_set->singletons);
283  }
284 
285  if (data_set->tickets) {
286  g_hash_table_destroy(data_set->tickets);
287  }
288 
289  if (data_set->template_rsc_sets) {
290  g_hash_table_destroy(data_set->template_rsc_sets);
291  }
292 
293  if (data_set->tags) {
294  g_hash_table_destroy(data_set->tags);
295  }
296 
297  free(data_set->dc_uuid);
298 
299  crm_trace("deleting resources");
300  pe_free_resources(data_set->resources);
301 
302  crm_trace("deleting actions");
303  pe_free_actions(data_set->actions);
304 
305  crm_trace("deleting nodes");
306  pe_free_nodes(data_set->nodes);
307 
308  pe__free_param_checks(data_set);
309  g_list_free(data_set->stop_needed);
310  free_xml(data_set->graph);
311  crm_time_free(data_set->now);
312  free_xml(data_set->input);
313  free_xml(data_set->failed);
314 
315  set_working_set_defaults(data_set);
316 
317  CRM_CHECK(data_set->ordering_constraints == NULL,;
318  );
319  CRM_CHECK(data_set->placement_constraints == NULL,;
320  );
321 }
322 
328 void
330 {
331  if (data_set == NULL) {
332  return;
333  }
334 
335  crm_trace("Deleting %d ordering constraints",
336  g_list_length(data_set->ordering_constraints));
337  pe__free_ordering(data_set->ordering_constraints);
338  data_set->ordering_constraints = NULL;
339 
340  crm_trace("Deleting %d location constraints",
341  g_list_length(data_set->placement_constraints));
342  pe__free_location(data_set->placement_constraints);
343  data_set->placement_constraints = NULL;
344 
345  crm_trace("Deleting %d colocation constraints",
346  g_list_length(data_set->colocation_constraints));
347  g_list_free_full(data_set->colocation_constraints, free);
348  data_set->colocation_constraints = NULL;
349 
350  crm_trace("Deleting %d ticket constraints",
351  g_list_length(data_set->ticket_constraints));
352  g_list_free_full(data_set->ticket_constraints, free);
353  data_set->ticket_constraints = NULL;
354 
355  cleanup_calculations(data_set);
356 }
357 
358 void
360 {
361  void *priv = data_set->priv;
362 
363  memset(data_set, 0, sizeof(pe_working_set_t));
364 
365  data_set->priv = priv;
366  data_set->order_id = 1;
367  data_set->action_id = 1;
368  data_set->no_quorum_policy = no_quorum_stop;
369 
370  data_set->flags = 0x0ULL;
371 
372  pe__set_working_set_flags(data_set,
376  if (!strcmp(PCMK__CONCURRENT_FENCING_DEFAULT, "true")) {
378  }
379 }
380 
382 pe_find_resource(GList *rsc_list, const char *id)
383 {
384  return pe_find_resource_with_flags(rsc_list, id, pe_find_renamed);
385 }
386 
388 pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
389 {
390  GList *rIter = NULL;
391 
392  for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
393  pe_resource_t *parent = rIter->data;
394 
395  pe_resource_t *match =
396  parent->fns->find_rsc(parent, id, NULL, flags);
397  if (match != NULL) {
398  return match;
399  }
400  }
401  crm_trace("No match for %s", id);
402  return NULL;
403 }
404 
405 pe_node_t *
406 pe_find_node_any(GList *nodes, const char *id, const char *uname)
407 {
408  pe_node_t *match = pe_find_node_id(nodes, id);
409 
410  if (match) {
411  return match;
412  }
413  crm_trace("Looking up %s via its uname instead", uname);
414  return pe_find_node(nodes, uname);
415 }
416 
417 pe_node_t *
418 pe_find_node_id(GList *nodes, const char *id)
419 {
420  GList *gIter = nodes;
421 
422  for (; gIter != NULL; gIter = gIter->next) {
423  pe_node_t *node = (pe_node_t *) gIter->data;
424 
425  if (node && pcmk__str_eq(node->details->id, id, pcmk__str_casei)) {
426  return node;
427  }
428  }
429  /* error */
430  return NULL;
431 }
432 
433 pe_node_t *
434 pe_find_node(GList *nodes, const char *uname)
435 {
436  GList *gIter = nodes;
437 
438  for (; gIter != NULL; gIter = gIter->next) {
439  pe_node_t *node = (pe_node_t *) gIter->data;
440 
441  if (node && pcmk__str_eq(node->details->uname, uname, pcmk__str_casei)) {
442  return node;
443  }
444  }
445  /* error */
446  return NULL;
447 }
GHashTable * tags
Definition: pe_types.h:180
#define LOG_TRACE
Definition: logging.h:36
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:225
pe_node_t * pe_find_node(GList *nodes, const char *uname)
Definition: status.c:434
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:149
A dumping ground.
xmlNode * failed
Definition: pe_types.h:165
#define pe_flag_stop_action_orphans
Definition: pe_types.h:104
bool pe__is_guest_or_remote_node(const pe_node_t *node)
Definition: remote.c:41
GHashTable * attrs
Definition: pe_types.h:234
pe_node_t * pe_find_node_any(GList *nodes, const char *id, const char *uname)
Definition: status.c:406
void set_working_set_defaults(pe_working_set_t *data_set)
Definition: status.c:359
pe_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition: status.c:388
G_GNUC_INTERNAL gboolean unpack_remote_nodes(xmlNode *xml_resources, pe_working_set_t *data_set)
Definition: unpack.c:622
#define pe_flag_concurrent_fencing
Definition: pe_types.h:101
#define pe_flag_symmetric_cluster
Definition: pe_types.h:95
xmlNode * op_defaults
Definition: pe_types.h:166
pe_resource_t * pe_find_resource(GList *rsc_list, const char *id)
Definition: status.c:382
resource_object_functions_t * fns
Definition: pe_types.h:333
G_GNUC_INTERNAL gboolean unpack_status(xmlNode *status, pe_working_set_t *data_set)
Definition: unpack.c:1242
#define XML_ATTR_DC_UUID
Definition: msg_xml.h:135
#define pe_flag_no_counts
Don&#39;t count total, disabled and blocked resource instances.
Definition: pe_types.h:126
#define pe_flag_have_status
Definition: pe_types.h:116
GList * actions
Definition: pe_types.h:164
int order_id
Deprecated (will be removed in a future release)
Definition: pe_types.h:172
void cleanup_calculations(pe_working_set_t *data_set)
Reset working set to default state without freeing it or constraints.
Definition: status.c:270
GHashTable * tickets
Definition: pe_types.h:152
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:181
#define pe_flag_have_quorum
Definition: pe_types.h:94
#define LOG_NEVER
Definition: logging.h:46
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
char * dc_uuid
Definition: pe_types.h:141
#define PCMK__CONCURRENT_FENCING_DEFAULT
Definition: config.h:517
GList * resources
Definition: pe_types.h:158
GList * nodes
Definition: pe_types.h:157
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:180
G_GNUC_INTERNAL gboolean unpack_tags(xmlNode *xml_tags, pe_working_set_t *data_set)
Definition: unpack.c:820
GList * ticket_constraints
Definition: pe_types.h:162
#define crm_warn(fmt, args...)
Definition: logging.h:358
pe_find
Determine behavior of pe_find_resource_with_flags()
Definition: pe_types.h:83
G_GNUC_INTERNAL gboolean unpack_nodes(xmlNode *xml_nodes, pe_working_set_t *data_set)
Definition: unpack.c:529
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:726
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
xmlNode * rsc_defaults
Definition: pe_types.h:167
#define crm_trace(fmt, args...)
Definition: logging.h:363
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
pe_node_t * pe_find_node_id(GList *nodes, const char *id)
Definition: status.c:418
struct pe_node_shared_s * details
Definition: pe_types.h:244
G_GNUC_INTERNAL gboolean unpack_resources(xmlNode *xml_resources, pe_working_set_t *data_set)
Definition: unpack.c:759
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:118
const char * uname
Definition: pe_types.h:209
Wrappers for and extensions to libxml2.
GHashTable * config_hash
Definition: pe_types.h:151
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
void(* free)(pe_resource_t *)
Definition: pe_types.h:55
void free_xml(xmlNode *child)
Definition: xml.c:824
xmlNode * input
Definition: pe_types.h:137
void pe__free_param_checks(pe_working_set_t *data_set)
Definition: remote.c:261
const char * id
Definition: pe_types.h:208
GList * running_rsc
Definition: pe_types.h:231
match resource ID or LRM history ID
Definition: pe_types.h:84
#define pe_flag_quick_location
Definition: pe_types.h:119
void pe_free_working_set(pe_working_set_t *data_set)
Free a working set.
Definition: status.c:50
gboolean cluster_status(pe_working_set_t *data_set)
Definition: status.c:71
GList * ordering_constraints
Definition: pe_types.h:160
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:92
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:184
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:186
GList * colocation_constraints
Definition: pe_types.h:161
GHashTable * utilization
Definition: pe_types.h:235
char uname[MAX_NAME]
Definition: cpg.c:50
#define pe__set_working_set_flags(working_set, flags_to_set)
Definition: internal.h:35
GHashTable * digest_cache
cache of calculated resource digests
Definition: pe_types.h:236
GList * placement_constraints
Definition: pe_types.h:159
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:179
#define XML_CIB_TAG_TAGS
Definition: msg_xml.h:429
gboolean crm_is_true(const char *s)
Definition: strings.c:416
GHashTable * singletons
Definition: pe_types.h:155
unsigned long long flags
Definition: pe_types.h:146
GList * allocated_rsc
Definition: pe_types.h:232
G_GNUC_INTERNAL gboolean unpack_config(xmlNode *config, pe_working_set_t *data_set)
Definition: unpack.c:197
pe_resource_t *(* find_rsc)(pe_resource_t *parent, const char *search, const pe_node_t *node, int flags)
Definition: pe_types.h:45
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:185
#define pe__clear_working_set_flags(working_set, flags_to_clear)
Definition: internal.h:41
crm_time_t * now
Definition: pe_types.h:138
GHashTable * template_rsc_sets
Definition: pe_types.h:178
uint64_t flags
Definition: remote.c:149
pe_working_set_t * pe_new_working_set()
Create a new working set.
Definition: status.c:34
GList * stop_needed
Definition: pe_types.h:186
void pe_reset_working_set(pe_working_set_t *data_set)
Reset a working set to default state without freeing it.
Definition: status.c:329
void pe_free_action(pe_action_t *action)
Definition: utils.c:1456
xmlNode * graph
Definition: pe_types.h:176
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:140
#define pe_flag_stop_rsc_orphans
Definition: pe_types.h:103