pacemaker  2.1.5-b7adf64e51
Scalable High-Availability cluster resource manager
pcmk_sched_recurring.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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 
17 #include "libpacemaker_private.h"
18 
19 // Information parsed from an operation history entry in the CIB
20 struct 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 
39 static guint
40 xe_interval(const xmlNode *xml)
41 {
44 }
45 
57 static bool
58 is_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 
104 static bool
105 op_cannot_recur(const char *name)
106 {
109  CRMD_ACTION_MIGRATED, NULL);
110 }
111 
122 static bool
123 is_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 
186 static bool
187 active_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 (GList *iter = possible_matches; iter != NULL; iter = iter->next) {
214  pe_action_t *op = (pe_action_t *) iter->data;
215 
217  pe_rsc_trace(rsc,
218  "%s will be mandatory because "
219  "it needs to be rescheduled", key);
220  g_list_free(possible_matches);
221  return false;
222  }
223  }
224 
225  g_list_free(possible_matches);
226  return true;
227 }
228 
238 static void
239 recurring_op_for_active(pe_resource_t *rsc, pe_action_t *start,
240  const pe_node_t *node, const struct op_history *op)
241 {
242  pe_action_t *mon = NULL;
243  bool is_optional = true;
244 
245  // We're only interested in recurring actions for active roles
246  if (op->role == RSC_ROLE_STOPPED) {
247  return;
248  }
249 
250  is_optional = active_recurring_should_be_optional(rsc, node, op->key,
251  start);
252 
253  if (((op->role != RSC_ROLE_UNKNOWN) && (rsc->next_role != op->role))
254  || ((op->role == RSC_ROLE_UNKNOWN)
255  && (rsc->next_role == RSC_ROLE_PROMOTED))) {
256  // Configured monitor role doesn't match role resource will have
257 
258  if (is_optional) { // It's running, so cancel it
259  char *after_key = NULL;
260  pe_action_t *cancel_op = pcmk__new_cancel_action(rsc, op->name,
261  op->interval_ms,
262  node);
263 
264  switch (rsc->role) {
265  case RSC_ROLE_UNPROMOTED:
266  case RSC_ROLE_STARTED:
267  if (rsc->next_role == RSC_ROLE_PROMOTED) {
268  after_key = promote_key(rsc);
269 
270  } else if (rsc->next_role == RSC_ROLE_STOPPED) {
271  after_key = stop_key(rsc);
272  }
273 
274  break;
275  case RSC_ROLE_PROMOTED:
276  after_key = demote_key(rsc);
277  break;
278  default:
279  break;
280  }
281 
282  if (after_key) {
283  pcmk__new_ordering(rsc, NULL, cancel_op, rsc, after_key, NULL,
285  }
286  }
287 
288  do_crm_log((is_optional? LOG_INFO : LOG_TRACE),
289  "%s recurring action %s because %s configured for %s role "
290  "(not %s)",
291  (is_optional? "Cancelling" : "Ignoring"), op->key, op->id,
292  role2text((op->role == RSC_ROLE_UNKNOWN)? RSC_ROLE_UNPROMOTED : op->role),
293  role2text(rsc->next_role));
294  return;
295  }
296 
297  pe_rsc_trace(rsc,
298  "Creating %s recurring action %s for %s (%s %s on %s)",
299  (is_optional? "optional" : "mandatory"), op->key,
300  op->id, rsc->id, role2text(rsc->next_role),
301  pe__node_name(node));
302 
303  mon = custom_action(rsc, strdup(op->key), op->name, node, is_optional, TRUE,
304  rsc->cluster);
305 
306  if (!pcmk_is_set(start->flags, pe_action_runnable)) {
307  pe_rsc_trace(rsc, "%s is unrunnable because start is", mon->uuid);
309 
310  } else if ((node == NULL) || !node->details->online
311  || node->details->unclean) {
312  pe_rsc_trace(rsc, "%s is unrunnable because no node is available",
313  mon->uuid);
315 
316  } else if (!pcmk_is_set(mon->flags, pe_action_optional)) {
317  pe_rsc_info(rsc, "Start %s-interval %s for %s on %s",
318  pcmk__readable_interval(op->interval_ms), mon->task,
319  rsc->id, pe__node_name(node));
320  }
321 
322  if (rsc->next_role == RSC_ROLE_PROMOTED) {
324  }
325 
326  // Order monitor relative to other actions
327  if ((node == NULL) || pcmk_is_set(rsc->flags, pe_rsc_managed)) {
328  pcmk__new_ordering(rsc, start_key(rsc), NULL,
329  NULL, strdup(mon->uuid), mon,
331  rsc->cluster);
332 
333  pcmk__new_ordering(rsc, reload_key(rsc), NULL,
334  NULL, strdup(mon->uuid), mon,
336  rsc->cluster);
337 
338  if (rsc->next_role == RSC_ROLE_PROMOTED) {
339  pcmk__new_ordering(rsc, promote_key(rsc), NULL,
340  rsc, NULL, mon,
342  rsc->cluster);
343 
344  } else if (rsc->role == RSC_ROLE_PROMOTED) {
345  pcmk__new_ordering(rsc, demote_key(rsc), NULL,
346  rsc, NULL, mon,
348  rsc->cluster);
349  }
350  }
351 }
352 
363 static void
364 cancel_if_running(pe_resource_t *rsc, const pe_node_t *node, const char *key,
365  const char *name, guint interval_ms)
366 {
367  GList *possible_matches = find_actions_exact(rsc->actions, key, node);
368  pe_action_t *cancel_op = NULL;
369 
370  if (possible_matches == NULL) {
371  return; // Recurring action isn't running on this node
372  }
373  g_list_free(possible_matches);
374 
375  cancel_op = pcmk__new_cancel_action(rsc, name, interval_ms, node);
376 
377  switch (rsc->next_role) {
378  case RSC_ROLE_STARTED:
379  case RSC_ROLE_UNPROMOTED:
380  /* Order starts after cancel. If the current role is
381  * stopped, this cancels the monitor before the resource
382  * starts; if the current role is started, then this cancels
383  * the monitor on a migration target before starting there.
384  */
385  pcmk__new_ordering(rsc, NULL, cancel_op,
386  rsc, start_key(rsc), NULL,
388  break;
389  default:
390  break;
391  }
392  pe_rsc_info(rsc,
393  "Cancelling %s-interval %s action for %s on %s because "
394  "configured for " RSC_ROLE_STOPPED_S " role (not %s)",
395  pcmk__readable_interval(interval_ms), name, rsc->id,
396  pe__node_name(node), role2text(rsc->next_role));
397 }
398 
407 static void
408 order_after_probes(pe_resource_t *rsc, const pe_node_t *node,
410 {
411  GList *probes = pe__resource_actions(rsc, node, RSC_STATUS, FALSE);
412 
413  for (GList *iter = probes; iter != NULL; iter = iter->next) {
414  order_actions((pe_action_t *) iter->data, action,
416  }
417  g_list_free(probes);
418 }
419 
428 static void
429 order_after_stops(pe_resource_t *rsc, const pe_node_t *node,
431 {
432  GList *stop_ops = pe__resource_actions(rsc, node, RSC_STOP, TRUE);
433 
434  for (GList *iter = stop_ops; iter != NULL; iter = iter->next) {
435  pe_action_t *stop = (pe_action_t *) iter->data;
436 
439  && !pcmk_is_set(rsc->flags, pe_rsc_managed)) {
440  pe_rsc_trace(rsc, "%s optional on %s: unmanaged",
441  action->uuid, pe__node_name(node));
443  }
444 
445  if (!pcmk_is_set(stop->flags, pe_action_runnable)) {
446  crm_debug("%s unrunnable on %s: stop is unrunnable",
447  action->uuid, pe__node_name(node));
449  }
450 
451  if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
452  pcmk__new_ordering(rsc, stop_key(rsc), stop,
453  NULL, NULL, action,
455  rsc->cluster);
456  }
457  }
458  g_list_free(stop_ops);
459 }
460 
469 static void
470 recurring_op_for_inactive(pe_resource_t *rsc, const pe_node_t *node,
471  const struct op_history *op)
472 {
473  GList *possible_matches = NULL;
474 
475  // We're only interested in recurring actions for the inactive role
476  if (op->role != RSC_ROLE_STOPPED) {
477  return;
478  }
479 
480  if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
481  crm_notice("Ignoring %s (recurring monitors for " RSC_ROLE_STOPPED_S
482  " role are not supported for anonymous clones)", op->id);
483  return; // @TODO add support
484  }
485 
486  pe_rsc_trace(rsc, "Creating recurring action %s for %s on nodes "
487  "where it should not be running", op->id, rsc->id);
488 
489  for (GList *iter = rsc->cluster->nodes; iter != NULL; iter = iter->next) {
490  pe_node_t *stop_node = (pe_node_t *) iter->data;
491 
492  bool is_optional = true;
493  pe_action_t *stopped_mon = NULL;
494 
495  // Cancel action on node where resource will be active
496  if ((node != NULL)
497  && pcmk__str_eq(stop_node->details->uname, node->details->uname,
498  pcmk__str_casei)) {
499  cancel_if_running(rsc, node, op->key, op->name, op->interval_ms);
500  continue;
501  }
502 
503  // Recurring action on this node is optional if it's already active here
504  possible_matches = find_actions_exact(rsc->actions, op->key, stop_node);
505  is_optional = (possible_matches != NULL);
506  g_list_free(possible_matches);
507 
508  pe_rsc_trace(rsc,
509  "Creating %s recurring action %s for %s (%s "
510  RSC_ROLE_STOPPED_S " on %s)",
511  (is_optional? "optional" : "mandatory"),
512  op->key, op->id, rsc->id, pe__node_name(stop_node));
513 
514  stopped_mon = custom_action(rsc, strdup(op->key), op->name, stop_node,
515  is_optional, TRUE, rsc->cluster);
516 
518 
519  if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
520  order_after_probes(rsc, stop_node, stopped_mon);
521  }
522 
523  /* The recurring action is for the inactive role, so it shouldn't be
524  * performed until the resource is inactive.
525  */
526  order_after_stops(rsc, stop_node, stopped_mon);
527 
528  if (!stop_node->details->online || stop_node->details->unclean) {
529  pe_rsc_debug(rsc, "%s unrunnable on %s: node unavailable)",
530  stopped_mon->uuid, pe__node_name(stop_node));
532  }
533 
534  if (pcmk_is_set(stopped_mon->flags, pe_action_runnable)
535  && !pcmk_is_set(stopped_mon->flags, pe_action_optional)) {
536  crm_notice("Start recurring %s-interval %s for "
537  RSC_ROLE_STOPPED_S " %s on %s",
538  pcmk__readable_interval(op->interval_ms),
539  stopped_mon->task, rsc->id, pe__node_name(stop_node));
540  }
541  }
542 }
543 
550 void
552 {
553  pe_action_t *start = NULL;
554 
555  if (pcmk_is_set(rsc->flags, pe_rsc_block)) {
556  pe_rsc_trace(rsc, "Skipping recurring actions for blocked resource %s",
557  rsc->id);
558  return;
559  }
560 
561  if (pcmk_is_set(rsc->flags, pe_rsc_maintenance)) {
562  pe_rsc_trace(rsc, "Skipping recurring actions for %s "
563  "in maintenance mode", rsc->id);
564  return;
565  }
566 
567  if (rsc->allocated_to == NULL) {
568  // Recurring actions for active roles not needed
569 
570  } else if (rsc->allocated_to->details->maintenance) {
571  pe_rsc_trace(rsc,
572  "Skipping recurring actions for %s on %s "
573  "in maintenance mode",
574  rsc->id, pe__node_name(rsc->allocated_to));
575 
576  } else if ((rsc->next_role != RSC_ROLE_STOPPED)
577  || !pcmk_is_set(rsc->flags, pe_rsc_managed)) {
578  // Recurring actions for active roles needed
579  start = start_action(rsc, rsc->allocated_to, TRUE);
580  }
581 
582  pe_rsc_trace(rsc, "Creating any recurring actions needed for %s", rsc->id);
583 
584  for (xmlNode *op = first_named_child(rsc->ops_xml, "op");
585  op != NULL; op = crm_next_same_xml(op)) {
586 
587  struct op_history op_history = { NULL, };
588 
589  if (!is_recurring_history(rsc, op, &op_history)) {
590  continue;
591  }
592 
593  if (start != NULL) {
594  recurring_op_for_active(rsc, start, rsc->allocated_to, &op_history);
595  }
596  recurring_op_for_inactive(rsc, rsc->allocated_to, &op_history);
597 
598  free(op_history.key);
599  }
600 }
601 
613 pe_action_t *
614 pcmk__new_cancel_action(pe_resource_t *rsc, const char *task, guint interval_ms,
615  const pe_node_t *node)
616 {
617  pe_action_t *cancel_op = NULL;
618  char *key = NULL;
619  char *interval_ms_s = NULL;
620 
621  CRM_ASSERT((rsc != NULL) && (task != NULL) && (node != NULL));
622 
623  // @TODO dangerous if possible to schedule another action with this key
624  key = pcmk__op_key(rsc->id, task, interval_ms);
625 
626  cancel_op = custom_action(rsc, key, RSC_CANCEL, node, FALSE, TRUE,
627  rsc->cluster);
628 
629  pcmk__str_update(&cancel_op->task, RSC_CANCEL);
630  pcmk__str_update(&cancel_op->cancel_task, task);
631 
632  interval_ms_s = crm_strdup_printf("%u", interval_ms);
633  add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, task);
634  add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL_MS, interval_ms_s);
635  free(interval_ms_s);
636 
637  return cancel_op;
638 }
639 
651 void
652 pcmk__schedule_cancel(pe_resource_t *rsc, const char *call_id, const char *task,
653  guint interval_ms, const pe_node_t *node,
654  const char *reason)
655 {
656  pe_action_t *cancel = NULL;
657 
658  CRM_CHECK((rsc != NULL) && (task != NULL)
659  && (node != NULL) && (reason != NULL),
660  return);
661 
662  crm_info("Recurring %s-interval %s for %s will be stopped on %s: %s",
663  pcmk__readable_interval(interval_ms), task, rsc->id,
664  pe__node_name(node), reason);
665  cancel = pcmk__new_cancel_action(rsc, task, interval_ms, node);
666  add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
667 
668  // Cancellations happen after stops
669  pcmk__new_ordering(rsc, stop_key(rsc), NULL, rsc, NULL, cancel,
670  pe_order_optional, rsc->cluster);
671 }
672 
682 void
684  guint interval_ms, pe_node_t *node)
685 {
686  pe_action_t *op = NULL;
687 
688  trigger_unfencing(rsc, node, "Device parameters changed (reschedule)",
689  NULL, rsc->cluster);
690  op = custom_action(rsc, pcmk__op_key(rsc->id, task, interval_ms),
691  task, node, TRUE, TRUE, rsc->cluster);
693 }
694 
703 bool
705 {
706  guint interval_ms = 0;
707 
708  if (pcmk__guint_from_hash(action->meta,
710  &interval_ms) != pcmk_rc_ok) {
711  return false;
712  }
713  return (interval_ms > 0);
714 }
#define LOG_TRACE
Definition: logging.h:37
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
xmlNode * find_rsc_op_entry(const pe_resource_t *rsc, const char *key)
Definition: pe_actions.c:145
#define RSC_STOP
Definition: crm.h:202
pe_action_t * pcmk__new_cancel_action(pe_resource_t *rsc, const char *task, guint interval_ms, const pe_node_t *node)
#define crm_notice(fmt, args...)
Definition: logging.h:361
#define CRMD_ACTION_MIGRATED
Definition: crm.h:172
xmlNode * ops_xml
Definition: pe_types.h:333
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:46
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:86
const char * name
Definition: cib.c:24
enum rsc_role_e role
Definition: pe_types.h:377
resource_alloc_functions_t * cmds
Definition: pe_types.h:341
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2930
Service active and promoted.
Definition: results.h:244
enum rsc_role_e next_role
Definition: pe_types.h:378
#define reload_key(rsc)
Definition: internal.h:419
#define pcmk__config_err(fmt...)
char * cancel_task
Definition: pe_types.h:412
#define pe_rsc_unique
Definition: pe_types.h:262
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:294
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)
#define demote_key(rsc)
Definition: internal.h:440
#define RSC_START
Definition: crm.h:199
pe_node_t * allocated_to
Definition: pe_types.h:370
const char * action
Definition: pcmk_fence.c:30
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
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:604
GList * nodes
Definition: pe_types.h:164
void pcmk__reschedule_recurring(pe_resource_t *rsc, const char *task, guint interval_ms, pe_node_t *node)
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:300
const char * role2text(enum rsc_role_e role)
Definition: common.c:454
#define CRMD_ACTION_RELOAD_AGENT
Definition: crm.h:170
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition: strings.c:311
#define crm_debug(fmt, args...)
Definition: logging.h:364
bool pcmk__action_is_recurring(const pe_action_t *action)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:517
#define stop_key(rsc)
Definition: internal.h:414
void pe__add_action_expected_result(pe_action_t *action, int expected_result)
Definition: pe_actions.c:1673
char * task
Definition: pe_types.h:410
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:95
#define crm_trace(fmt, args...)
Definition: logging.h:365
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:168
#define promote_key(rsc)
Definition: internal.h:430
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * meta
Definition: pe_types.h:420
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
struct pe_node_shared_s * details
Definition: pe_types.h:252
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:474
unsigned long long flags
Definition: pe_types.h:355
const char * uname
Definition: pe_types.h:216
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1190
GList * actions
Definition: pe_types.h:366
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)
char * uuid
Definition: pe_types.h:411
enum rsc_role_e text2role(const char *role)
Definition: common.c:483
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:952
uint32_t id
Definition: cpg.c:45
Service safely stopped.
Definition: results.h:243
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:45
void pcmk__create_recurring_actions(pe_resource_t *rsc)
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:504
#define start_action(rsc, node, optional)
Definition: internal.h:421
#define CRM_ASSERT(expr)
Definition: results.h:42
#define RSC_STATUS
Definition: crm.h:213
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:271
#define RSC_PROMOTE
Definition: crm.h:205
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:298
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:312
#define CRMD_ACTION_MIGRATE
Definition: crm.h:171
#define RSC_ROLE_STOPPED_S
Definition: common.h:111
rsc_role_e
Possible roles that a resource can be in.
Definition: common.h:92
#define pe_rsc_block
Definition: pe_types.h:258
enum pe_action_flags flags
Definition: pe_types.h:415
gboolean maintenance
Definition: pe_types.h:229
#define pe_rsc_maintenance
Definition: pe_types.h:290
pe_working_set_t * cluster
Definition: pe_types.h:335
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:1765
GList * find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
Definition: pe_actions.c:1359
#define RSC_CANCEL
Definition: crm.h:194
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:47
#define start_key(rsc)
Definition: internal.h:420
#define ID(x)
Definition: msg_xml.h:468
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.
Definition: pe_actions.c:1398
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:940
gboolean unclean
Definition: pe_types.h:224
#define crm_info(fmt, args...)
Definition: logging.h:362
#define pe_rsc_managed
Definition: pe_types.h:257
gboolean online
Definition: pe_types.h:220
#define RSC_DEMOTE
Definition: crm.h:207
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:45
char * id
Definition: pe_types.h:329
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2956