pacemaker 2.1.6-6fdc9deea29
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_sched_recurring.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2023 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 General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdbool.h>
13
14#include <crm/msg_xml.h>
15#include <pacemaker-internal.h>
16
18
19// Information parsed from an operation history entry in the CIB
20struct op_history {
21 // XML attributes
22 const char *id; // ID of history entry
23 const char *name; // Action name
24
25 // Parsed information
26 char *key; // Operation key for action
27 enum rsc_role_e role; // Action role (or RSC_ROLE_UNKNOWN for default)
28 guint interval_ms; // Action interval
29};
30
39static guint
40xe_interval(const xmlNode *xml)
41{
44}
45
57static bool
58is_op_dup(const pe_resource_t *rsc, const char *name, guint interval_ms)
59{
60 const char *id = NULL;
61
62 for (xmlNode *op = first_named_child(rsc->ops_xml, "op");
63 op != NULL; op = crm_next_same_xml(op)) {
64
65 // Check whether action name and interval match
66 if (!pcmk__str_eq(crm_element_value(op, "name"),
68 || (xe_interval(op) != interval_ms)) {
69 continue;
70 }
71
72 if (ID(op) == NULL) {
73 continue; // Shouldn't be possible
74 }
75
76 if (id == NULL) {
77 id = ID(op); // First matching op
78 } else {
79 pcmk__config_err("Operation %s is duplicate of %s (do not use "
80 "same name and interval combination more "
81 "than once per resource)", ID(op), id);
82 return true;
83 }
84 }
85 return false;
86}
87
104static bool
105op_cannot_recur(const char *name)
106{
110}
111
122static bool
123is_recurring_history(const pe_resource_t *rsc, const xmlNode *xml,
124 struct op_history *op)
125{
126 const char *role = NULL;
127
128 op->interval_ms = xe_interval(xml);
129 if (op->interval_ms == 0) {
130 return false; // Not recurring
131 }
132
133 op->id = ID(xml);
134 if (pcmk__str_empty(op->id)) {
135 pcmk__config_err("Ignoring resource history entry without ID");
136 return false; // Shouldn't be possible (unless CIB was manually edited)
137 }
138
139 op->name = crm_element_value(xml, "name");
140 if (op_cannot_recur(op->name)) {
141 pcmk__config_err("Ignoring %s because %s action cannot be recurring",
142 op->id, pcmk__s(op->name, "unnamed"));
143 return false;
144 }
145
146 // There should only be one recurring operation per action/interval
147 if (is_op_dup(rsc, op->name, op->interval_ms)) {
148 return false;
149 }
150
151 // Ensure role is valid if specified
152 role = crm_element_value(xml, "role");
153 if (role == NULL) {
154 op->role = RSC_ROLE_UNKNOWN;
155 } else {
156 op->role = text2role(role);
157 if (op->role == RSC_ROLE_UNKNOWN) {
158 pcmk__config_err("Ignoring %s because %s is not a valid role",
159 op->id, role);
160 }
161 }
162
163 // Disabled resources don't get monitored
164 op->key = pcmk__op_key(rsc->id, op->name, op->interval_ms);
165 if (find_rsc_op_entry(rsc, op->key) == NULL) {
166 crm_trace("Not creating recurring action %s for disabled resource %s",
167 op->id, rsc->id);
168 free(op->key);
169 return false;
170 }
171
172 return true;
173}
174
186static bool
187active_recurring_should_be_optional(const pe_resource_t *rsc,
188 const pe_node_t *node, const char *key,
189 pe_action_t *start)
190{
191 GList *possible_matches = NULL;
192
193 if (node == NULL) { // Should only be possible if unmanaged and stopped
194 pe_rsc_trace(rsc, "%s will be mandatory because resource is unmanaged",
195 key);
196 return false;
197 }
198
199 if (!pcmk_is_set(rsc->cmds->action_flags(start, NULL),
201 pe_rsc_trace(rsc, "%s will be mandatory because %s is",
202 key, start->uuid);
203 return false;
204 }
205
206 possible_matches = find_actions_exact(rsc->actions, key, node);
207 if (possible_matches == NULL) {
208 pe_rsc_trace(rsc, "%s will be mandatory because it is not active on %s",
209 key, pe__node_name(node));
210 return false;
211 }
212
213 for (const GList *iter = possible_matches;
214 iter != NULL; iter = iter->next) {
215
216 const pe_action_t *op = (const pe_action_t *) iter->data;
217
218 if (pcmk_is_set(op->flags, pe_action_reschedule)) {
219 pe_rsc_trace(rsc,
220 "%s will be mandatory because "
221 "it needs to be rescheduled", key);
222 g_list_free(possible_matches);
223 return false;
224 }
225 }
226
227 g_list_free(possible_matches);
228 return true;
229}
230
240static void
241recurring_op_for_active(pe_resource_t *rsc, pe_action_t *start,
242 const pe_node_t *node, const struct op_history *op)
243{
244 pe_action_t *mon = NULL;
245 bool is_optional = true;
246
247 // We're only interested in recurring actions for active roles
248 if (op->role == RSC_ROLE_STOPPED) {
249 return;
250 }
251
252 is_optional = active_recurring_should_be_optional(rsc, node, op->key,
253 start);
254
255 if (((op->role != RSC_ROLE_UNKNOWN) && (rsc->next_role != op->role))
256 || ((op->role == RSC_ROLE_UNKNOWN)
257 && (rsc->next_role == RSC_ROLE_PROMOTED))) {
258 // Configured monitor role doesn't match role resource will have
259
260 if (is_optional) { // It's running, so cancel it
261 char *after_key = NULL;
262 pe_action_t *cancel_op = pcmk__new_cancel_action(rsc, op->name,
263 op->interval_ms,
264 node);
265
266 switch (rsc->role) {
268 case RSC_ROLE_STARTED:
269 if (rsc->next_role == RSC_ROLE_PROMOTED) {
270 after_key = promote_key(rsc);
271
272 } else if (rsc->next_role == RSC_ROLE_STOPPED) {
273 after_key = stop_key(rsc);
274 }
275
276 break;
278 after_key = demote_key(rsc);
279 break;
280 default:
281 break;
282 }
283
284 if (after_key) {
285 pcmk__new_ordering(rsc, NULL, cancel_op, rsc, after_key, NULL,
287 }
288 }
289
290 do_crm_log((is_optional? LOG_INFO : LOG_TRACE),
291 "%s recurring action %s because %s configured for %s role "
292 "(not %s)",
293 (is_optional? "Cancelling" : "Ignoring"), op->key, op->id,
294 role2text((op->role == RSC_ROLE_UNKNOWN)? RSC_ROLE_UNPROMOTED : op->role),
295 role2text(rsc->next_role));
296 return;
297 }
298
299 pe_rsc_trace(rsc,
300 "Creating %s recurring action %s for %s (%s %s on %s)",
301 (is_optional? "optional" : "mandatory"), op->key,
302 op->id, rsc->id, role2text(rsc->next_role),
303 pe__node_name(node));
304
305 mon = custom_action(rsc, strdup(op->key), op->name, node, is_optional, TRUE,
306 rsc->cluster);
307
308 if (!pcmk_is_set(start->flags, pe_action_runnable)) {
309 pe_rsc_trace(rsc, "%s is unrunnable because start is", mon->uuid);
311
312 } else if ((node == NULL) || !node->details->online
313 || node->details->unclean) {
314 pe_rsc_trace(rsc, "%s is unrunnable because no node is available",
315 mon->uuid);
317
318 } else if (!pcmk_is_set(mon->flags, pe_action_optional)) {
319 pe_rsc_info(rsc, "Start %s-interval %s for %s on %s",
320 pcmk__readable_interval(op->interval_ms), mon->task,
321 rsc->id, pe__node_name(node));
322 }
323
324 if (rsc->next_role == RSC_ROLE_PROMOTED) {
326 }
327
328 // Order monitor relative to other actions
329 if ((node == NULL) || pcmk_is_set(rsc->flags, pe_rsc_managed)) {
330 pcmk__new_ordering(rsc, start_key(rsc), NULL,
331 NULL, strdup(mon->uuid), mon,
333 rsc->cluster);
334
335 pcmk__new_ordering(rsc, reload_key(rsc), NULL,
336 NULL, strdup(mon->uuid), mon,
338 rsc->cluster);
339
340 if (rsc->next_role == RSC_ROLE_PROMOTED) {
341 pcmk__new_ordering(rsc, promote_key(rsc), NULL,
342 rsc, NULL, mon,
344 rsc->cluster);
345
346 } else if (rsc->role == RSC_ROLE_PROMOTED) {
347 pcmk__new_ordering(rsc, demote_key(rsc), NULL,
348 rsc, NULL, mon,
350 rsc->cluster);
351 }
352 }
353}
354
365static void
366cancel_if_running(pe_resource_t *rsc, const pe_node_t *node, const char *key,
367 const char *name, guint interval_ms)
368{
369 GList *possible_matches = find_actions_exact(rsc->actions, key, node);
370 pe_action_t *cancel_op = NULL;
371
372 if (possible_matches == NULL) {
373 return; // Recurring action isn't running on this node
374 }
375 g_list_free(possible_matches);
376
377 cancel_op = pcmk__new_cancel_action(rsc, name, interval_ms, node);
378
379 switch (rsc->next_role) {
380 case RSC_ROLE_STARTED:
382 /* Order starts after cancel. If the current role is
383 * stopped, this cancels the monitor before the resource
384 * starts; if the current role is started, then this cancels
385 * the monitor on a migration target before starting there.
386 */
387 pcmk__new_ordering(rsc, NULL, cancel_op,
388 rsc, start_key(rsc), NULL,
390 break;
391 default:
392 break;
393 }
394 pe_rsc_info(rsc,
395 "Cancelling %s-interval %s action for %s on %s because "
396 "configured for " RSC_ROLE_STOPPED_S " role (not %s)",
397 pcmk__readable_interval(interval_ms), name, rsc->id,
398 pe__node_name(node), role2text(rsc->next_role));
399}
400
409static void
410order_after_probes(pe_resource_t *rsc, const pe_node_t *node,
412{
413 GList *probes = pe__resource_actions(rsc, node, RSC_STATUS, FALSE);
414
415 for (GList *iter = probes; iter != NULL; iter = iter->next) {
416 order_actions((pe_action_t *) iter->data, action,
418 }
419 g_list_free(probes);
420}
421
430static void
431order_after_stops(pe_resource_t *rsc, const pe_node_t *node,
433{
434 GList *stop_ops = pe__resource_actions(rsc, node, RSC_STOP, TRUE);
435
436 for (GList *iter = stop_ops; iter != NULL; iter = iter->next) {
437 pe_action_t *stop = (pe_action_t *) iter->data;
438
439 if (!pcmk_is_set(stop->flags, pe_action_optional)
441 && !pcmk_is_set(rsc->flags, pe_rsc_managed)) {
442 pe_rsc_trace(rsc, "%s optional on %s: unmanaged",
443 action->uuid, pe__node_name(node));
445 }
446
447 if (!pcmk_is_set(stop->flags, pe_action_runnable)) {
448 crm_debug("%s unrunnable on %s: stop is unrunnable",
449 action->uuid, pe__node_name(node));
451 }
452
453 if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
454 pcmk__new_ordering(rsc, stop_key(rsc), stop,
455 NULL, NULL, action,
457 rsc->cluster);
458 }
459 }
460 g_list_free(stop_ops);
461}
462
471static void
472recurring_op_for_inactive(pe_resource_t *rsc, const pe_node_t *node,
473 const struct op_history *op)
474{
475 GList *possible_matches = NULL;
476
477 // We're only interested in recurring actions for the inactive role
478 if (op->role != RSC_ROLE_STOPPED) {
479 return;
480 }
481
482 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
483 crm_notice("Ignoring %s (recurring monitors for " RSC_ROLE_STOPPED_S
484 " role are not supported for anonymous clones)", op->id);
485 return; // @TODO add support
486 }
487
488 pe_rsc_trace(rsc, "Creating recurring action %s for %s on nodes "
489 "where it should not be running", op->id, rsc->id);
490
491 for (GList *iter = rsc->cluster->nodes; iter != NULL; iter = iter->next) {
492 pe_node_t *stop_node = (pe_node_t *) iter->data;
493
494 bool is_optional = true;
495 pe_action_t *stopped_mon = NULL;
496
497 // Cancel action on node where resource will be active
498 if ((node != NULL)
499 && pcmk__str_eq(stop_node->details->uname, node->details->uname,
501 cancel_if_running(rsc, node, op->key, op->name, op->interval_ms);
502 continue;
503 }
504
505 // Recurring action on this node is optional if it's already active here
506 possible_matches = find_actions_exact(rsc->actions, op->key, stop_node);
507 is_optional = (possible_matches != NULL);
508 g_list_free(possible_matches);
509
510 pe_rsc_trace(rsc,
511 "Creating %s recurring action %s for %s (%s "
512 RSC_ROLE_STOPPED_S " on %s)",
513 (is_optional? "optional" : "mandatory"),
514 op->key, op->id, rsc->id, pe__node_name(stop_node));
515
516 stopped_mon = custom_action(rsc, strdup(op->key), op->name, stop_node,
517 is_optional, TRUE, rsc->cluster);
518
520
521 if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
522 order_after_probes(rsc, stop_node, stopped_mon);
523 }
524
525 /* The recurring action is for the inactive role, so it shouldn't be
526 * performed until the resource is inactive.
527 */
528 order_after_stops(rsc, stop_node, stopped_mon);
529
530 if (!stop_node->details->online || stop_node->details->unclean) {
531 pe_rsc_debug(rsc, "%s unrunnable on %s: node unavailable)",
532 stopped_mon->uuid, pe__node_name(stop_node));
534 }
535
536 if (pcmk_is_set(stopped_mon->flags, pe_action_runnable)
537 && !pcmk_is_set(stopped_mon->flags, pe_action_optional)) {
538 crm_notice("Start recurring %s-interval %s for "
539 RSC_ROLE_STOPPED_S " %s on %s",
540 pcmk__readable_interval(op->interval_ms),
541 stopped_mon->task, rsc->id, pe__node_name(stop_node));
542 }
543 }
544}
545
552void
554{
555 pe_action_t *start = NULL;
556
557 if (pcmk_is_set(rsc->flags, pe_rsc_block)) {
558 pe_rsc_trace(rsc, "Skipping recurring actions for blocked resource %s",
559 rsc->id);
560 return;
561 }
562
564 pe_rsc_trace(rsc, "Skipping recurring actions for %s "
565 "in maintenance mode", rsc->id);
566 return;
567 }
568
569 if (rsc->allocated_to == NULL) {
570 // Recurring actions for active roles not needed
571
572 } else if (rsc->allocated_to->details->maintenance) {
573 pe_rsc_trace(rsc,
574 "Skipping recurring actions for %s on %s "
575 "in maintenance mode",
576 rsc->id, pe__node_name(rsc->allocated_to));
577
578 } else if ((rsc->next_role != RSC_ROLE_STOPPED)
579 || !pcmk_is_set(rsc->flags, pe_rsc_managed)) {
580 // Recurring actions for active roles needed
581 start = start_action(rsc, rsc->allocated_to, TRUE);
582 }
583
584 pe_rsc_trace(rsc, "Creating any recurring actions needed for %s", rsc->id);
585
586 for (xmlNode *op = first_named_child(rsc->ops_xml, "op");
587 op != NULL; op = crm_next_same_xml(op)) {
588
589 struct op_history op_history = { NULL, };
590
591 if (!is_recurring_history(rsc, op, &op_history)) {
592 continue;
593 }
594
595 if (start != NULL) {
596 recurring_op_for_active(rsc, start, rsc->allocated_to, &op_history);
597 }
598 recurring_op_for_inactive(rsc, rsc->allocated_to, &op_history);
599
600 free(op_history.key);
601 }
602}
603
616pcmk__new_cancel_action(pe_resource_t *rsc, const char *task, guint interval_ms,
617 const pe_node_t *node)
618{
619 pe_action_t *cancel_op = NULL;
620 char *key = NULL;
621 char *interval_ms_s = NULL;
622
623 CRM_ASSERT((rsc != NULL) && (task != NULL) && (node != NULL));
624
625 // @TODO dangerous if possible to schedule another action with this key
626 key = pcmk__op_key(rsc->id, task, interval_ms);
627
628 cancel_op = custom_action(rsc, key, RSC_CANCEL, node, FALSE, TRUE,
629 rsc->cluster);
630
631 pcmk__str_update(&cancel_op->task, RSC_CANCEL);
632 pcmk__str_update(&cancel_op->cancel_task, task);
633
634 interval_ms_s = crm_strdup_printf("%u", interval_ms);
635 add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, task);
636 add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL_MS, interval_ms_s);
637 free(interval_ms_s);
638
639 return cancel_op;
640}
641
653void
654pcmk__schedule_cancel(pe_resource_t *rsc, const char *call_id, const char *task,
655 guint interval_ms, const pe_node_t *node,
656 const char *reason)
657{
658 pe_action_t *cancel = NULL;
659
660 CRM_CHECK((rsc != NULL) && (task != NULL)
661 && (node != NULL) && (reason != NULL),
662 return);
663
664 crm_info("Recurring %s-interval %s for %s will be stopped on %s: %s",
665 pcmk__readable_interval(interval_ms), task, rsc->id,
666 pe__node_name(node), reason);
667 cancel = pcmk__new_cancel_action(rsc, task, interval_ms, node);
668 add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
669
670 // Cancellations happen after stops
671 pcmk__new_ordering(rsc, stop_key(rsc), NULL, rsc, NULL, cancel,
673}
674
684void
686 guint interval_ms, pe_node_t *node)
687{
688 pe_action_t *op = NULL;
689
690 trigger_unfencing(rsc, node, "Device parameters changed (reschedule)",
691 NULL, rsc->cluster);
692 op = custom_action(rsc, pcmk__op_key(rsc->id, task, interval_ms),
693 task, node, TRUE, TRUE, rsc->cluster);
695}
696
705bool
707{
708 guint interval_ms = 0;
709
712 &interval_ms) != pcmk_rc_ok) {
713 return false;
714 }
715 return (interval_ms > 0);
716}
const char * name
Definition cib.c:24
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition operations.c:42
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition utils.c:271
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:121
#define RSC_ROLE_STOPPED_S
Definition common.h:111
const char * role2text(enum rsc_role_e role)
Definition common.c:450
rsc_role_e
Possible roles that a resource can be in.
Definition common.h:92
@ RSC_ROLE_STARTED
Definition common.h:95
@ RSC_ROLE_STOPPED
Definition common.h:94
@ RSC_ROLE_PROMOTED
Definition common.h:97
@ RSC_ROLE_UNKNOWN
Definition common.h:93
@ RSC_ROLE_UNPROMOTED
Definition common.h:96
enum rsc_role_e text2role(const char *role)
Definition common.c:479
uint32_t id
Definition cpg.c:0
#define RSC_PROMOTE
Definition crm.h:205
#define RSC_DEMOTE
Definition crm.h:207
#define CRMD_ACTION_RELOAD_AGENT
Definition crm.h:170
#define CRMD_ACTION_MIGRATED
Definition crm.h:172
#define RSC_START
Definition crm.h:199
#define RSC_STOP
Definition crm.h:202
#define CRMD_ACTION_MIGRATE
Definition crm.h:171
#define RSC_STATUS
Definition crm.h:213
#define RSC_CANCEL
Definition crm.h:194
const char * pcmk__readable_interval(guint interval_ms)
Definition iso8601.c:1926
G_GNUC_INTERNAL void pcmk__new_ordering(pe_resource_t *first_rsc, char *first_task, pe_action_t *first_action, pe_resource_t *then_rsc, char *then_task, pe_action_t *then_action, uint32_t flags, pe_working_set_t *data_set)
#define crm_info(fmt, args...)
Definition logging.h:378
#define do_crm_log(level, fmt, args...)
Log a message.
Definition logging.h:172
#define crm_notice(fmt, args...)
Definition logging.h:377
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define crm_debug(fmt, args...)
Definition logging.h:380
#define crm_trace(fmt, args...)
Definition logging.h:381
#define LOG_TRACE
Definition logging.h:37
#define pcmk__config_err(fmt...)
#define ID(x)
Definition msg_xml.h:480
#define XML_LRM_ATTR_INTERVAL
Definition msg_xml.h:309
#define XML_LRM_ATTR_TASK
Definition msg_xml.h:315
#define XML_LRM_ATTR_CALLID
Definition msg_xml.h:327
#define XML_LRM_ATTR_INTERVAL_MS
Definition msg_xml.h:313
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:496
const char * action
Definition pcmk_fence.c:30
pe_action_t * pcmk__new_cancel_action(pe_resource_t *rsc, const char *task, guint interval_ms, const pe_node_t *node)
void pcmk__schedule_cancel(pe_resource_t *rsc, const char *call_id, const char *task, guint interval_ms, const pe_node_t *node, const char *reason)
void pcmk__create_recurring_actions(pe_resource_t *rsc)
void pcmk__reschedule_recurring(pe_resource_t *rsc, const char *task, guint interval_ms, pe_node_t *node)
bool pcmk__action_is_recurring(const pe_action_t *action)
#define pe_rsc_block
Definition pe_types.h:274
#define pe_rsc_managed
Definition pe_types.h:273
@ pe_order_implies_then
Definition pe_types.h:512
@ pe_order_optional
Definition pe_types.h:508
@ pe_order_runnable_left
Definition pe_types.h:518
#define pe_rsc_unique
Definition pe_types.h:278
@ pe_action_optional
Definition pe_types.h:319
@ pe_action_runnable
Definition pe_types.h:318
@ pe_action_reschedule
Definition pe_types.h:338
#define pe_rsc_maintenance
Definition pe_types.h:308
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
#define demote_key(rsc)
Definition internal.h:431
GList * find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
#define reload_key(rsc)
Definition internal.h:410
#define start_action(rsc, node, optional)
Definition internal.h:412
void trigger_unfencing(pe_resource_t *rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t *data_set)
Definition utils.c:616
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, const pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Create or update an action object.
Definition pe_actions.c:942
#define start_key(rsc)
Definition internal.h:411
#define stop_key(rsc)
Definition internal.h:405
#define pe_rsc_debug(rsc, fmt, args...)
Definition internal.h:49
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition utils.c:488
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
#define promote_key(rsc)
Definition internal.h:421
#define pe_rsc_info(rsc, fmt, args...)
Definition internal.h:48
void pe__add_action_expected_result(pe_action_t *action, int expected_result)
#define pe__clear_action_flags(action, flags_to_clear)
Definition internal.h:98
xmlNode * find_rsc_op_entry(const pe_resource_t *rsc, const char *key)
Definition pe_actions.c:145
#define pe__set_action_flags(action, flags_to_set)
Definition internal.h:89
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition common.c:500
#define CRM_ASSERT(expr)
Definition results.h:42
@ CRM_EX_NOT_RUNNING
Service safely stopped.
Definition results.h:246
@ CRM_EX_PROMOTED
Service active and promoted.
Definition results.h:247
@ pcmk_rc_ok
Definition results.h:151
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1193
@ pcmk__str_none
@ pcmk__str_casei
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition strings.c:311
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:957
char * uuid
Definition pe_types.h:438
char * task
Definition pe_types.h:437
GHashTable * meta
Definition pe_types.h:447
char * cancel_task
Definition pe_types.h:439
enum pe_action_flags flags
Definition pe_types.h:442
struct pe_node_shared_s * details
Definition pe_types.h:268
gboolean online
Definition pe_types.h:236
const char * uname
Definition pe_types.h:232
gboolean unclean
Definition pe_types.h:240
gboolean maintenance
Definition pe_types.h:245
GList * actions
Definition pe_types.h:391
pe_working_set_t * cluster
Definition pe_types.h:353
pe_node_t * allocated_to
Definition pe_types.h:395
unsigned long long flags
Definition pe_types.h:373
resource_alloc_functions_t * cmds
Definition pe_types.h:359
enum rsc_role_e next_role
Definition pe_types.h:403
enum rsc_role_e role
Definition pe_types.h:402
xmlNode * ops_xml
Definition pe_types.h:351
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2521
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2547