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