pacemaker 2.1.7-2.1.7
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>
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{
45}
46
58static bool
59is_op_dup(const pcmk_resource_t *rsc, const char *name, guint interval_ms)
60{
61 const char *id = NULL;
62
63 for (xmlNode *op = first_named_child(rsc->ops_xml, "op");
64 op != NULL; op = crm_next_same_xml(op)) {
65
66 // Check whether action name and interval match
67 if (!pcmk__str_eq(crm_element_value(op, "name"), name, pcmk__str_none)
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{
111 NULL);
112}
113
124static bool
125is_recurring_history(const pcmk_resource_t *rsc, const xmlNode *xml,
126 struct op_history *op)
127{
128 const char *role = NULL;
129
130 op->interval_ms = xe_interval(xml);
131 if (op->interval_ms == 0) {
132 return false; // Not recurring
133 }
134
135 op->id = ID(xml);
136 if (pcmk__str_empty(op->id)) {
137 pcmk__config_err("Ignoring resource history entry without ID");
138 return false; // Shouldn't be possible (unless CIB was manually edited)
139 }
140
141 op->name = crm_element_value(xml, "name");
142 if (op_cannot_recur(op->name)) {
143 pcmk__config_err("Ignoring %s because %s action cannot be recurring",
144 op->id, pcmk__s(op->name, "unnamed"));
145 return false;
146 }
147
148 // There should only be one recurring operation per action/interval
149 if (is_op_dup(rsc, op->name, op->interval_ms)) {
150 return false;
151 }
152
153 // Ensure role is valid if specified
154 role = crm_element_value(xml, "role");
155 if (role == NULL) {
156 op->role = pcmk_role_unknown;
157 } else {
158 op->role = text2role(role);
159 if (op->role == pcmk_role_unknown) {
160 pcmk__config_err("Ignoring %s because %s is not a valid role",
161 op->id, role);
162 return false;
163 }
164 }
165
166 // Only actions that are still configured and enabled matter
167 if (pcmk__find_action_config(rsc, op->name, op->interval_ms,
168 false) == NULL) {
169 pe_rsc_trace(rsc,
170 "Ignoring %s (%s-interval %s for %s) because it is "
171 "disabled or no longer in configuration",
172 op->id, pcmk__readable_interval(op->interval_ms), op->name,
173 rsc->id);
174 return false;
175 }
176
177 op->key = pcmk__op_key(rsc->id, op->name, op->interval_ms);
178 return true;
179}
180
192static bool
193active_recurring_should_be_optional(const pcmk_resource_t *rsc,
194 const pcmk_node_t *node, const char *key,
195 pcmk_action_t *start)
196{
197 GList *possible_matches = NULL;
198
199 if (node == NULL) { // Should only be possible if unmanaged and stopped
200 pe_rsc_trace(rsc, "%s will be mandatory because resource is unmanaged",
201 key);
202 return false;
203 }
204
205 if (!pcmk_is_set(rsc->cmds->action_flags(start, NULL),
207 pe_rsc_trace(rsc, "%s will be mandatory because %s is",
208 key, start->uuid);
209 return false;
210 }
211
212 possible_matches = find_actions_exact(rsc->actions, key, node);
213 if (possible_matches == NULL) {
214 pe_rsc_trace(rsc, "%s will be mandatory because it is not active on %s",
215 key, pe__node_name(node));
216 return false;
217 }
218
219 for (const GList *iter = possible_matches;
220 iter != NULL; iter = iter->next) {
221
222 const pcmk_action_t *op = (const pcmk_action_t *) iter->data;
223
224 if (pcmk_is_set(op->flags, pcmk_action_reschedule)) {
225 pe_rsc_trace(rsc,
226 "%s will be mandatory because "
227 "it needs to be rescheduled", key);
228 g_list_free(possible_matches);
229 return false;
230 }
231 }
232
233 g_list_free(possible_matches);
234 return true;
235}
236
246static void
247recurring_op_for_active(pcmk_resource_t *rsc, pcmk_action_t *start,
248 const pcmk_node_t *node, const struct op_history *op)
249{
250 pcmk_action_t *mon = NULL;
251 bool is_optional = true;
252 const bool is_default_role = (op->role == pcmk_role_unknown);
253
254 // We're only interested in recurring actions for active roles
255 if (op->role == pcmk_role_stopped) {
256 return;
257 }
258
259 is_optional = active_recurring_should_be_optional(rsc, node, op->key,
260 start);
261
262 if ((!is_default_role && (rsc->next_role != op->role))
263 || (is_default_role && (rsc->next_role == pcmk_role_promoted))) {
264 // Configured monitor role doesn't match role resource will have
265
266 if (is_optional) { // It's running, so cancel it
267 char *after_key = NULL;
268 pcmk_action_t *cancel_op = pcmk__new_cancel_action(rsc, op->name,
269 op->interval_ms,
270 node);
271
272 switch (rsc->role) {
275 if (rsc->next_role == pcmk_role_promoted) {
276 after_key = promote_key(rsc);
277
278 } else if (rsc->next_role == pcmk_role_stopped) {
279 after_key = stop_key(rsc);
280 }
281
282 break;
284 after_key = demote_key(rsc);
285 break;
286 default:
287 break;
288 }
289
290 if (after_key) {
291 pcmk__new_ordering(rsc, NULL, cancel_op, rsc, after_key, NULL,
293 rsc->cluster);
294 }
295 }
296
297 do_crm_log((is_optional? LOG_INFO : LOG_TRACE),
298 "%s recurring action %s because %s configured for %s role "
299 "(not %s)",
300 (is_optional? "Cancelling" : "Ignoring"), op->key, op->id,
301 role2text(is_default_role? pcmk_role_unpromoted : op->role),
302 role2text(rsc->next_role));
303 return;
304 }
305
306 pe_rsc_trace(rsc,
307 "Creating %s recurring action %s for %s (%s %s on %s)",
308 (is_optional? "optional" : "mandatory"), op->key,
309 op->id, rsc->id, role2text(rsc->next_role),
310 pe__node_name(node));
311
312 mon = custom_action(rsc, strdup(op->key), op->name, node, is_optional,
313 rsc->cluster);
314
315 if (!pcmk_is_set(start->flags, pcmk_action_runnable)) {
316 pe_rsc_trace(rsc, "%s is unrunnable because start is", mon->uuid);
318
319 } else if ((node == NULL) || !node->details->online
320 || node->details->unclean) {
321 pe_rsc_trace(rsc, "%s is unrunnable because no node is available",
322 mon->uuid);
324
325 } else if (!pcmk_is_set(mon->flags, pcmk_action_optional)) {
326 pe_rsc_info(rsc, "Start %s-interval %s for %s on %s",
327 pcmk__readable_interval(op->interval_ms), mon->task,
328 rsc->id, pe__node_name(node));
329 }
330
331 if (rsc->next_role == pcmk_role_promoted) {
333 }
334
335 // Order monitor relative to other actions
336 if ((node == NULL) || pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
337 pcmk__new_ordering(rsc, start_key(rsc), NULL,
338 NULL, strdup(mon->uuid), mon,
341 rsc->cluster);
342
343 pcmk__new_ordering(rsc, reload_key(rsc), NULL,
344 NULL, strdup(mon->uuid), mon,
347 rsc->cluster);
348
349 if (rsc->next_role == pcmk_role_promoted) {
350 pcmk__new_ordering(rsc, promote_key(rsc), NULL,
351 rsc, NULL, mon,
354 rsc->cluster);
355
356 } else if (rsc->role == pcmk_role_promoted) {
357 pcmk__new_ordering(rsc, demote_key(rsc), NULL,
358 rsc, NULL, mon,
361 rsc->cluster);
362 }
363 }
364}
365
376static void
377cancel_if_running(pcmk_resource_t *rsc, const pcmk_node_t *node,
378 const char *key, const char *name, guint interval_ms)
379{
380 GList *possible_matches = find_actions_exact(rsc->actions, key, node);
381 pcmk_action_t *cancel_op = NULL;
382
383 if (possible_matches == NULL) {
384 return; // Recurring action isn't running on this node
385 }
386 g_list_free(possible_matches);
387
388 cancel_op = pcmk__new_cancel_action(rsc, name, interval_ms, node);
389
390 switch (rsc->next_role) {
393 /* Order starts after cancel. If the current role is
394 * stopped, this cancels the monitor before the resource
395 * starts; if the current role is started, then this cancels
396 * the monitor on a migration target before starting there.
397 */
398 pcmk__new_ordering(rsc, NULL, cancel_op,
399 rsc, start_key(rsc), NULL,
401 break;
402 default:
403 break;
404 }
405 pe_rsc_info(rsc,
406 "Cancelling %s-interval %s action for %s on %s because "
407 "configured for " PCMK__ROLE_STOPPED " role (not %s)",
408 pcmk__readable_interval(interval_ms), name, rsc->id,
409 pe__node_name(node), role2text(rsc->next_role));
410}
411
420static void
421order_after_probes(pcmk_resource_t *rsc, const pcmk_node_t *node,
423{
424 GList *probes = pe__resource_actions(rsc, node, PCMK_ACTION_MONITOR, FALSE);
425
426 for (GList *iter = probes; iter != NULL; iter = iter->next) {
427 order_actions((pcmk_action_t *) iter->data, action,
429 }
430 g_list_free(probes);
431}
432
441static void
442order_after_stops(pcmk_resource_t *rsc, const pcmk_node_t *node,
444{
445 GList *stop_ops = pe__resource_actions(rsc, node, PCMK_ACTION_STOP, TRUE);
446
447 for (GList *iter = stop_ops; iter != NULL; iter = iter->next) {
448 pcmk_action_t *stop = (pcmk_action_t *) iter->data;
449
450 if (!pcmk_is_set(stop->flags, pcmk_action_optional)
453 pe_rsc_trace(rsc, "%s optional on %s: unmanaged",
454 action->uuid, pe__node_name(node));
456 }
457
458 if (!pcmk_is_set(stop->flags, pcmk_action_runnable)) {
459 crm_debug("%s unrunnable on %s: stop is unrunnable",
460 action->uuid, pe__node_name(node));
462 }
463
465 pcmk__new_ordering(rsc, stop_key(rsc), stop,
466 NULL, NULL, action,
469 rsc->cluster);
470 }
471 }
472 g_list_free(stop_ops);
473}
474
483static void
484recurring_op_for_inactive(pcmk_resource_t *rsc, const pcmk_node_t *node,
485 const struct op_history *op)
486{
487 GList *possible_matches = NULL;
488
489 // We're only interested in recurring actions for the inactive role
490 if (op->role != pcmk_role_stopped) {
491 return;
492 }
493
494 if (!pcmk_is_set(rsc->flags, pcmk_rsc_unique)) {
495 crm_notice("Ignoring %s (recurring monitors for " PCMK__ROLE_STOPPED
496 " role are not supported for anonymous clones)", op->id);
497 return; // @TODO add support
498 }
499
500 pe_rsc_trace(rsc, "Creating recurring action %s for %s on nodes "
501 "where it should not be running", op->id, rsc->id);
502
503 for (GList *iter = rsc->cluster->nodes; iter != NULL; iter = iter->next) {
504 pcmk_node_t *stop_node = (pcmk_node_t *) iter->data;
505
506 bool is_optional = true;
507 pcmk_action_t *stopped_mon = NULL;
508
509 // Cancel action on node where resource will be active
510 if ((node != NULL)
511 && pcmk__str_eq(stop_node->details->uname, node->details->uname,
513 cancel_if_running(rsc, node, op->key, op->name, op->interval_ms);
514 continue;
515 }
516
517 // Recurring action on this node is optional if it's already active here
518 possible_matches = find_actions_exact(rsc->actions, op->key, stop_node);
519 is_optional = (possible_matches != NULL);
520 g_list_free(possible_matches);
521
522 pe_rsc_trace(rsc,
523 "Creating %s recurring action %s for %s (%s "
524 PCMK__ROLE_STOPPED " on %s)",
525 (is_optional? "optional" : "mandatory"),
526 op->key, op->id, rsc->id, pe__node_name(stop_node));
527
528 stopped_mon = custom_action(rsc, strdup(op->key), op->name, stop_node,
529 is_optional, rsc->cluster);
530
532
534 order_after_probes(rsc, stop_node, stopped_mon);
535 }
536
537 /* The recurring action is for the inactive role, so it shouldn't be
538 * performed until the resource is inactive.
539 */
540 order_after_stops(rsc, stop_node, stopped_mon);
541
542 if (!stop_node->details->online || stop_node->details->unclean) {
543 pe_rsc_debug(rsc, "%s unrunnable on %s: node unavailable)",
544 stopped_mon->uuid, pe__node_name(stop_node));
546 }
547
548 if (pcmk_is_set(stopped_mon->flags, pcmk_action_runnable)
549 && !pcmk_is_set(stopped_mon->flags, pcmk_action_optional)) {
550 crm_notice("Start recurring %s-interval %s for "
551 PCMK__ROLE_STOPPED " %s on %s",
552 pcmk__readable_interval(op->interval_ms),
553 stopped_mon->task, rsc->id, pe__node_name(stop_node));
554 }
555 }
556}
557
564void
566{
567 pcmk_action_t *start = NULL;
568
570 pe_rsc_trace(rsc, "Skipping recurring actions for blocked resource %s",
571 rsc->id);
572 return;
573 }
574
576 pe_rsc_trace(rsc, "Skipping recurring actions for %s "
577 "in maintenance mode", rsc->id);
578 return;
579 }
580
581 if (rsc->allocated_to == NULL) {
582 // Recurring actions for active roles not needed
583
584 } else if (rsc->allocated_to->details->maintenance) {
585 pe_rsc_trace(rsc,
586 "Skipping recurring actions for %s on %s "
587 "in maintenance mode",
588 rsc->id, pe__node_name(rsc->allocated_to));
589
590 } else if ((rsc->next_role != pcmk_role_stopped)
592 // Recurring actions for active roles needed
593 start = start_action(rsc, rsc->allocated_to, TRUE);
594 }
595
596 pe_rsc_trace(rsc, "Creating any recurring actions needed for %s", rsc->id);
597
598 for (xmlNode *op = first_named_child(rsc->ops_xml, "op");
599 op != NULL; op = crm_next_same_xml(op)) {
600
601 struct op_history op_history = { NULL, };
602
603 if (!is_recurring_history(rsc, op, &op_history)) {
604 continue;
605 }
606
607 if (start != NULL) {
608 recurring_op_for_active(rsc, start, rsc->allocated_to, &op_history);
609 }
610 recurring_op_for_inactive(rsc, rsc->allocated_to, &op_history);
611
612 free(op_history.key);
613 }
614}
615
629 guint interval_ms, const pcmk_node_t *node)
630{
631 pcmk_action_t *cancel_op = NULL;
632 char *key = NULL;
633 char *interval_ms_s = NULL;
634
635 CRM_ASSERT((rsc != NULL) && (task != NULL) && (node != NULL));
636
637 // @TODO dangerous if possible to schedule another action with this key
638 key = pcmk__op_key(rsc->id, task, interval_ms);
639
640 cancel_op = custom_action(rsc, key, PCMK_ACTION_CANCEL, node, FALSE,
641 rsc->cluster);
642
644 pcmk__str_update(&cancel_op->cancel_task, task);
645
646 interval_ms_s = crm_strdup_printf("%u", interval_ms);
647 add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, task);
648 add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL_MS, interval_ms_s);
649 free(interval_ms_s);
650
651 return cancel_op;
652}
653
665void
666pcmk__schedule_cancel(pcmk_resource_t *rsc, const char *call_id,
667 const char *task, guint interval_ms,
668 const pcmk_node_t *node, const char *reason)
669{
670 pcmk_action_t *cancel = NULL;
671
672 CRM_CHECK((rsc != NULL) && (task != NULL)
673 && (node != NULL) && (reason != NULL),
674 return);
675
676 crm_info("Recurring %s-interval %s for %s will be stopped on %s: %s",
677 pcmk__readable_interval(interval_ms), task, rsc->id,
678 pe__node_name(node), reason);
679 cancel = pcmk__new_cancel_action(rsc, task, interval_ms, node);
680 add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
681
682 // Cancellations happen after stops
683 pcmk__new_ordering(rsc, stop_key(rsc), NULL, rsc, NULL, cancel,
685}
686
696void
698 guint interval_ms, pcmk_node_t *node)
699{
700 pcmk_action_t *op = NULL;
701
702 trigger_unfencing(rsc, node, "Device parameters changed (reschedule)",
703 NULL, rsc->cluster);
704 op = custom_action(rsc, pcmk__op_key(rsc->id, task, interval_ms),
705 task, node, TRUE, rsc->cluster);
707}
708
717bool
719{
720 guint interval_ms = 0;
721
724 &interval_ms) != pcmk_rc_ok) {
725 return false;
726 }
727 return (interval_ms > 0);
728}
@ 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:74
#define PCMK_ACTION_CANCEL
Definition actions.h:45
#define PCMK_ACTION_PROMOTE
Definition actions.h:65
#define PCMK_ACTION_START
Definition actions.h:71
#define PCMK_ACTION_MIGRATE_FROM
Definition actions.h:57
@ pcmk_action_runnable
Whether action is runnable.
Definition actions.h:241
@ pcmk_action_reschedule
Whether action is recurring monitor that must be rescheduled if active.
Definition actions.h:269
@ pcmk_action_optional
Whether action should not be executed.
Definition actions.h:244
#define PCMK_ACTION_MIGRATE_TO
Definition actions.h:58
#define PCMK_ACTION_MONITOR
Definition actions.h:59
#define PCMK_ACTION_RELOAD_AGENT
Definition actions.h:69
#define PCMK_ACTION_DEMOTE
Definition actions.h:49
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:42
const char * name
Definition cib.c:26
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:99
const char * role2text(enum rsc_role_e role)
Definition common.c:458
enum rsc_role_e text2role(const char *role)
Definition common.c:487
uint32_t id
Definition cpg.c:0
const char * pcmk__readable_interval(guint interval_ms)
Definition iso8601.c:1926
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:382
#define do_crm_log(level, fmt, args...)
Log a message.
Definition logging.h:175
#define crm_notice(fmt, args...)
Definition logging.h:381
#define CRM_CHECK(expr, failure_action)
Definition logging.h:238
#define crm_debug(fmt, args...)
Definition logging.h:384
#define LOG_TRACE
Definition logging.h:38
#define pcmk__config_err(fmt...)
#define ID(x)
Definition msg_xml.h:474
#define XML_LRM_ATTR_INTERVAL
Definition msg_xml.h:300
#define XML_LRM_ATTR_TASK
Definition msg_xml.h:306
#define XML_LRM_ATTR_CALLID
Definition msg_xml.h:318
#define XML_LRM_ATTR_INTERVAL_MS
Definition msg_xml.h:304
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:447
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:394
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:383
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
Definition utils.c:450
#define start_action(rsc, node, optional)
Definition internal.h:385
#define start_key(rsc)
Definition internal.h:384
#define stop_key(rsc)
Definition internal.h:378
#define pe_rsc_debug(rsc, fmt, args...)
Definition internal.h:36
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:37
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:389
#define pe_rsc_info(rsc, fmt, args...)
Definition internal.h:35
#define pe__clear_action_flags(action, flags_to_clear)
Definition internal.h:85
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:581
xmlNode * pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, guint interval_ms, bool include_disabled)
Definition pe_actions.c:129
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
#define pe__set_action_flags(action, flags_to_set)
Definition internal.h:76
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition common.c:508
@ pcmk_rsc_unique
Whether resource is not an anonymous clone instance.
Definition resources.h:118
@ pcmk_rsc_maintenance
Whether resource, its node, or entire cluster is in maintenance mode.
Definition resources.h:181
@ pcmk_rsc_blocked
Whether resource is blocked from further action.
Definition resources.h:109
@ pcmk_rsc_managed
Whether resource is managed.
Definition resources.h:106
#define CRM_ASSERT(expr)
Definition results.h:42
@ CRM_EX_NOT_RUNNING
Service safely stopped.
Definition results.h:249
@ CRM_EX_PROMOTED
Service active and promoted.
Definition results.h:250
@ pcmk_rc_ok
Definition results.h:154
rsc_role_e
Definition roles.h:27
@ pcmk_role_started
Started.
Definition roles.h:30
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:28
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:31
@ pcmk_role_promoted
Promoted.
Definition roles.h:32
@ pcmk_role_stopped
Stopped.
Definition roles.h:29
#define PCMK__ROLE_STOPPED
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
Implementation of pcmk_action_t.
Definition actions.h:390
char * uuid
Action key.
Definition actions.h:404
char * task
Action name.
Definition actions.h:403
GHashTable * meta
Meta-attributes relevant to action.
Definition actions.h:414
char * cancel_task
If task is "cancel", the action being cancelled.
Definition actions.h:405
enum pe_action_flags flags
Group of enum pe_action_flags.
Definition actions.h:409
Implementation of pcmk_node_t.
Definition nodes.h:130
struct pe_node_shared_s * details
Basic node information.
Definition nodes.h:134
gboolean online
Whether online.
Definition nodes.h:72
const char * uname
Node name in cluster.
Definition nodes.h:68
gboolean unclean
Whether node requires fencing.
Definition nodes.h:76
gboolean maintenance
Whether in maintenance mode.
Definition nodes.h:81
Implementation of pcmk_resource_t.
Definition resources.h:399
pcmk_assignment_methods_t * cmds
Resource assignment methods.
Definition resources.h:417
GList * actions
Definition resources.h:447
pcmk_scheduler_t * cluster
Cluster that resource is part of.
Definition resources.h:412
char * id
Resource ID in configuration.
Definition resources.h:400
pcmk_node_t * allocated_to
Node resource is assigned to.
Definition resources.h:451
unsigned long long flags
Group of enum pcmk_rsc_flags.
Definition resources.h:429
enum rsc_role_e next_role
Resource's scheduled next role.
Definition resources.h:469
enum rsc_role_e role
Resource's current role.
Definition resources.h:468
xmlNode * ops_xml
Configuration of resource operations (possibly expanded from template)
Definition resources.h:410
GList * nodes
Nodes in cluster.
Definition scheduler.h:195
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2484
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2510