pacemaker 2.1.8-2.1.8
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-2024 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/common/xml.h>
16#include <pacemaker-internal.h>
17
19
20// Information parsed from an operation history entry in the CIB
21struct op_history {
22 // XML attributes
23 const char *id; // ID of history entry
24 const char *name; // Action name
25
26 // Parsed information
27 char *key; // Operation key for action
28 enum rsc_role_e role; // Action role (or pcmk_role_unknown for default)
29 guint interval_ms; // Action interval
30};
31
40static guint
41xe_interval(const xmlNode *xml)
42{
43 guint interval_ms = 0U;
44
46 &interval_ms);
47 return interval_ms;
48}
49
61static bool
62is_op_dup(const pcmk_resource_t *rsc, const char *name, guint interval_ms)
63{
64 const char *id = NULL;
65
66 for (xmlNode *op = pcmk__xe_first_child(rsc->ops_xml, PCMK_XE_OP, NULL,
67 NULL);
68 op != NULL; op = pcmk__xe_next_same(op)) {
69
70 // Check whether action name and interval match
71 if (!pcmk__str_eq(crm_element_value(op, PCMK_XA_NAME), name,
73 || (xe_interval(op) != interval_ms)) {
74 continue;
75 }
76
77 if (pcmk__xe_id(op) == NULL) {
78 continue; // Shouldn't be possible
79 }
80
81 if (id == NULL) {
82 id = pcmk__xe_id(op); // First matching op
83 } else {
84 pcmk__config_err("Operation %s is duplicate of %s (do not use "
85 "same name and interval combination more "
86 "than once per resource)", pcmk__xe_id(op), id);
87 return true;
88 }
89 }
90 return false;
91}
92
109static bool
110op_cannot_recur(const char *name)
111{
116 NULL);
117}
118
129static bool
130is_recurring_history(const pcmk_resource_t *rsc, const xmlNode *xml,
131 struct op_history *op)
132{
133 const char *role = NULL;
134
135 op->interval_ms = xe_interval(xml);
136 if (op->interval_ms == 0) {
137 return false; // Not recurring
138 }
139
140 op->id = pcmk__xe_id(xml);
141 if (pcmk__str_empty(op->id)) {
142 pcmk__config_err("Ignoring resource history entry without ID");
143 return false; // Shouldn't be possible (unless CIB was manually edited)
144 }
145
146 op->name = crm_element_value(xml, PCMK_XA_NAME);
147 if (op_cannot_recur(op->name)) {
148 pcmk__config_err("Ignoring %s because %s action cannot be recurring",
149 op->id, pcmk__s(op->name, "unnamed"));
150 return false;
151 }
152
153 // There should only be one recurring operation per action/interval
154 if (is_op_dup(rsc, op->name, op->interval_ms)) {
155 return false;
156 }
157
158 // Ensure role is valid if specified
159 role = crm_element_value(xml, PCMK_XA_ROLE);
160 if (role == NULL) {
161 op->role = pcmk_role_unknown;
162 } else {
163 op->role = pcmk_parse_role(role);
164 if (op->role == pcmk_role_unknown) {
165 pcmk__config_err("Ignoring %s role because %s is not a valid role",
166 op->id, role);
167 return false;
168 }
169 }
170
171 // Only actions that are still configured and enabled matter
172 if (pcmk__find_action_config(rsc, op->name, op->interval_ms,
173 false) == NULL) {
174 pcmk__rsc_trace(rsc,
175 "Ignoring %s (%s-interval %s for %s) because it is "
176 "disabled or no longer in configuration",
177 op->id, pcmk__readable_interval(op->interval_ms),
178 op->name, rsc->id);
179 return false;
180 }
181
182 op->key = pcmk__op_key(rsc->id, op->name, op->interval_ms);
183 return true;
184}
185
197static bool
198active_recurring_should_be_optional(const pcmk_resource_t *rsc,
199 const pcmk_node_t *node, const char *key,
200 pcmk_action_t *start)
201{
202 GList *possible_matches = NULL;
203
204 if (node == NULL) { // Should only be possible if unmanaged and stopped
205 pcmk__rsc_trace(rsc,
206 "%s will be mandatory because resource is unmanaged",
207 key);
208 return false;
209 }
210
211 if (!pcmk_is_set(rsc->cmds->action_flags(start, NULL),
213 pcmk__rsc_trace(rsc, "%s will be mandatory because %s is",
214 key, start->uuid);
215 return false;
216 }
217
218 possible_matches = find_actions_exact(rsc->actions, key, node);
219 if (possible_matches == NULL) {
220 pcmk__rsc_trace(rsc,
221 "%s will be mandatory because it is not active on %s",
222 key, pcmk__node_name(node));
223 return false;
224 }
225
226 for (const GList *iter = possible_matches;
227 iter != NULL; iter = iter->next) {
228
229 const pcmk_action_t *op = (const pcmk_action_t *) iter->data;
230
231 if (pcmk_is_set(op->flags, pcmk_action_reschedule)) {
232 pcmk__rsc_trace(rsc,
233 "%s will be mandatory because "
234 "it needs to be rescheduled", key);
235 g_list_free(possible_matches);
236 return false;
237 }
238 }
239
240 g_list_free(possible_matches);
241 return true;
242}
243
253static void
254recurring_op_for_active(pcmk_resource_t *rsc, pcmk_action_t *start,
255 const pcmk_node_t *node, const struct op_history *op)
256{
257 pcmk_action_t *mon = NULL;
258 bool is_optional = true;
259 bool role_match = false;
260 enum rsc_role_e monitor_role = op->role;
261
262 // We're only interested in recurring actions for active roles
263 if (monitor_role == pcmk_role_stopped) {
264 return;
265 }
266
267 is_optional = active_recurring_should_be_optional(rsc, node, op->key,
268 start);
269
270 // Check whether monitor's role matches role resource will have
271 if (monitor_role == pcmk_role_unknown) {
272 monitor_role = pcmk_role_unpromoted;
273 role_match = (rsc->next_role != pcmk_role_promoted);
274 } else {
275 role_match = (rsc->next_role == monitor_role);
276 }
277
278 if (!role_match) {
279 if (is_optional) { // It's running, so cancel it
280 char *after_key = NULL;
281 pcmk_action_t *cancel_op = pcmk__new_cancel_action(rsc, op->name,
282 op->interval_ms,
283 node);
284
285 switch (rsc->role) {
288 if (rsc->next_role == pcmk_role_promoted) {
289 after_key = promote_key(rsc);
290
291 } else if (rsc->next_role == pcmk_role_stopped) {
292 after_key = stop_key(rsc);
293 }
294
295 break;
297 after_key = demote_key(rsc);
298 break;
299 default:
300 break;
301 }
302
303 if (after_key) {
304 pcmk__new_ordering(rsc, NULL, cancel_op, rsc, after_key, NULL,
306 rsc->cluster);
307 }
308 }
309
310 do_crm_log((is_optional? LOG_INFO : LOG_TRACE),
311 "%s recurring action %s because %s configured for %s role "
312 "(not %s)",
313 (is_optional? "Cancelling" : "Ignoring"), op->key, op->id,
314 pcmk_role_text(monitor_role),
315 pcmk_role_text(rsc->next_role));
316 return;
317 }
318
319 pcmk__rsc_trace(rsc,
320 "Creating %s recurring action %s for %s (%s %s on %s)",
321 (is_optional? "optional" : "mandatory"), op->key,
322 op->id, rsc->id, pcmk_role_text(rsc->next_role),
323 pcmk__node_name(node));
324
325 mon = custom_action(rsc, strdup(op->key), op->name, node, is_optional,
326 rsc->cluster);
327
328 if (!pcmk_is_set(start->flags, pcmk_action_runnable)) {
329 pcmk__rsc_trace(rsc, "%s is unrunnable because start is", mon->uuid);
331
332 } else if ((node == NULL) || !node->details->online
333 || node->details->unclean) {
334 pcmk__rsc_trace(rsc, "%s is unrunnable because no node is available",
335 mon->uuid);
337
338 } else if (!pcmk_is_set(mon->flags, pcmk_action_optional)) {
339 pcmk__rsc_info(rsc, "Start %s-interval %s for %s on %s",
340 pcmk__readable_interval(op->interval_ms), mon->task,
341 rsc->id, pcmk__node_name(node));
342 }
343
344 if (rsc->next_role == pcmk_role_promoted) {
346 }
347
348 // Order monitor relative to other actions
349 if ((node == NULL) || pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
350 pcmk__new_ordering(rsc, start_key(rsc), NULL,
351 NULL, strdup(mon->uuid), mon,
354 rsc->cluster);
355
356 pcmk__new_ordering(rsc, reload_key(rsc), NULL,
357 NULL, strdup(mon->uuid), mon,
360 rsc->cluster);
361
362 if (rsc->next_role == pcmk_role_promoted) {
363 pcmk__new_ordering(rsc, promote_key(rsc), NULL,
364 rsc, NULL, mon,
367 rsc->cluster);
368
369 } else if (rsc->role == pcmk_role_promoted) {
370 pcmk__new_ordering(rsc, demote_key(rsc), NULL,
371 rsc, NULL, mon,
374 rsc->cluster);
375 }
376 }
377}
378
389static void
390cancel_if_running(pcmk_resource_t *rsc, const pcmk_node_t *node,
391 const char *key, const char *name, guint interval_ms)
392{
393 GList *possible_matches = find_actions_exact(rsc->actions, key, node);
394 pcmk_action_t *cancel_op = NULL;
395
396 if (possible_matches == NULL) {
397 return; // Recurring action isn't running on this node
398 }
399 g_list_free(possible_matches);
400
401 cancel_op = pcmk__new_cancel_action(rsc, name, interval_ms, node);
402
403 switch (rsc->next_role) {
406 /* Order starts after cancel. If the current role is
407 * stopped, this cancels the monitor before the resource
408 * starts; if the current role is started, then this cancels
409 * the monitor on a migration target before starting there.
410 */
411 pcmk__new_ordering(rsc, NULL, cancel_op,
412 rsc, start_key(rsc), NULL,
414 break;
415 default:
416 break;
417 }
418 pcmk__rsc_info(rsc,
419 "Cancelling %s-interval %s action for %s on %s because "
420 "configured for " PCMK_ROLE_STOPPED " role (not %s)",
421 pcmk__readable_interval(interval_ms), name, rsc->id,
422 pcmk__node_name(node), pcmk_role_text(rsc->next_role));
423}
424
433static void
434order_after_probes(pcmk_resource_t *rsc, const pcmk_node_t *node,
436{
437 GList *probes = pe__resource_actions(rsc, node, PCMK_ACTION_MONITOR, FALSE);
438
439 for (GList *iter = probes; iter != NULL; iter = iter->next) {
440 order_actions((pcmk_action_t *) iter->data, action,
442 }
443 g_list_free(probes);
444}
445
454static void
455order_after_stops(pcmk_resource_t *rsc, const pcmk_node_t *node,
457{
458 GList *stop_ops = pe__resource_actions(rsc, node, PCMK_ACTION_STOP, TRUE);
459
460 for (GList *iter = stop_ops; iter != NULL; iter = iter->next) {
461 pcmk_action_t *stop = (pcmk_action_t *) iter->data;
462
463 if (!pcmk_is_set(stop->flags, pcmk_action_optional)
466 pcmk__rsc_trace(rsc, "%s optional on %s: unmanaged",
467 action->uuid, pcmk__node_name(node));
469 }
470
471 if (!pcmk_is_set(stop->flags, pcmk_action_runnable)) {
472 crm_debug("%s unrunnable on %s: stop is unrunnable",
473 action->uuid, pcmk__node_name(node));
475 }
476
478 pcmk__new_ordering(rsc, stop_key(rsc), stop,
479 NULL, NULL, action,
482 rsc->cluster);
483 }
484 }
485 g_list_free(stop_ops);
486}
487
496static void
497recurring_op_for_inactive(pcmk_resource_t *rsc, const pcmk_node_t *node,
498 const struct op_history *op)
499{
500 GList *possible_matches = NULL;
501
502 // We're only interested in recurring actions for the inactive role
503 if (op->role != pcmk_role_stopped) {
504 return;
505 }
506
507 if (!pcmk_is_set(rsc->flags, pcmk_rsc_unique)) {
508 crm_notice("Ignoring %s (recurring monitors for " PCMK_ROLE_STOPPED
509 " role are not supported for anonymous clones)", op->id);
510 return; // @TODO add support
511 }
512
513 pcmk__rsc_trace(rsc,
514 "Creating recurring action %s for %s on nodes "
515 "where it should not be running", op->id, rsc->id);
516
517 for (GList *iter = rsc->cluster->nodes; iter != NULL; iter = iter->next) {
518 pcmk_node_t *stop_node = (pcmk_node_t *) iter->data;
519
520 bool is_optional = true;
521 pcmk_action_t *stopped_mon = NULL;
522
523 // Cancel action on node where resource will be active
524 if ((node != NULL)
525 && pcmk__str_eq(stop_node->details->uname, node->details->uname,
527 cancel_if_running(rsc, node, op->key, op->name, op->interval_ms);
528 continue;
529 }
530
531 // Recurring action on this node is optional if it's already active here
532 possible_matches = find_actions_exact(rsc->actions, op->key, stop_node);
533 is_optional = (possible_matches != NULL);
534 g_list_free(possible_matches);
535
536 pcmk__rsc_trace(rsc,
537 "Creating %s recurring action %s for %s (%s "
538 PCMK_ROLE_STOPPED " on %s)",
539 (is_optional? "optional" : "mandatory"),
540 op->key, op->id, rsc->id, pcmk__node_name(stop_node));
541
542 stopped_mon = custom_action(rsc, strdup(op->key), op->name, stop_node,
543 is_optional, rsc->cluster);
544
546
548 order_after_probes(rsc, stop_node, stopped_mon);
549 }
550
551 /* The recurring action is for the inactive role, so it shouldn't be
552 * performed until the resource is inactive.
553 */
554 order_after_stops(rsc, stop_node, stopped_mon);
555
556 if (!stop_node->details->online || stop_node->details->unclean) {
557 pcmk__rsc_debug(rsc, "%s unrunnable on %s: node unavailable)",
558 stopped_mon->uuid, pcmk__node_name(stop_node));
560 }
561
562 if (pcmk_is_set(stopped_mon->flags, pcmk_action_runnable)
563 && !pcmk_is_set(stopped_mon->flags, pcmk_action_optional)) {
564 crm_notice("Start recurring %s-interval %s for "
565 PCMK_ROLE_STOPPED " %s on %s",
566 pcmk__readable_interval(op->interval_ms),
567 stopped_mon->task, rsc->id, pcmk__node_name(stop_node));
568 }
569 }
570}
571
578void
580{
581 pcmk_action_t *start = NULL;
582
584 pcmk__rsc_trace(rsc,
585 "Skipping recurring actions for blocked resource %s",
586 rsc->id);
587 return;
588 }
589
591 pcmk__rsc_trace(rsc,
592 "Skipping recurring actions for %s "
593 "in maintenance mode", rsc->id);
594 return;
595 }
596
597 if (rsc->allocated_to == NULL) {
598 // Recurring actions for active roles not needed
599
600 } else if (rsc->allocated_to->details->maintenance) {
601 pcmk__rsc_trace(rsc,
602 "Skipping recurring actions for %s on %s "
603 "in maintenance mode",
604 rsc->id, pcmk__node_name(rsc->allocated_to));
605
606 } else if ((rsc->next_role != pcmk_role_stopped)
608 // Recurring actions for active roles needed
609 start = start_action(rsc, rsc->allocated_to, TRUE);
610 }
611
612 pcmk__rsc_trace(rsc, "Creating any recurring actions needed for %s",
613 rsc->id);
614
615 for (xmlNode *op = pcmk__xe_first_child(rsc->ops_xml, PCMK_XE_OP, NULL,
616 NULL);
617 op != NULL; op = pcmk__xe_next_same(op)) {
618
619 struct op_history op_history = { NULL, };
620
621 if (!is_recurring_history(rsc, op, &op_history)) {
622 continue;
623 }
624
625 if (start != NULL) {
626 recurring_op_for_active(rsc, start, rsc->allocated_to, &op_history);
627 }
628 recurring_op_for_inactive(rsc, rsc->allocated_to, &op_history);
629
630 free(op_history.key);
631 }
632}
633
647 guint interval_ms, const pcmk_node_t *node)
648{
649 pcmk_action_t *cancel_op = NULL;
650 char *key = NULL;
651 char *interval_ms_s = NULL;
652
653 CRM_ASSERT((rsc != NULL) && (task != NULL) && (node != NULL));
654
655 key = pcmk__op_key(rsc->id, task, interval_ms);
656
657 /* This finds an existing action by key, so custom_action() does not change
658 * cancel_op->task.
659 */
660 cancel_op = custom_action(rsc, key, PCMK_ACTION_CANCEL, node, FALSE,
661 rsc->cluster);
662
664 pcmk__str_update(&(cancel_op->cancel_task), task);
665
666 interval_ms_s = crm_strdup_printf("%u", interval_ms);
667 pcmk__insert_meta(cancel_op, PCMK_XA_OPERATION, task);
668 pcmk__insert_meta(cancel_op, PCMK_META_INTERVAL, interval_ms_s);
669 free(interval_ms_s);
670
671 return cancel_op;
672}
673
685void
686pcmk__schedule_cancel(pcmk_resource_t *rsc, const char *call_id,
687 const char *task, guint interval_ms,
688 const pcmk_node_t *node, const char *reason)
689{
690 pcmk_action_t *cancel = NULL;
691
692 CRM_CHECK((rsc != NULL) && (task != NULL)
693 && (node != NULL) && (reason != NULL),
694 return);
695
696 crm_info("Recurring %s-interval %s for %s will be stopped on %s: %s",
697 pcmk__readable_interval(interval_ms), task, rsc->id,
698 pcmk__node_name(node), reason);
699 cancel = pcmk__new_cancel_action(rsc, task, interval_ms, node);
700 pcmk__insert_meta(cancel, PCMK__XA_CALL_ID, call_id);
701
702 // Cancellations happen after stops
703 pcmk__new_ordering(rsc, stop_key(rsc), NULL, rsc, NULL, cancel,
705}
706
716void
718 guint interval_ms, pcmk_node_t *node)
719{
720 pcmk_action_t *op = NULL;
721
722 trigger_unfencing(rsc, node, "Device parameters changed (reschedule)",
723 NULL, rsc->cluster);
724 op = custom_action(rsc, pcmk__op_key(rsc->id, task, interval_ms),
725 task, node, TRUE, rsc->cluster);
727}
728
737bool
739{
740 guint interval_ms = 0;
741
743 &interval_ms) != pcmk_rc_ok) {
744 return false;
745 }
746 return (interval_ms > 0);
747}
@ pcmk__ar_first_implies_then
@ pcmk__ar_unrunnable_first_blocks
'then' is runnable (and migratable) only if 'first' is runnable
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_CANCEL
Definition actions.h:45
#define PCMK_ACTION_PROMOTE
Definition actions.h:66
#define PCMK_ACTION_START
Definition actions.h:72
#define PCMK_ACTION_MIGRATE_FROM
Definition actions.h:58
@ pcmk_action_runnable
Definition actions.h:207
@ pcmk_action_reschedule
Definition actions.h:236
@ pcmk_action_optional
Definition actions.h:210
#define PCMK_ACTION_MIGRATE_TO
Definition actions.h:59
#define PCMK_ACTION_MONITOR
Definition actions.h:60
#define PCMK_ACTION_RELOAD_AGENT
Definition actions.h:70
#define PCMK_ACTION_DEMOTE
Definition actions.h:49
#define pcmk__set_action_flags(action, flags_to_set)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition actions.c:196
#define pcmk__clear_action_flags(action, flags_to_clear)
const char * name
Definition cib.c:26
char int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
Definition strings.c:451
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:98
uint32_t id
Definition cpg.c:0
const char * pcmk__readable_interval(guint interval_ms)
Definition iso8601.c:2134
G_GNUC_INTERNAL void pcmk__new_ordering(pcmk_resource_t *first_rsc, char *first_task, pcmk_action_t *first_action, pcmk_resource_t *then_rsc, char *then_task, pcmk_action_t *then_action, uint32_t flags, pcmk_scheduler_t *sched)
#define crm_info(fmt, args...)
Definition logging.h:397
#define do_crm_log(level, fmt, args...)
Log a message.
Definition logging.h:181
#define crm_notice(fmt, args...)
Definition logging.h:395
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define LOG_TRACE
Definition logging.h:38
#define pcmk__config_err(fmt...)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
#define pcmk__insert_meta(obj, name, value)
#define PCMK_META_INTERVAL
Definition options.h:91
const char * action
Definition pcmk_fence.c:30
pcmk_action_t * pcmk__new_cancel_action(pcmk_resource_t *rsc, const char *task, guint interval_ms, const pcmk_node_t *node)
bool pcmk__action_is_recurring(const pcmk_action_t *action)
void pcmk__schedule_cancel(pcmk_resource_t *rsc, const char *call_id, const char *task, guint interval_ms, const pcmk_node_t *node, const char *reason)
void pcmk__reschedule_recurring(pcmk_resource_t *rsc, const char *task, guint interval_ms, pcmk_node_t *node)
void pcmk__create_recurring_actions(pcmk_resource_t *rsc)
#define demote_key(rsc)
Definition internal.h:229
GList * pe__resource_actions(const pcmk_resource_t *rsc, const pcmk_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
#define reload_key(rsc)
Definition internal.h:218
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
Definition utils.c:457
#define start_action(rsc, node, optional)
Definition internal.h:220
#define start_key(rsc)
Definition internal.h:219
#define stop_key(rsc)
Definition internal.h:213
void pe__add_action_expected_result(pcmk_action_t *action, int expected_result)
pcmk_action_t * custom_action(pcmk_resource_t *rsc, char *key, const char *task, const pcmk_node_t *on_node, gboolean optional, pcmk_scheduler_t *scheduler)
Create or update an action object.
#define promote_key(rsc)
Definition internal.h:224
void trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, const char *reason, pcmk_action_t *dependency, pcmk_scheduler_t *scheduler)
Definition utils.c:591
xmlNode * pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, bool include_disabled)
Definition pe_actions.c:132
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
@ pcmk_rsc_unique
Definition resources.h:100
@ pcmk_rsc_maintenance
Definition resources.h:166
@ pcmk_rsc_blocked
Definition resources.h:91
@ pcmk_rsc_managed
Definition resources.h:88
#define CRM_ASSERT(expr)
Definition results.h:42
@ CRM_EX_NOT_RUNNING
Service safely stopped.
Definition results.h:264
@ CRM_EX_PROMOTED
Service active and promoted.
Definition results.h:265
@ pcmk_rc_ok
Definition results.h:162
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition roles.c:23
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition roles.c:59
rsc_role_e
Definition roles.h:34
@ pcmk_role_started
Started.
Definition roles.h:37
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:35
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:38
@ pcmk_role_promoted
Promoted.
Definition roles.h:39
@ pcmk_role_stopped
Stopped.
Definition roles.h:36
#define PCMK_ROLE_STOPPED
Definition roles.h:25
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__rsc_debug(rsc, fmt, args...)
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1277
@ 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:1050
char * uuid
Definition actions.h:344
char * task
Definition actions.h:343
char * cancel_task
Definition actions.h:345
enum pe_action_flags flags
Definition actions.h:349
struct pe_node_shared_s * details
Definition nodes.h:167
gboolean online
Definition nodes.h:80
const char * uname
Definition nodes.h:73
gboolean unclean
Definition nodes.h:91
gboolean maintenance
Definition nodes.h:104
pcmk_assignment_methods_t * cmds
Definition resources.h:413
GList * actions
Definition resources.h:444
pcmk_scheduler_t * cluster
Definition resources.h:408
pcmk_node_t * allocated_to
Definition resources.h:447
unsigned long long flags
Definition resources.h:428
enum rsc_role_e next_role
Definition resources.h:465
enum rsc_role_e role
Definition resources.h:464
xmlNode * ops_xml
Definition resources.h:406
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
Wrappers for and extensions to libxml2.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml.c:440
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition xml.c:2108
#define PCMK_XA_OPERATION
Definition xml_names.h:344
#define PCMK_XA_ROLE
Definition xml_names.h:382
#define PCMK_XA_NAME
Definition xml_names.h:325
#define PCMK_XE_OP
Definition xml_names.h:143
#define PCMK__XA_CALL_ID