pacemaker  1.1.15-e174ec8
Scalable High-Availability cluster resource manager
unpack.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 #include <crm/crm.h>
23 #include <crm/msg_xml.h>
24 
25 #include <crm/common/xml.h>
26 #include <crm/transition.h>
27 #include <sys/stat.h>
28 
29 CRM_TRACE_INIT_DATA(transitioner);
30 
31 static crm_action_t *
32 unpack_action(synapse_t * parent, xmlNode * xml_action)
33 {
34  crm_action_t *action = NULL;
35  const char *value = crm_element_value(xml_action, XML_ATTR_ID);
36 
37  if (value == NULL) {
38  crm_err("Actions must have an id!");
39  crm_log_xml_trace(xml_action, "Action with missing id");
40  return NULL;
41  }
42 
43  action = calloc(1, sizeof(crm_action_t));
44  CRM_CHECK(action != NULL, return NULL);
45 
46  action->id = crm_parse_int(value, NULL);
47  action->type = action_type_rsc;
48  action->xml = copy_xml(xml_action);
49  action->synapse = parent;
50 
51  if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_RSC_OP)) {
52  action->type = action_type_rsc;
53 
54  } else if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_PSEUDO_EVENT)) {
55  action->type = action_type_pseudo;
56 
57  } else if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_CRM_EVENT)) {
58  action->type = action_type_crm;
59  }
60 
61  action->params = xml2list(action->xml);
62 
63  value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
64  if (value != NULL) {
65  action->timeout = crm_parse_int(value, NULL);
66  }
67 
68  /* Take start-delay into account for the timeout of the action timer */
69  value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
70  if (value != NULL) {
71  action->timeout += crm_parse_int(value, NULL);
72  }
73 
74  value = g_hash_table_lookup(action->params, "CRM_meta_interval");
75  if (value != NULL) {
76  action->interval = crm_parse_int(value, NULL);
77  }
78 
79  value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
80  if (value != NULL) {
81  crm_str_to_boolean(value, &(action->can_fail));
82  }
83 
84  crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
85 
86  return action;
87 }
88 
89 static synapse_t *
90 unpack_synapse(crm_graph_t * new_graph, xmlNode * xml_synapse)
91 {
92  const char *value = NULL;
93  xmlNode *inputs = NULL;
94  xmlNode *action_set = NULL;
95  synapse_t *new_synapse = NULL;
96 
97  CRM_CHECK(xml_synapse != NULL, return NULL);
98  crm_trace("looking in synapse %s", ID(xml_synapse));
99 
100  new_synapse = calloc(1, sizeof(synapse_t));
101  new_synapse->id = crm_parse_int(ID(xml_synapse), NULL);
102 
103  value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
104  if (value != NULL) {
105  new_synapse->priority = crm_parse_int(value, NULL);
106  }
107 
108  new_graph->num_synapses++;
109  CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
110  return NULL);
111 
112  crm_trace("look for actions in synapse %s", crm_element_value(xml_synapse, XML_ATTR_ID));
113 
114  for (action_set = __xml_first_child(xml_synapse); action_set != NULL;
115  action_set = __xml_next(action_set)) {
116  if (crm_str_eq((const char *)action_set->name, "action_set", TRUE)) {
117  xmlNode *action = NULL;
118 
119  for (action = __xml_first_child(action_set); action != NULL;
120  action = __xml_next(action)) {
121  crm_action_t *new_action = unpack_action(new_synapse, action);
122 
123  new_graph->num_actions++;
124 
125  if (new_action == NULL) {
126  continue;
127  }
128  crm_trace("Adding action %d to synapse %d", new_action->id, new_synapse->id);
129 
130  new_synapse->actions = g_list_append(new_synapse->actions, new_action);
131  }
132  }
133  }
134 
135  crm_trace("look for inputs in synapse %s", ID(xml_synapse));
136 
137  for (inputs = __xml_first_child(xml_synapse); inputs != NULL; inputs = __xml_next(inputs)) {
138  if (crm_str_eq((const char *)inputs->name, "inputs", TRUE)) {
139  xmlNode *trigger = NULL;
140 
141  for (trigger = __xml_first_child(inputs); trigger != NULL;
142  trigger = __xml_next(trigger)) {
143  xmlNode *input = NULL;
144 
145  for (input = __xml_first_child(trigger); input != NULL; input = __xml_next(input)) {
146  crm_action_t *new_input = unpack_action(new_synapse, input);
147 
148  if (new_input == NULL) {
149  continue;
150  }
151 
152  crm_trace("Adding input %d to synapse %d", new_input->id, new_synapse->id);
153 
154  new_synapse->inputs = g_list_append(new_synapse->inputs, new_input);
155  }
156  }
157  }
158  }
159 
160  return new_synapse;
161 }
162 
163 crm_graph_t *
164 unpack_graph(xmlNode * xml_graph, const char *reference)
165 {
166 /*
167  <transition_graph>
168  <synapse>
169  <action_set>
170  <rsc_op id="2"
171  ...
172  <inputs>
173  <rsc_op id="2"
174  ...
175 */
176  crm_graph_t *new_graph = NULL;
177  const char *t_id = NULL;
178  const char *time = NULL;
179  xmlNode *synapse = NULL;
180 
181  new_graph = calloc(1, sizeof(crm_graph_t));
182 
183  new_graph->id = -1;
184  new_graph->abort_priority = 0;
185  new_graph->network_delay = -1;
186  new_graph->transition_timeout = -1;
187  new_graph->stonith_timeout = -1;
188  new_graph->completion_action = tg_done;
189 
190  if (reference) {
191  new_graph->source = strdup(reference);
192  } else {
193  new_graph->source = strdup("unknown");
194  }
195 
196  if (xml_graph != NULL) {
197  t_id = crm_element_value(xml_graph, "transition_id");
198  CRM_CHECK(t_id != NULL, free(new_graph);
199  return NULL);
200  new_graph->id = crm_parse_int(t_id, "-1");
201 
202  time = crm_element_value(xml_graph, "cluster-delay");
203  CRM_CHECK(time != NULL, free(new_graph);
204  return NULL);
205  new_graph->network_delay = crm_get_msec(time);
206 
207  time = crm_element_value(xml_graph, "stonith-timeout");
208  if (time == NULL) {
209  new_graph->stonith_timeout = new_graph->network_delay;
210  } else {
211  new_graph->stonith_timeout = crm_get_msec(time);
212  }
213 
214  t_id = crm_element_value(xml_graph, "batch-limit");
215  new_graph->batch_limit = crm_parse_int(t_id, "0");
216 
217  t_id = crm_element_value(xml_graph, "migration-limit");
218  new_graph->migration_limit = crm_parse_int(t_id, "-1");
219  }
220 
221  for (synapse = __xml_first_child(xml_graph); synapse != NULL; synapse = __xml_next(synapse)) {
222  if (crm_str_eq((const char *)synapse->name, "synapse", TRUE)) {
223  synapse_t *new_synapse = unpack_synapse(new_graph, synapse);
224 
225  if (new_synapse != NULL) {
226  new_graph->synapses = g_list_append(new_graph->synapses, new_synapse);
227  }
228  }
229  }
230 
231  crm_debug("Unpacked transition %d: %d actions in %d synapses",
232  new_graph->id, new_graph->num_actions, new_graph->num_synapses);
233 
234  return new_graph;
235 }
236 
237 static void
238 destroy_action(crm_action_t * action)
239 {
240  if (action->timer && action->timer->source_id != 0) {
241  crm_warn("Cancelling timer for action %d (src=%d)", action->id, action->timer->source_id);
242  g_source_remove(action->timer->source_id);
243  }
244  if (action->params) {
245  g_hash_table_destroy(action->params);
246  }
247  free_xml(action->xml);
248  free(action->timer);
249  free(action);
250 }
251 
252 static void
253 destroy_synapse(synapse_t * synapse)
254 {
255  while (g_list_length(synapse->actions) > 0) {
256  crm_action_t *action = g_list_nth_data(synapse->actions, 0);
257 
258  synapse->actions = g_list_remove(synapse->actions, action);
259  destroy_action(action);
260  }
261 
262  while (g_list_length(synapse->inputs) > 0) {
263  crm_action_t *action = g_list_nth_data(synapse->inputs, 0);
264 
265  synapse->inputs = g_list_remove(synapse->inputs, action);
266  destroy_action(action);
267  }
268  free(synapse);
269 }
270 
271 void
273 {
274  if (graph == NULL) {
275  return;
276  }
277  while (g_list_length(graph->synapses) > 0) {
278  synapse_t *synapse = g_list_nth_data(graph->synapses, 0);
279 
280  graph->synapses = g_list_remove(graph->synapses, synapse);
281  destroy_synapse(synapse);
282  }
283 
284  free(graph->source);
285  free(graph);
286 }
287 
289 convert_graph_action(xmlNode * resource, crm_action_t * action, int status, int rc)
290 {
291  xmlNode *xop = NULL;
292  lrmd_event_data_t *op = NULL;
293  GHashTableIter iter;
294  const char *name = NULL;
295  const char *value = NULL;
296  xmlNode *action_resource = NULL;
297 
298  CRM_CHECK(action != NULL, return NULL);
299  CRM_CHECK(action->type == action_type_rsc, return NULL);
300 
301  action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
302  CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "Bad");
303  return NULL);
304 
305  op = calloc(1, sizeof(lrmd_event_data_t));
306 
307  op->rsc_id = strdup(ID(action_resource));
308  op->interval = action->interval;
309  op->op_type = strdup(crm_element_value(action->xml, XML_LRM_ATTR_TASK));
310 
311  op->rc = rc;
312  op->op_status = status;
313  op->t_run = time(NULL);
314  op->t_rcchange = op->t_run;
315 
316  op->params = g_hash_table_new_full(crm_str_hash, g_str_equal,
318 
319  g_hash_table_iter_init(&iter, action->params);
320  while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
321  g_hash_table_insert(op->params, strdup(name), strdup(value));
322  }
323 
324  for (xop = __xml_first_child(resource); xop != NULL; xop = __xml_next(xop)) {
325  int tmp = 0;
326 
328  crm_debug("Got call_id=%d for %s", tmp, ID(resource));
329  if (tmp > op->call_id) {
330  op->call_id = tmp;
331  }
332  }
333 
334  op->call_id++;
335  return op;
336 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
GListPtr actions
Definition: transition.h:40
A dumping ground.
GHashTable * xml2list(xmlNode *parent)
Definition: xml.c:5045
action_type_e type
Definition: transition.h:49
enum transition_action completion_action
Definition: transition.h:93
const char * rsc_id
Definition: lrmd.h:192
xmlNode * xml
Definition: transition.h:61
long long crm_get_msec(const char *input)
Definition: utils.c:776
gboolean can_fail
Definition: transition.h:59
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:292
int crm_parse_int(const char *text, const char *default_text)
Definition: utils.c:671
unsigned int t_rcchange
Definition: lrmd.h:218
void g_hash_destroy_str(gpointer data)
Definition: utils.c:615
#define XML_GRAPH_TAG_CRM_EVENT
Definition: msg_xml.h:294
int num_synapses
Definition: transition.h:96
enum ocf_exitcode rc
Definition: lrmd.h:210
GHashTable * params
Definition: transition.h:48
crm_action_timer_t * timer
Definition: transition.h:51
int transition_timeout
Definition: transition.h:101
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition: msg_xml.h:293
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:245
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2897
int priority
Definition: transition.h:33
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:263
void * params
Definition: lrmd.h:229
#define crm_warn(fmt, args...)
Definition: logging.h:249
#define crm_debug(fmt, args...)
Definition: logging.h:253
#define XML_ATTR_ID
Definition: msg_xml.h:100
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:184
#define crm_trace(fmt, args...)
Definition: logging.h:254
Wrappers for and extensions to libxml2.
#define crm_log_xml_warn(xml, text)
Definition: logging.h:258
int crm_element_value_int(xmlNode *data, const char *name, int *dest)
Definition: xml.c:4009
const char * crm_element_value(xmlNode *data, const char *name)
Definition: xml.c:5842
GListPtr synapses
Definition: transition.h:109
crm_graph_t * unpack_graph(xmlNode *xml_graph, const char *reference)
Definition: unpack.c:164
void free_xml(xmlNode *child)
Definition: xml.c:2851
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: utils.c:1441
int stonith_timeout
Definition: transition.h:100
const char * op_type
Definition: lrmd.h:194
int batch_limit
Definition: transition.h:98
unsigned int t_run
Definition: lrmd.h:216
GListPtr inputs
Definition: transition.h:41
char * source
Definition: transition.h:88
int network_delay
Definition: transition.h:99
int crm_str_to_boolean(const char *s, int *ret)
Definition: utils.c:722
int num_actions
Definition: transition.h:95
int migration_limit
Definition: transition.h:111
#define crm_err(fmt, args...)
Definition: logging.h:248
int abort_priority
Definition: transition.h:89
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:275
int source_id
Definition: transition.h:72
xmlNode * first_named_child(xmlNode *parent, const char *name)
Definition: xml.c:5210
#define crm_log_xml_trace(xml, text)
Definition: logging.h:262
CRM_TRACE_INIT_DATA(pe_status)
#define ID(x)
Definition: msg_xml.h:419
#define safe_str_eq(a, b)
Definition: util.h:74
#define crm_str_hash
Definition: crm.h:198
void destroy_graph(crm_graph_t *graph)
Definition: unpack.c:272
synapse_t * synapse
Definition: transition.h:52
lrmd_event_data_t * convert_graph_action(xmlNode *resource, crm_action_t *action, int status, int rc)
Definition: unpack.c:289