This source file includes following definitions.
- free_graph_action
- free_graph_synapse
- pcmk__free_graph
- update_synapse_ready
- update_synapse_confirmed
- pcmk__update_graph
- pcmk__set_graph_functions
- should_fire_synapse
- initiate_action
- fire_synapse
- pseudo_action_dummy
- pcmk__execute_graph
- unpack_action
- unpack_synapse
- pcmk__unpack_graph
- pcmk__event_from_graph_action
1
2
3
4
5
6
7
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/common/xml.h>
17 #include <crm/common/xml_internal.h>
18 #include <crm/lrmd_internal.h>
19 #include <pacemaker-internal.h>
20
21
22
23
24
25
26
27
28
29
30
31
32 static void
33 free_graph_action(gpointer user_data)
34 {
35 pcmk__graph_action_t *action = user_data;
36
37 if (action->timer != 0) {
38 crm_warn("Cancelling timer for graph action %d", action->id);
39 g_source_remove(action->timer);
40 }
41 if (action->params != NULL) {
42 g_hash_table_destroy(action->params);
43 }
44 free_xml(action->xml);
45 free(action);
46 }
47
48
49
50
51
52
53
54 static void
55 free_graph_synapse(gpointer user_data)
56 {
57 pcmk__graph_synapse_t *synapse = user_data;
58
59 g_list_free_full(synapse->actions, free_graph_action);
60 g_list_free_full(synapse->inputs, free_graph_action);
61 free(synapse);
62 }
63
64
65
66
67
68
69
70 void
71 pcmk__free_graph(pcmk__graph_t *graph)
72 {
73 if (graph != NULL) {
74 g_list_free_full(graph->synapses, free_graph_synapse);
75 free(graph->source);
76 free(graph->failed_stop_offset);
77 free(graph->failed_start_offset);
78 free(graph);
79 }
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 static void
105 update_synapse_ready(pcmk__graph_synapse_t *synapse, int action_id)
106 {
107 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
108 return;
109 }
110
111
112 pcmk__set_synapse_flags(synapse, pcmk__synapse_ready);
113
114 for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
115 pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
116
117 if (prereq->id == action_id) {
118 crm_trace("Confirming input %d of synapse %d",
119 action_id, synapse->id);
120 pcmk__set_graph_action_flags(prereq, pcmk__graph_action_confirmed);
121
122 } else if (!pcmk_is_set(prereq->flags, pcmk__graph_action_confirmed)) {
123 pcmk__clear_synapse_flags(synapse, pcmk__synapse_ready);
124 crm_trace("Synapse %d still not ready after action %d",
125 synapse->id, action_id);
126 }
127 }
128 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
129 crm_trace("Synapse %d is now ready to execute", synapse->id);
130 }
131 }
132
133
134
135
136
137
138
139
140 static void
141 update_synapse_confirmed(pcmk__graph_synapse_t *synapse, int action_id)
142 {
143 bool all_confirmed = true;
144
145 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
146 pcmk__graph_action_t *action = (pcmk__graph_action_t *) lpc->data;
147
148 if (action->id == action_id) {
149 crm_trace("Confirmed action %d of synapse %d",
150 action_id, synapse->id);
151 pcmk__set_graph_action_flags(action, pcmk__graph_action_confirmed);
152
153 } else if (all_confirmed &&
154 !pcmk_is_set(action->flags, pcmk__graph_action_confirmed)) {
155 all_confirmed = false;
156 crm_trace("Synapse %d still not confirmed after action %d",
157 synapse->id, action_id);
158 }
159 }
160
161 if (all_confirmed
162 && !pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
163 crm_trace("Confirmed synapse %d", synapse->id);
164 pcmk__set_synapse_flags(synapse, pcmk__synapse_confirmed);
165 }
166 }
167
168
169
170
171
172
173
174
175 void
176 pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
177 {
178 for (GList *lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
179 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
180
181 if (pcmk_any_flags_set(synapse->flags,
182 pcmk__synapse_confirmed|pcmk__synapse_failed)) {
183 continue;
184
185 } else if (pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
186 update_synapse_confirmed(synapse, action->id);
187
188 } else if (!pcmk_is_set(action->flags, pcmk__graph_action_failed)
189 || (synapse->priority == PCMK_SCORE_INFINITY)) {
190 update_synapse_ready(synapse, action->id);
191 }
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 static pcmk__graph_functions_t *graph_fns = NULL;
205
206
207
208
209
210
211
212 void
213 pcmk__set_graph_functions(pcmk__graph_functions_t *fns)
214 {
215
216 pcmk__assert((fns != NULL) && (fns->rsc != NULL) && (fns->cluster != NULL)
217 && (fns->pseudo != NULL) && (fns->fence != NULL));
218 crm_debug("Setting custom functions for executing transition graphs");
219 graph_fns = fns;
220 }
221
222
223
224
225
226
227
228
229
230
231 static bool
232 should_fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
233 {
234 GList *lpc = NULL;
235
236 pcmk__set_synapse_flags(synapse, pcmk__synapse_ready);
237 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
238 pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
239
240 if (!(pcmk_is_set(prereq->flags, pcmk__graph_action_confirmed))) {
241 crm_trace("Input %d for synapse %d not yet confirmed",
242 prereq->id, synapse->id);
243 pcmk__clear_synapse_flags(synapse, pcmk__synapse_ready);
244 break;
245
246 } else if (pcmk_is_set(prereq->flags, pcmk__graph_action_failed)
247 && !pcmk_is_set(prereq->flags,
248 pcmk__graph_action_can_fail)) {
249 crm_trace("Input %d for synapse %d confirmed but failed",
250 prereq->id, synapse->id);
251 pcmk__clear_synapse_flags(synapse, pcmk__synapse_ready);
252 break;
253 }
254 }
255 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
256 crm_trace("Synapse %d is ready to execute", synapse->id);
257 } else {
258 return false;
259 }
260
261 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
262 pcmk__graph_action_t *a = (pcmk__graph_action_t *) lpc->data;
263
264 if (a->type == pcmk__pseudo_graph_action) {
265
266
267 } else if (synapse->priority < graph->abort_priority) {
268 crm_trace("Skipping synapse %d: priority %d is less than "
269 "abort priority %d",
270 synapse->id, synapse->priority, graph->abort_priority);
271 graph->skipped++;
272 return false;
273
274 } else if (graph_fns->allowed && !(graph_fns->allowed(graph, a))) {
275 crm_trace("Deferring synapse %d: not allowed", synapse->id);
276 return false;
277 }
278 }
279
280 return true;
281 }
282
283
284
285
286
287
288
289
290
291
292 static int
293 initiate_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
294 {
295 const char *id = pcmk__xe_id(action->xml);
296
297 CRM_CHECK(id != NULL, return EINVAL);
298 CRM_CHECK(!pcmk_is_set(action->flags, pcmk__graph_action_executed),
299 return pcmk_rc_already);
300
301 pcmk__set_graph_action_flags(action, pcmk__graph_action_executed);
302 switch (action->type) {
303 case pcmk__pseudo_graph_action:
304 crm_trace("Executing pseudo-action %d (%s)", action->id, id);
305 return graph_fns->pseudo(graph, action);
306
307 case pcmk__rsc_graph_action:
308 crm_trace("Executing resource action %d (%s)", action->id, id);
309 return graph_fns->rsc(graph, action);
310
311 case pcmk__cluster_graph_action:
312 if (pcmk__str_eq(crm_element_value(action->xml, PCMK_XA_OPERATION),
313 PCMK_ACTION_STONITH, pcmk__str_none)) {
314 crm_trace("Executing fencing action %d (%s)",
315 action->id, id);
316 return graph_fns->fence(graph, action);
317 }
318 crm_trace("Executing cluster action %d (%s)", action->id, id);
319 return graph_fns->cluster(graph, action);
320
321 default:
322 crm_err("Unsupported graph action type <%s " PCMK_XA_ID "='%s'> "
323 "(bug?)",
324 action->xml->name, id);
325 return EINVAL;
326 }
327 }
328
329
330
331
332
333
334
335
336
337
338 static int
339 fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
340 {
341 pcmk__set_synapse_flags(synapse, pcmk__synapse_executed);
342 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
343 pcmk__graph_action_t *action = (pcmk__graph_action_t *) lpc->data;
344 int rc = initiate_action(graph, action);
345
346 if (rc != pcmk_rc_ok) {
347 crm_err("Failed initiating <%s " PCMK_XA_ID "=%d> in synapse %d: "
348 "%s",
349 action->xml->name, action->id, synapse->id,
350 pcmk_rc_str(rc));
351 pcmk__set_synapse_flags(synapse, pcmk__synapse_confirmed);
352 pcmk__set_graph_action_flags(action,
353 pcmk__graph_action_confirmed
354 |pcmk__graph_action_failed);
355 return pcmk_rc_error;
356 }
357 }
358 return pcmk_rc_ok;
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372 static int
373 pseudo_action_dummy(pcmk__graph_t *graph, pcmk__graph_action_t *action)
374 {
375 static int fail = -1;
376
377 if (fail < 0) {
378 long long fail_ll;
379
380 if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
381 && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
382 fail = (int) fail_ll;
383 } else {
384 fail = 0;
385 }
386 }
387
388 if (action->id == fail) {
389 crm_err("Dummy event handler: pretending action %d failed", action->id);
390 pcmk__set_graph_action_flags(action, pcmk__graph_action_failed);
391 graph->abort_priority = PCMK_SCORE_INFINITY;
392 } else {
393 crm_trace("Dummy event handler: action %d initiated", action->id);
394 }
395 pcmk__set_graph_action_flags(action, pcmk__graph_action_confirmed);
396 pcmk__update_graph(graph, action);
397 return pcmk_rc_ok;
398 }
399
400 static pcmk__graph_functions_t default_fns = {
401 pseudo_action_dummy,
402 pseudo_action_dummy,
403 pseudo_action_dummy,
404 pseudo_action_dummy
405 };
406
407
408
409
410
411
412
413
414
415 enum pcmk__graph_status
416 pcmk__execute_graph(pcmk__graph_t *graph)
417 {
418 GList *lpc = NULL;
419 int log_level = LOG_DEBUG;
420 enum pcmk__graph_status pass_result = pcmk__graph_active;
421 const char *status = "In progress";
422
423 if (graph_fns == NULL) {
424 graph_fns = &default_fns;
425 }
426 if (graph == NULL) {
427 return pcmk__graph_complete;
428 }
429
430 graph->fired = 0;
431 graph->pending = 0;
432 graph->skipped = 0;
433 graph->completed = 0;
434 graph->incomplete = 0;
435
436
437 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
438 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
439
440 if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
441 graph->completed++;
442
443 } else if (!pcmk_is_set(synapse->flags, pcmk__synapse_failed)
444 && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
445 graph->pending++;
446 }
447 }
448 crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
449 graph->id, graph->completed, graph->pending);
450
451
452 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
453 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
454
455 if ((graph->batch_limit > 0)
456 && (graph->pending >= graph->batch_limit)) {
457
458 crm_debug("Throttling graph execution: batch limit (%d) reached",
459 graph->batch_limit);
460 break;
461
462 } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
463 graph->skipped++;
464 continue;
465
466 } else if (pcmk_any_flags_set(synapse->flags,
467 pcmk__synapse_confirmed
468 |pcmk__synapse_executed)) {
469 continue;
470
471 } else if (should_fire_synapse(graph, synapse)) {
472 graph->fired++;
473 if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
474 crm_err("Synapse %d failed to fire", synapse->id);
475 log_level = LOG_ERR;
476 graph->abort_priority = PCMK_SCORE_INFINITY;
477 graph->incomplete++;
478 graph->fired--;
479 }
480
481 if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
482 graph->pending++;
483 }
484
485 } else {
486 crm_trace("Synapse %d cannot fire", synapse->id);
487 graph->incomplete++;
488 }
489 }
490
491 if ((graph->pending == 0) && (graph->fired == 0)) {
492 graph->complete = true;
493
494 if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
495 log_level = LOG_WARNING;
496 pass_result = pcmk__graph_terminated;
497 status = "Terminated";
498
499 } else if (graph->skipped != 0) {
500 log_level = LOG_NOTICE;
501 pass_result = pcmk__graph_complete;
502 status = "Stopped";
503
504 } else {
505 log_level = LOG_NOTICE;
506 pass_result = pcmk__graph_complete;
507 status = "Complete";
508 }
509
510 } else if (graph->fired == 0) {
511 pass_result = pcmk__graph_pending;
512 }
513
514 do_crm_log(log_level,
515 "Transition %d (Complete=%d, Pending=%d,"
516 " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
517 graph->id, graph->completed, graph->pending, graph->fired,
518 graph->skipped, graph->incomplete, graph->source, status);
519
520 return pass_result;
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537 static pcmk__graph_action_t *
538 unpack_action(pcmk__graph_synapse_t *parent, xmlNode *xml_action)
539 {
540 enum pcmk__graph_action_type action_type;
541 pcmk__graph_action_t *action = NULL;
542 const char *value = pcmk__xe_id(xml_action);
543
544 if (value == NULL) {
545 crm_err("Ignoring transition graph action without " PCMK_XA_ID
546 " (bug?)");
547 crm_log_xml_trace(xml_action, "invalid");
548 return NULL;
549 }
550
551 if (pcmk__xe_is(xml_action, PCMK__XE_RSC_OP)) {
552 action_type = pcmk__rsc_graph_action;
553
554 } else if (pcmk__xe_is(xml_action, PCMK__XE_PSEUDO_EVENT)) {
555 action_type = pcmk__pseudo_graph_action;
556
557 } else if (pcmk__xe_is(xml_action, PCMK__XE_CRM_EVENT)) {
558 action_type = pcmk__cluster_graph_action;
559
560 } else {
561 crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
562 xml_action->name);
563 crm_log_xml_trace(xml_action, "invalid");
564 return NULL;
565 }
566
567 action = calloc(1, sizeof(pcmk__graph_action_t));
568 if (action == NULL) {
569 crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
570 crm_log_xml_trace(xml_action, "lost");
571 return NULL;
572 }
573
574 pcmk__scan_min_int(value, &(action->id), -1);
575 action->type = pcmk__rsc_graph_action;
576 action->xml = pcmk__xml_copy(NULL, xml_action);
577 action->synapse = parent;
578 action->type = action_type;
579 action->params = xml2list(action->xml);
580
581 value = crm_meta_value(action->params, PCMK_META_TIMEOUT);
582 pcmk__scan_min_int(value, &(action->timeout), 0);
583
584
585
586
587 value = crm_meta_value(action->params, PCMK_META_START_DELAY);
588 {
589 int start_delay;
590
591 pcmk__scan_min_int(value, &start_delay, 0);
592 action->timeout += start_delay;
593 }
594
595 if (pcmk__guint_from_hash(action->params, CRM_META "_" PCMK_META_INTERVAL,
596 0, &(action->interval_ms)) != pcmk_rc_ok) {
597 action->interval_ms = 0;
598 }
599
600 value = crm_meta_value(action->params, PCMK__META_CAN_FAIL);
601 if (value != NULL) {
602 int can_fail = 0;
603
604 if ((crm_str_to_boolean(value, &can_fail) > 0) && (can_fail > 0)) {
605 pcmk__set_graph_action_flags(action, pcmk__graph_action_can_fail);
606 } else {
607 pcmk__clear_graph_action_flags(action, pcmk__graph_action_can_fail);
608 }
609
610 if (pcmk_is_set(action->flags, pcmk__graph_action_can_fail)) {
611 crm_warn("Support for the " PCMK__META_CAN_FAIL " meta-attribute "
612 "is deprecated and will be removed in a future release");
613 }
614 }
615
616 crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
617
618 return action;
619 }
620
621
622
623
624
625
626
627
628
629
630 static pcmk__graph_synapse_t *
631 unpack_synapse(pcmk__graph_t *new_graph, const xmlNode *xml_synapse)
632 {
633 const char *value = NULL;
634 xmlNode *action_set = NULL;
635 pcmk__graph_synapse_t *new_synapse = NULL;
636
637 crm_trace("Unpacking synapse %s", pcmk__xe_id(xml_synapse));
638
639 new_synapse = calloc(1, sizeof(pcmk__graph_synapse_t));
640 if (new_synapse == NULL) {
641 return NULL;
642 }
643
644 pcmk__scan_min_int(pcmk__xe_id(xml_synapse), &(new_synapse->id), 0);
645
646 value = crm_element_value(xml_synapse, PCMK__XA_PRIORITY);
647 pcmk__scan_min_int(value, &(new_synapse->priority), 0);
648
649 CRM_CHECK(new_synapse->id >= 0,
650 free_graph_synapse((gpointer) new_synapse); return NULL);
651
652 new_graph->num_synapses++;
653
654 crm_trace("Unpacking synapse %s action sets",
655 crm_element_value(xml_synapse, PCMK_XA_ID));
656
657 for (action_set = pcmk__xe_first_child(xml_synapse, "action_set", NULL,
658 NULL);
659 action_set != NULL; action_set = pcmk__xe_next_same(action_set)) {
660
661 for (xmlNode *action = pcmk__xe_first_child(action_set, NULL, NULL,
662 NULL);
663 action != NULL; action = pcmk__xe_next(action)) {
664
665 pcmk__graph_action_t *new_action = unpack_action(new_synapse,
666 action);
667
668 if (new_action == NULL) {
669 continue;
670 }
671
672 crm_trace("Adding action %d to synapse %d",
673 new_action->id, new_synapse->id);
674 new_graph->num_actions++;
675 new_synapse->actions = g_list_append(new_synapse->actions,
676 new_action);
677 }
678 }
679
680 crm_trace("Unpacking synapse %s inputs", pcmk__xe_id(xml_synapse));
681
682 for (xmlNode *inputs = pcmk__xe_first_child(xml_synapse, "inputs", NULL,
683 NULL);
684 inputs != NULL; inputs = pcmk__xe_next_same(inputs)) {
685
686 for (xmlNode *trigger = pcmk__xe_first_child(inputs, "trigger", NULL,
687 NULL);
688 trigger != NULL; trigger = pcmk__xe_next_same(trigger)) {
689
690 for (xmlNode *input = pcmk__xe_first_child(trigger, NULL, NULL,
691 NULL);
692 input != NULL; input = pcmk__xe_next(input)) {
693
694 pcmk__graph_action_t *new_input = unpack_action(new_synapse,
695 input);
696
697 if (new_input == NULL) {
698 continue;
699 }
700
701 crm_trace("Adding input %d to synapse %d",
702 new_input->id, new_synapse->id);
703
704 new_synapse->inputs = g_list_append(new_synapse->inputs,
705 new_input);
706 }
707 }
708 }
709
710 return new_synapse;
711 }
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738 pcmk__graph_t *
739 pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
740 {
741 pcmk__graph_t *new_graph = NULL;
742
743 new_graph = calloc(1, sizeof(pcmk__graph_t));
744 if (new_graph == NULL) {
745 return NULL;
746 }
747
748 new_graph->source = strdup(pcmk__s(reference, "unknown"));
749 if (new_graph->source == NULL) {
750 pcmk__free_graph(new_graph);
751 return NULL;
752 }
753
754 new_graph->completion_action = pcmk__graph_done;
755
756
757 if (xml_graph != NULL) {
758 const char *buf = crm_element_value(xml_graph, "transition_id");
759
760 CRM_CHECK(buf != NULL,
761 pcmk__free_graph(new_graph); return NULL);
762 pcmk__scan_min_int(buf, &(new_graph->id), 1);
763
764 buf = crm_element_value(xml_graph, PCMK_OPT_CLUSTER_DELAY);
765 CRM_CHECK(buf != NULL,
766 pcmk__free_graph(new_graph); return NULL);
767 pcmk_parse_interval_spec(buf, &(new_graph->network_delay));
768
769 buf = crm_element_value(xml_graph, PCMK_OPT_STONITH_TIMEOUT);
770 if (buf == NULL) {
771 new_graph->stonith_timeout = new_graph->network_delay;
772 } else {
773 pcmk_parse_interval_spec(buf, &(new_graph->stonith_timeout));
774 }
775
776
777 buf = crm_element_value(xml_graph, PCMK_OPT_BATCH_LIMIT);
778 if ((buf == NULL)
779 || (pcmk__scan_min_int(buf, &(new_graph->batch_limit),
780 -1) != pcmk_rc_ok)) {
781 new_graph->batch_limit = 0;
782 }
783
784 buf = crm_element_value(xml_graph, PCMK_OPT_MIGRATION_LIMIT);
785 pcmk__scan_min_int(buf, &(new_graph->migration_limit), -1);
786
787 new_graph->failed_stop_offset =
788 crm_element_value_copy(xml_graph, "failed-stop-offset");
789 new_graph->failed_start_offset =
790 crm_element_value_copy(xml_graph, "failed-start-offset");
791
792 if (crm_element_value_epoch(xml_graph, "recheck-by",
793 &(new_graph->recheck_by)) != pcmk_ok) {
794 new_graph->recheck_by = 0;
795 }
796 }
797
798
799 for (const xmlNode *synapse_xml = pcmk__xe_first_child(xml_graph,
800 "synapse", NULL,
801 NULL);
802 synapse_xml != NULL; synapse_xml = pcmk__xe_next_same(synapse_xml)) {
803
804 pcmk__graph_synapse_t *new_synapse = unpack_synapse(new_graph,
805 synapse_xml);
806
807 if (new_synapse != NULL) {
808 new_graph->synapses = g_list_append(new_graph->synapses,
809 new_synapse);
810 }
811 }
812
813 crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
814 new_graph->id, new_graph->source, new_graph->num_actions,
815 new_graph->num_synapses);
816
817 return new_graph;
818 }
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837 lrmd_event_data_t *
838 pcmk__event_from_graph_action(const xmlNode *resource,
839 const pcmk__graph_action_t *action,
840 int status, int rc, const char *exit_reason)
841 {
842 lrmd_event_data_t *op = NULL;
843 GHashTableIter iter;
844 const char *name = NULL;
845 const char *value = NULL;
846 xmlNode *action_resource = NULL;
847
848 CRM_CHECK(action != NULL, return NULL);
849 CRM_CHECK(action->type == pcmk__rsc_graph_action, return NULL);
850
851 action_resource = pcmk__xe_first_child(action->xml, PCMK_XE_PRIMITIVE, NULL,
852 NULL);
853 CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
854 return NULL);
855
856 op = lrmd_new_event(pcmk__xe_id(action_resource),
857 crm_element_value(action->xml, PCMK_XA_OPERATION),
858 action->interval_ms);
859 lrmd__set_result(op, rc, status, exit_reason);
860
861 op->t_run = time(NULL);
862 op->t_rcchange = op->t_run;
863 op->params = pcmk__strkey_table(free, free);
864
865 g_hash_table_iter_init(&iter, action->params);
866 while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
867 pcmk__insert_dup(op->params, name, value);
868 }
869
870 for (xmlNode *xop = pcmk__xe_first_child(resource, NULL, NULL, NULL);
871 xop != NULL; xop = pcmk__xe_next(xop)) {
872
873 int tmp = 0;
874
875 crm_element_value_int(xop, PCMK__XA_CALL_ID, &tmp);
876 crm_debug("Got call_id=%d for %s", tmp, pcmk__xe_id(resource));
877 if (tmp > op->call_id) {
878 op->call_id = tmp;
879 }
880 }
881
882 op->call_id++;
883 return op;
884 }