pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
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 
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 (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 
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 
240 static void
241 recurring_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) {
267  case RSC_ROLE_UNPROMOTED:
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;
277  case RSC_ROLE_PROMOTED:
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 
365 static void
366 cancel_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:
381  case RSC_ROLE_UNPROMOTED:
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 
409 static void
410 order_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 
430 static void
431 order_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 
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 
471 static void
472 recurring_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,
500  pcmk__str_casei)) {
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 
552 void
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 
563  if (pcmk_is_set(rsc->flags, pe_rsc_maintenance)) {
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 
615 pe_action_t *
616 pcmk__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 
653 void
654 pcmk__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,
672  pe_order_optional, rsc->cluster);
673 }
674 
684 void
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 
705 bool
707 {
708  guint interval_ms = 0;
709 
710  if (pcmk__guint_from_hash(action->meta,
712  &interval_ms) != pcmk_rc_ok) {
713  return false;
714  }
715  return (interval_ms > 0);
716 }
#define LOG_TRACE
Definition: logging.h:37
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:235
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:379
#define CRMD_ACTION_MIGRATED
Definition: crm.h:172
xmlNode * ops_xml
Definition: pe_types.h:351
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:49
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:89
const char * name
Definition: cib.c:24
enum rsc_role_e role
Definition: pe_types.h:402
resource_alloc_functions_t * cmds
Definition: pe_types.h:359
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2521
Service active and promoted.
Definition: results.h:247
enum rsc_role_e next_role
Definition: pe_types.h:403
#define reload_key(rsc)
Definition: internal.h:410
#define pcmk__config_err(fmt...)
char * cancel_task
Definition: pe_types.h:439
#define pe_rsc_unique
Definition: pe_types.h:278
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:309
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:431
#define RSC_START
Definition: crm.h:199
pe_node_t * allocated_to
Definition: pe_types.h:395
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:616
GList * nodes
Definition: pe_types.h:180
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:315
const char * role2text(enum rsc_role_e role)
Definition: common.c:450
#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:382
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:496
#define stop_key(rsc)
Definition: internal.h:405
void pe__add_action_expected_result(pe_action_t *action, int expected_result)
Definition: pe_actions.c:1676
char * task
Definition: pe_types.h:437
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:98
#define crm_trace(fmt, args...)
Definition: logging.h:383
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:172
#define promote_key(rsc)
Definition: internal.h:421
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * meta
Definition: pe_types.h:447
#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:268
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:488
unsigned long long flags
Definition: pe_types.h:373
const char * uname
Definition: pe_types.h:232
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
GList * actions
Definition: pe_types.h:391
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:438
enum rsc_role_e text2role(const char *role)
Definition: common.c:479
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:957
uint32_t id
Definition: cpg.c:45
Service safely stopped.
Definition: results.h:246
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
void pcmk__create_recurring_actions(pe_resource_t *rsc)
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:500
#define start_action(rsc, node, optional)
Definition: internal.h:412
#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:313
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:327
#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:274
enum pe_action_flags flags
Definition: pe_types.h:442
gboolean maintenance
Definition: pe_types.h:245
#define pe_rsc_maintenance
Definition: pe_types.h:308
pe_working_set_t * cluster
Definition: pe_types.h:353
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:1926
GList * find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
Definition: pe_actions.c:1361
#define RSC_CANCEL
Definition: crm.h:194
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:50
#define start_key(rsc)
Definition: internal.h:411
#define ID(x)
Definition: msg_xml.h:480
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:1400
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
gboolean unclean
Definition: pe_types.h:240
#define crm_info(fmt, args...)
Definition: logging.h:380
#define pe_rsc_managed
Definition: pe_types.h:273
gboolean online
Definition: pe_types.h:236
#define RSC_DEMOTE
Definition: crm.h:207
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:48
char * id
Definition: pe_types.h:347
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2547