pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
status.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <crm_internal.h>
20 
21 #include <sys/param.h>
22 
23 #include <crm/crm.h>
24 #include <crm/msg_xml.h>
25 #include <crm/common/xml.h>
26 
27 #include <glib.h>
28 
29 #include <crm/pengine/internal.h>
30 #include <unpack.h>
31 
32 #define MEMCHECK_STAGE_0 0
33 
34 #define check_and_exit(stage) cleanup_calculations(data_set); \
35  crm_mem_stats(NULL); \
36  crm_err("Exiting: stage %d", stage); \
37  crm_exit(pcmk_err_generic);
38 
51 {
52  pe_working_set_t *data_set = calloc(1, sizeof(pe_working_set_t));
53 
54  if (data_set != NULL) {
55  set_working_set_defaults(data_set);
56  }
57  return data_set;
58 }
59 
65 void
67 {
68  if (data_set != NULL) {
69  pe_reset_working_set(data_set);
70  free(data_set);
71  }
72 }
73 
74 /*
75  * Unpack everything
76  * At the end you'll have:
77  * - A list of nodes
78  * - A list of resources (each with any dependencies on other resources)
79  * - A list of constraints between resources and nodes
80  * - A list of constraints between start/stop actions
81  * - A list of nodes that need to be stonith'd
82  * - A list of nodes that need to be shutdown
83  * - A list of the possible stop/start actions (without dependencies)
84  */
85 gboolean
87 {
88  xmlNode *config = get_xpath_object("//"XML_CIB_TAG_CRMCONFIG, data_set->input, LOG_TRACE);
89  xmlNode *cib_nodes = get_xpath_object("//"XML_CIB_TAG_NODES, data_set->input, LOG_TRACE);
90  xmlNode *cib_resources = get_xpath_object("//"XML_CIB_TAG_RESOURCES, data_set->input, LOG_TRACE);
91  xmlNode *cib_status = get_xpath_object("//"XML_CIB_TAG_STATUS, data_set->input, LOG_TRACE);
92  xmlNode *cib_tags = get_xpath_object("//"XML_CIB_TAG_TAGS, data_set->input, LOG_TRACE);
93  const char *value = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM);
94 
95  crm_trace("Beginning unpack");
96  pe_dataset = data_set;
97 
98  /* reset remaining global variables */
99  data_set->failed = create_xml_node(NULL, "failed-ops");
100 
101  if (data_set->input == NULL) {
102  return FALSE;
103  }
104 
105  if (data_set->now == NULL) {
106  data_set->now = crm_time_new(NULL);
107  }
108 
109  if (data_set->dc_uuid == NULL) {
110  data_set->dc_uuid = crm_element_value_copy(data_set->input,
112  }
113 
114  clear_bit(data_set->flags, pe_flag_have_quorum);
115  if (crm_is_true(value)) {
116  set_bit(data_set->flags, pe_flag_have_quorum);
117  }
118 
119  data_set->op_defaults = get_xpath_object("//"XML_CIB_TAG_OPCONFIG, data_set->input, LOG_TRACE);
121 
122  unpack_config(config, data_set);
123 
124  if (is_not_set(data_set->flags, pe_flag_quick_location)
125  && is_not_set(data_set->flags, pe_flag_have_quorum)
126  && data_set->no_quorum_policy != no_quorum_ignore) {
127  crm_warn("Fencing and resource management disabled due to lack of quorum");
128  }
129 
130  unpack_nodes(cib_nodes, data_set);
131 
132  if(is_not_set(data_set->flags, pe_flag_quick_location)) {
133  unpack_remote_nodes(cib_resources, data_set);
134  }
135 
136  unpack_resources(cib_resources, data_set);
137  unpack_tags(cib_tags, data_set);
138 
139  if(is_not_set(data_set->flags, pe_flag_quick_location)) {
140  unpack_status(cib_status, data_set);
141  }
142 
143  if (is_not_set(data_set->flags, pe_flag_no_counts)) {
144  for (GList *item = data_set->resources; item != NULL;
145  item = item->next) {
146  ((pe_resource_t *) (item->data))->fns->count(item->data);
147  }
148  }
149 
150  set_bit(data_set->flags, pe_flag_have_status);
151  return TRUE;
152 }
153 
165 static void
166 pe_free_resources(GListPtr resources)
167 {
168  resource_t *rsc = NULL;
169  GListPtr iterator = resources;
170 
171  while (iterator != NULL) {
172  rsc = (resource_t *) iterator->data;
173  iterator = iterator->next;
174  rsc->fns->free(rsc);
175  }
176  if (resources != NULL) {
177  g_list_free(resources);
178  }
179 }
180 
181 static void
182 pe_free_actions(GListPtr actions)
183 {
184  GListPtr iterator = actions;
185 
186  while (iterator != NULL) {
187  pe_free_action(iterator->data);
188  iterator = iterator->next;
189  }
190  if (actions != NULL) {
191  g_list_free(actions);
192  }
193 }
194 
195 static void
196 pe_free_nodes(GListPtr nodes)
197 {
198  for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) {
199  pe_node_t *node = (pe_node_t *) iterator->data;
200 
201  // Shouldn't be possible, but to be safe ...
202  if (node == NULL) {
203  continue;
204  }
205  if (node->details == NULL) {
206  free(node);
207  continue;
208  }
209 
210  /* This is called after pe_free_resources(), which means that we can't
211  * use node->details->uname for Pacemaker Remote nodes.
212  */
213  crm_trace("Freeing node %s", (is_remote_node(node)?
214  "(Pacemaker Remote)" : node->details->uname));
215 
216  if (node->details->attrs != NULL) {
217  g_hash_table_destroy(node->details->attrs);
218  }
219  if (node->details->utilization != NULL) {
220  g_hash_table_destroy(node->details->utilization);
221  }
222  if (node->details->digest_cache != NULL) {
223  g_hash_table_destroy(node->details->digest_cache);
224  }
225  g_list_free(node->details->running_rsc);
226  g_list_free(node->details->allocated_rsc);
227  free(node->details);
228  free(node);
229  }
230  if (nodes != NULL) {
231  g_list_free(nodes);
232  }
233 }
234 
235 static void
236 pe__free_ordering(GListPtr constraints)
237 {
238  GListPtr iterator = constraints;
239 
240  while (iterator != NULL) {
241  pe__ordering_t *order = iterator->data;
242 
243  iterator = iterator->next;
244 
245  free(order->lh_action_task);
246  free(order->rh_action_task);
247  free(order);
248  }
249  if (constraints != NULL) {
250  g_list_free(constraints);
251  }
252 }
253 
254 static void
255 pe__free_location(GListPtr constraints)
256 {
257  GListPtr iterator = constraints;
258 
259  while (iterator != NULL) {
260  pe__location_t *cons = iterator->data;
261 
262  iterator = iterator->next;
263 
264  g_list_free_full(cons->node_list_rh, free);
265  free(cons->id);
266  free(cons);
267  }
268  if (constraints != NULL) {
269  g_list_free(constraints);
270  }
271 }
272 
281 void
283 {
284  pe_dataset = NULL;
285  if (data_set == NULL) {
286  return;
287  }
288 
289  clear_bit(data_set->flags, pe_flag_have_status);
290  if (data_set->config_hash != NULL) {
291  g_hash_table_destroy(data_set->config_hash);
292  }
293 
294  if (data_set->singletons != NULL) {
295  g_hash_table_destroy(data_set->singletons);
296  }
297 
298  if (data_set->tickets) {
299  g_hash_table_destroy(data_set->tickets);
300  }
301 
302  if (data_set->template_rsc_sets) {
303  g_hash_table_destroy(data_set->template_rsc_sets);
304  }
305 
306  if (data_set->tags) {
307  g_hash_table_destroy(data_set->tags);
308  }
309 
310  free(data_set->dc_uuid);
311 
312  crm_trace("deleting resources");
313  pe_free_resources(data_set->resources);
314 
315  crm_trace("deleting actions");
316  pe_free_actions(data_set->actions);
317 
318  crm_trace("deleting nodes");
319  pe_free_nodes(data_set->nodes);
320 
321  pe__free_param_checks(data_set);
322  g_list_free(data_set->stop_needed);
323  free_xml(data_set->graph);
324  crm_time_free(data_set->now);
325  free_xml(data_set->input);
326  free_xml(data_set->failed);
327 
328  set_working_set_defaults(data_set);
329 
330  CRM_CHECK(data_set->ordering_constraints == NULL,;
331  );
332  CRM_CHECK(data_set->placement_constraints == NULL,;
333  );
334 }
335 
341 void
343 {
344  if (data_set == NULL) {
345  return;
346  }
347 
348  crm_trace("Deleting %d ordering constraints",
349  g_list_length(data_set->ordering_constraints));
350  pe__free_ordering(data_set->ordering_constraints);
351  data_set->ordering_constraints = NULL;
352 
353  crm_trace("Deleting %d location constraints",
354  g_list_length(data_set->placement_constraints));
355  pe__free_location(data_set->placement_constraints);
356  data_set->placement_constraints = NULL;
357 
358  crm_trace("Deleting %d colocation constraints",
359  g_list_length(data_set->colocation_constraints));
360  g_list_free_full(data_set->colocation_constraints, free);
361  data_set->colocation_constraints = NULL;
362 
363  crm_trace("Deleting %d ticket constraints",
364  g_list_length(data_set->ticket_constraints));
365  g_list_free_full(data_set->ticket_constraints, free);
366  data_set->ticket_constraints = NULL;
367 
368  cleanup_calculations(data_set);
369 }
370 
371 void
373 {
374  pe_dataset = data_set;
375  memset(data_set, 0, sizeof(pe_working_set_t));
376 
377  data_set->order_id = 1;
378  data_set->action_id = 1;
380 
381  data_set->flags = 0x0ULL;
386 #ifdef DEFAULT_CONCURRENT_FENCING_TRUE
388 #endif
389 }
390 
391 resource_t *
392 pe_find_resource(GListPtr rsc_list, const char *id)
393 {
394  return pe_find_resource_with_flags(rsc_list, id, pe_find_renamed);
395 }
396 
397 resource_t *
398 pe_find_resource_with_flags(GListPtr rsc_list, const char *id, enum pe_find flags)
399 {
400  GListPtr rIter = NULL;
401 
402  for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
403  resource_t *parent = rIter->data;
404 
405  resource_t *match =
406  parent->fns->find_rsc(parent, id, NULL, flags);
407  if (match != NULL) {
408  return match;
409  }
410  }
411  crm_trace("No match for %s", id);
412  return NULL;
413 }
414 
415 node_t *
416 pe_find_node_any(GListPtr nodes, const char *id, const char *uname)
417 {
418  node_t *match = pe_find_node_id(nodes, id);
419 
420  if (match) {
421  return match;
422  }
423  crm_trace("Looking up %s via its uname instead", uname);
424  return pe_find_node(nodes, uname);
425 }
426 
427 node_t *
428 pe_find_node_id(GListPtr nodes, const char *id)
429 {
430  GListPtr gIter = nodes;
431 
432  for (; gIter != NULL; gIter = gIter->next) {
433  node_t *node = (node_t *) gIter->data;
434 
435  if (node && safe_str_eq(node->details->id, id)) {
436  return node;
437  }
438  }
439  /* error */
440  return NULL;
441 }
442 
443 node_t *
444 pe_find_node(GListPtr nodes, const char *uname)
445 {
446  GListPtr gIter = nodes;
447 
448  for (; gIter != NULL; gIter = gIter->next) {
449  node_t *node = (node_t *) gIter->data;
450 
451  if (node && safe_str_eq(node->details->uname, uname)) {
452  return node;
453  }
454  }
455  /* error */
456  return NULL;
457 }
GHashTable * tags
Definition: status.h:148
#define LOG_TRACE
Definition: logging.h:29
gboolean unpack_config(xmlNode *config, pe_working_set_t *data_set)
Definition: unpack.c:180
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
GListPtr nodes
Definition: status.h:125
#define pe_flag_no_counts
Don&#39;t count total, disabled and blocked resource instances.
Definition: status.h:96
const char * uname
Definition: status.h:173
A dumping ground.
xmlNode * failed
Definition: status.h:133
void set_working_set_defaults(pe_working_set_t *data_set)
Definition: status.c:372
const char * id
Definition: status.h:172
void(* free)(resource_t *)
Definition: complex.h:41
xmlNode * op_defaults
Definition: status.h:134
GListPtr running_rsc
Definition: status.h:187
resource_t * pe_find_resource_with_flags(GListPtr rsc_list, const char *id, enum pe_find flags)
Definition: status.c:398
#define pe_flag_stop_rsc_orphans
Definition: status.h:79
node_t * pe_find_node_any(GListPtr nodes, const char *id, const char *uname)
Definition: status.c:416
GListPtr resources
Definition: status.h:126
#define XML_ATTR_DC_UUID
Definition: msg_xml.h:112
no_quorum_policy_t no_quorum_policy
Definition: status.h:117
void cleanup_calculations(pe_working_set_t *data_set)
Reset working set to default state without freeing it or constraints.
Definition: status.c:282
#define clear_bit(word, bit)
Definition: crm_internal.h:211
GHashTable * tickets
Definition: status.h:120
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:161
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:224
char * dc_uuid
Definition: status.h:108
gboolean unpack_resources(xmlNode *xml_resources, pe_working_set_t *data_set)
Definition: unpack.c:765
GListPtr placement_constraints
Definition: status.h:127
GHashTable * utilization
Definition: status.h:195
#define XML_CIB_TAG_RESOURCES
Definition: msg_xml.h:160
char uname[MAX_NAME]
Definition: internal.h:81
gboolean is_remote_node(node_t *node)
Definition: remote.c:52
struct node_shared_s * details
Definition: status.h:213
gboolean unpack_status(xmlNode *status, pe_working_set_t *data_set)
Definition: unpack.c:1193
#define crm_warn(fmt, args...)
Definition: logging.h:275
#define set_bit(word, bit)
Definition: crm_internal.h:210
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:570
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:393
gboolean unpack_nodes(xmlNode *xml_nodes, pe_working_set_t *data_set)
Definition: unpack.c:548
xmlNode * rsc_defaults
Definition: status.h:135
resource_object_functions_t * fns
Definition: status.h:301
GHashTable * digest_cache
Definition: status.h:198
pe_working_set_t * pe_dataset
Definition: utils.c:32
#define crm_trace(fmt, args...)
Definition: logging.h:280
gboolean unpack_remote_nodes(xmlNode *xml_resources, pe_working_set_t *data_set)
Definition: unpack.c:636
pe_find
Definition: status.h:60
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:90
GListPtr actions
Definition: status.h:132
Wrappers for and extensions to libxml2.
GHashTable * config_hash
Definition: status.h:119
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1977
node_t * pe_find_node(GListPtr nodes, const char *uname)
Definition: status.c:444
void free_xml(xmlNode *child)
Definition: xml.c:2108
xmlNode * input
Definition: status.h:104
void pe__free_param_checks(pe_working_set_t *data_set)
Definition: remote.c:258
GListPtr ordering_constraints
Definition: status.h:128
GListPtr colocation_constraints
Definition: status.h:129
resource_t * pe_find_resource(GListPtr rsc_list, const char *id)
Definition: status.c:392
node_t * pe_find_node_id(GListPtr nodes, const char *id)
Definition: status.c:428
void pe_free_working_set(pe_working_set_t *data_set)
Free a working set.
Definition: status.c:66
gboolean cluster_status(pe_working_set_t *data_set)
Definition: status.c:86
#define pe_flag_have_status
Definition: status.h:88
#define pe_flag_quick_location
Definition: status.h:91
resource_t *(* find_rsc)(resource_t *parent, const char *search, node_t *node, int flags)
Definition: complex.h:34
GListPtr ticket_constraints
Definition: status.h:130
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:99
#define XML_CIB_TAG_CRMCONFIG
Definition: msg_xml.h:164
#define XML_CIB_TAG_RSCCONFIG
Definition: msg_xml.h:166
GHashTable * attrs
Definition: status.h:192
void pe_free_action(action_t *action)
Definition: utils.c:1404
#define pe_flag_have_quorum
Definition: status.h:69
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:159
#define XML_CIB_TAG_TAGS
Definition: msg_xml.h:422
#define pe_flag_is_managed_default
Definition: status.h:71
Definition: status.h:209
#define pe_flag_stop_action_orphans
Definition: status.h:80
gboolean crm_is_true(const char *s)
Definition: strings.c:197
#define pe_flag_symmetric_cluster
Definition: status.h:70
GHashTable * singletons
Definition: status.h:123
unsigned long long flags
Definition: status.h:113
gboolean unpack_tags(xmlNode *xml_tags, pe_working_set_t *data_set)
Definition: unpack.c:827
#define safe_str_eq(a, b)
Definition: util.h:74
#define XML_CIB_TAG_OPCONFIG
Definition: msg_xml.h:165
GList * GListPtr
Definition: crm.h:210
crm_time_t * now
Definition: status.h:105
GHashTable * template_rsc_sets
Definition: status.h:146
#define pe_flag_concurrent_fencing
Definition: status.h:77
uint64_t flags
Definition: remote.c:156
pe_working_set_t * pe_new_working_set()
Create a new working set.
Definition: status.c:50
GList * stop_needed
Definition: status.h:154
void pe_reset_working_set(pe_working_set_t *data_set)
Reset a working set to default state without freeing it.
Definition: status.c:342
GListPtr allocated_rsc
Definition: status.h:188
xmlNode * graph
Definition: status.h:144
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:116