pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcmk_trans_unpack.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 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 #include <sys/stat.h>
14 
15 #include <crm/crm.h>
16 #include <crm/msg_xml.h>
17 #include <crm/common/xml.h>
18 #include <pacemaker-internal.h>
19 
20 static crm_action_t *
21 unpack_action(synapse_t * parent, xmlNode * xml_action)
22 {
23  crm_action_t *action = NULL;
24  const char *value = crm_element_value(xml_action, XML_ATTR_ID);
25 
26  if (value == NULL) {
27  crm_err("Actions must have an id!");
28  crm_log_xml_trace(xml_action, "Action with missing id");
29  return NULL;
30  }
31 
32  action = calloc(1, sizeof(crm_action_t));
33  if (action == NULL) {
34  crm_perror(LOG_CRIT, "Cannot unpack action");
35  crm_log_xml_trace(xml_action, "Lost action");
36  return NULL;
37  }
38 
39  action->id = crm_parse_int(value, NULL);
40  action->type = action_type_rsc;
41  action->xml = copy_xml(xml_action);
42  action->synapse = parent;
43 
44  if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_RSC_OP)) {
45  action->type = action_type_rsc;
46 
47  } else if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_PSEUDO_EVENT)) {
48  action->type = action_type_pseudo;
49 
50  } else if (safe_str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_CRM_EVENT)) {
51  action->type = action_type_crm;
52  }
53 
54  action->params = xml2list(action->xml);
55 
56  value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
57  if (value != NULL) {
58  action->timeout = crm_parse_int(value, NULL);
59  }
60 
61  /* Take start-delay into account for the timeout of the action timer */
62  value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
63  if (value != NULL) {
64  action->timeout += crm_parse_int(value, NULL);
65  }
66 
67  if (pcmk__guint_from_hash(action->params,
69  &(action->interval_ms)) != pcmk_rc_ok) {
70  action->interval_ms = 0;
71  }
72 
73  value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
74  if (value != NULL) {
75  crm_str_to_boolean(value, &(action->can_fail));
76  }
77 
78  crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
79 
80  return action;
81 }
82 
83 static synapse_t *
84 unpack_synapse(crm_graph_t * new_graph, xmlNode * xml_synapse)
85 {
86  const char *value = NULL;
87  xmlNode *inputs = NULL;
88  xmlNode *action_set = NULL;
89  synapse_t *new_synapse = NULL;
90 
91  CRM_CHECK(xml_synapse != NULL, return NULL);
92  crm_trace("looking in synapse %s", ID(xml_synapse));
93 
94  new_synapse = calloc(1, sizeof(synapse_t));
95  new_synapse->id = crm_parse_int(ID(xml_synapse), NULL);
96 
97  value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
98  if (value != NULL) {
99  new_synapse->priority = crm_parse_int(value, NULL);
100  }
101 
102  CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
103  return NULL);
104 
105  new_graph->num_synapses++;
106 
107  crm_trace("look for actions in synapse %s", crm_element_value(xml_synapse, XML_ATTR_ID));
108 
109  for (action_set = __xml_first_child(xml_synapse); action_set != NULL;
110  action_set = __xml_next(action_set)) {
111  if (crm_str_eq((const char *)action_set->name, "action_set", TRUE)) {
112  xmlNode *action = NULL;
113 
114  for (action = __xml_first_child(action_set); action != NULL;
115  action = __xml_next(action)) {
116  crm_action_t *new_action = unpack_action(new_synapse, action);
117 
118  if (new_action == NULL) {
119  continue;
120  }
121 
122  new_graph->num_actions++;
123 
124  crm_trace("Adding action %d to synapse %d", new_action->id, new_synapse->id);
125 
126  new_synapse->actions = g_list_append(new_synapse->actions, new_action);
127  }
128  }
129  }
130 
131  crm_trace("look for inputs in synapse %s", ID(xml_synapse));
132 
133  for (inputs = __xml_first_child(xml_synapse); inputs != NULL; inputs = __xml_next(inputs)) {
134  if (crm_str_eq((const char *)inputs->name, "inputs", TRUE)) {
135  xmlNode *trigger = NULL;
136 
137  for (trigger = __xml_first_child(inputs); trigger != NULL;
138  trigger = __xml_next(trigger)) {
139  xmlNode *input = NULL;
140 
141  for (input = __xml_first_child(trigger); input != NULL; input = __xml_next(input)) {
142  crm_action_t *new_input = unpack_action(new_synapse, input);
143 
144  if (new_input == NULL) {
145  continue;
146  }
147 
148  crm_trace("Adding input %d to synapse %d", new_input->id, new_synapse->id);
149 
150  new_synapse->inputs = g_list_append(new_synapse->inputs, new_input);
151  }
152  }
153  }
154  }
155 
156  return new_synapse;
157 }
158 
159 static void destroy_action(crm_action_t * action);
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 = 0;
184  new_graph->stonith_timeout = 0;
185  new_graph->completion_action = tg_done;
186 
187  if (reference) {
188  new_graph->source = strdup(reference);
189  } else {
190  new_graph->source = strdup("unknown");
191  }
192 
193  if (xml_graph != NULL) {
194  t_id = crm_element_value(xml_graph, "transition_id");
195  CRM_CHECK(t_id != NULL, free(new_graph);
196  return NULL);
197  new_graph->id = crm_parse_int(t_id, "-1");
198 
199  time = crm_element_value(xml_graph, "cluster-delay");
200  CRM_CHECK(time != NULL, free(new_graph);
201  return NULL);
202  new_graph->network_delay = crm_parse_interval_spec(time);
203 
204  time = crm_element_value(xml_graph, "stonith-timeout");
205  if (time == NULL) {
206  new_graph->stonith_timeout = new_graph->network_delay;
207  } else {
208  new_graph->stonith_timeout = crm_parse_interval_spec(time);
209  }
210 
211  t_id = crm_element_value(xml_graph, "batch-limit");
212  new_graph->batch_limit = crm_parse_int(t_id, "0");
213 
214  t_id = crm_element_value(xml_graph, "migration-limit");
215  new_graph->migration_limit = crm_parse_int(t_id, "-1");
216  }
217 
218  for (synapse = __xml_first_child(xml_graph); synapse != NULL; synapse = __xml_next(synapse)) {
219  if (crm_str_eq((const char *)synapse->name, "synapse", TRUE)) {
220  synapse_t *new_synapse = unpack_synapse(new_graph, synapse);
221 
222  if (new_synapse != NULL) {
223  new_graph->synapses = g_list_append(new_graph->synapses, new_synapse);
224  }
225  }
226  }
227 
228  crm_debug("Unpacked transition %d: %d actions in %d synapses",
229  new_graph->id, new_graph->num_actions, new_graph->num_synapses);
230 
231  return new_graph;
232 }
233 
234 static void
235 destroy_action(crm_action_t * action)
236 {
237  if (action->timer && action->timer->source_id != 0) {
238  crm_warn("Cancelling timer for action %d (src=%d)", action->id, action->timer->source_id);
239  g_source_remove(action->timer->source_id);
240  }
241  if (action->params) {
242  g_hash_table_destroy(action->params);
243  }
244  free_xml(action->xml);
245  free(action->timer);
246  free(action);
247 }
248 
249 static void
250 destroy_synapse(synapse_t * synapse)
251 {
252  while (synapse->actions != NULL) {
253  crm_action_t *action = g_list_nth_data(synapse->actions, 0);
254 
255  synapse->actions = g_list_remove(synapse->actions, action);
256  destroy_action(action);
257  }
258 
259  while (synapse->inputs != NULL) {
260  crm_action_t *action = g_list_nth_data(synapse->inputs, 0);
261 
262  synapse->inputs = g_list_remove(synapse->inputs, action);
263  destroy_action(action);
264  }
265  free(synapse);
266 }
267 
268 void
270 {
271  if (graph == NULL) {
272  return;
273  }
274  while (graph->synapses != NULL) {
275  synapse_t *synapse = g_list_nth_data(graph->synapses, 0);
276 
277  graph->synapses = g_list_remove(graph->synapses, synapse);
278  destroy_synapse(synapse);
279  }
280 
281  free(graph->source);
282  free(graph);
283 }
284 
286 convert_graph_action(xmlNode * resource, crm_action_t * action, int status, int rc)
287 {
288  xmlNode *xop = NULL;
289  lrmd_event_data_t *op = NULL;
290  GHashTableIter iter;
291  const char *name = NULL;
292  const char *value = NULL;
293  xmlNode *action_resource = NULL;
294 
295  CRM_CHECK(action != NULL, return NULL);
296  CRM_CHECK(action->type == action_type_rsc, return NULL);
297 
298  action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
299  CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "Bad");
300  return NULL);
301 
302  op = lrmd_new_event(ID(action_resource),
304  action->interval_ms);
305  op->rc = rc;
306  op->op_status = status;
307  op->t_run = time(NULL);
308  op->t_rcchange = op->t_run;
309 
310  op->params = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
311 
312  g_hash_table_iter_init(&iter, action->params);
313  while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
314  g_hash_table_insert(op->params, strdup(name), strdup(value));
315  }
316 
317  for (xop = __xml_first_child(resource); xop != NULL; xop = __xml_next(xop)) {
318  int tmp = 0;
319 
321  crm_debug("Got call_id=%d for %s", tmp, ID(resource));
322  if (tmp > op->call_id) {
323  op->call_id = tmp;
324  }
325  }
326 
327  op->call_id++;
328  return op;
329 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
GListPtr actions
A dumping ground.
action_type_e type
enum transition_action completion_action
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:4399
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition: strings.c:162
gboolean can_fail
crm_graph_t * unpack_graph(xmlNode *xml_graph, const char *reference)
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:254
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:289
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:126
unsigned int t_rcchange
Definition: lrmd.h:229
#define XML_GRAPH_TAG_CRM_EVENT
Definition: msg_xml.h:291
guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:309
enum ocf_exitcode rc
Definition: lrmd.h:221
GHashTable * params
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:558
crm_action_timer_t * timer
const char * action
Definition: pcmk_fence.c:29
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition: msg_xml.h:290
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:235
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2142
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:260
void * params
Definition: lrmd.h:240
#define crm_warn(fmt, args...)
Definition: logging.h:364
int rc
Definition: pcmk_fence.c:34
#define crm_debug(fmt, args...)
Definition: logging.h:368
#define XML_ATTR_ID
Definition: msg_xml.h:96
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:174
#define crm_trace(fmt, args...)
Definition: logging.h:369
Wrappers for and extensions to libxml2.
#define crm_log_xml_warn(xml, text)
Definition: logging.h:373
GListPtr synapses
void free_xml(xmlNode *child)
Definition: xml.c:2136
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:326
void destroy_graph(crm_graph_t *graph)
unsigned int t_run
Definition: lrmd.h:227
GListPtr inputs
guint stonith_timeout
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:289
lrmd_event_data_t * lrmd_new_event(const char *rsc_id, const char *task, guint interval_ms)
Definition: lrmd_client.c:193
lrmd_event_data_t * convert_graph_action(xmlNode *resource, crm_action_t *action, int status, int rc)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:314
#define CRM_META
Definition: crm.h:71
#define crm_err(fmt, args...)
Definition: logging.h:363
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:272
#define crm_str_hash
Definition: util.h:66
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:910
#define crm_log_xml_trace(xml, text)
Definition: logging.h:377
#define ID(x)
Definition: msg_xml.h:418
#define safe_str_eq(a, b)
Definition: util.h:65
char * name
Definition: pcmk_fence.c:30
synapse_t * synapse