pacemaker  2.1.8-3980678f03
Scalable High-Availability cluster resource manager
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 
18 #include "libpacemaker_private.h"
19 
20 // Information parsed from an operation history entry in the CIB
21 struct 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 
40 static guint
41 xe_interval(const xmlNode *xml)
42 {
43  guint interval_ms = 0U;
44 
46  &interval_ms);
47  return interval_ms;
48 }
49 
61 static bool
62 is_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 
109 static bool
110 op_cannot_recur(const char *name)
111 {
116  NULL);
117 }
118 
129 static bool
130 is_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 
197 static bool
198 active_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 
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 
253 static void
254 recurring_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) {
287  case pcmk_role_started:
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;
296  case pcmk_role_promoted:
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 
389 static void
390 cancel_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) {
404  case pcmk_role_started:
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 
433 static void
434 order_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 
454 static void
455 order_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 
465  && !pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
477  if (pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
496 static void
497 recurring_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,
526  pcmk__str_casei)) {
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 
547  if (pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
578 void
580 {
581  pcmk_action_t *start = NULL;
582 
583  if (pcmk_is_set(rsc->flags, pcmk_rsc_blocked)) {
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)
607  || !pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
663  pcmk__str_update(&(cancel_op->task), PCMK_ACTION_CANCEL);
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 
685 void
686 pcmk__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,
704  pcmk__ar_ordered, rsc->cluster);
705 }
706 
716 void
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 
737 bool
739 {
740  guint interval_ms = 0;
741 
743  &interval_ms) != pcmk_rc_ok) {
744  return false;
745  }
746  return (interval_ms > 0);
747 }
pcmk_assignment_methods_t * cmds
Definition: resources.h:413
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
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
#define crm_notice(fmt, args...)
Definition: logging.h:397
&#39;then&#39; is runnable (and migratable) only if &#39;first&#39; is runnable
pcmk_scheduler_t * cluster
Definition: resources.h:408
xmlNode * ops_xml
Definition: resources.h:406
#define PCMK_XA_NAME
Definition: xml_names.h:325
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition: roles.c:23
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)
Stopped.
Definition: roles.h:36
const char * name
Definition: cib.c:26
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
enum rsc_role_e role
Definition: resources.h:464
#define pcmk__rsc_trace(rsc, fmt, args...)
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
Definition: utils.c:457
#define pcmk__rsc_info(rsc, fmt, args...)
Service active and promoted.
Definition: results.h:265
enum rsc_role_e next_role
Definition: resources.h:465
#define reload_key(rsc)
Definition: internal.h:218
#define pcmk__insert_meta(obj, name, value)
#define pcmk__config_err(fmt...)
char * cancel_task
Definition: actions.h:345
#define PCMK_ACTION_MONITOR
Definition: actions.h:60
#define PCMK_ACTION_MIGRATE_TO
Definition: actions.h:59
Promoted.
Definition: roles.h:39
#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.
Definition: pe_actions.c:1551
#define PCMK_XA_OPERATION
Definition: xml_names.h:344
const char * action
Definition: pcmk_fence.c:30
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition: roles.c:59
#define pcmk__rsc_debug(rsc, fmt, args...)
char int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
Definition: strings.c:451
#define PCMK_ACTION_RELOAD_AGENT
Definition: actions.h:70
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
Definition: pe_actions.c:1512
#define PCMK_ACTION_DEMOTE
Definition: actions.h:49
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition: strings.c:311
bool pcmk__action_is_recurring(const pcmk_action_t *action)
#define crm_debug(fmt, args...)
Definition: logging.h:402
Actions are ordered (optionally, if no other flags are set)
#define pcmk__clear_action_flags(action, flags_to_clear)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:440
#define stop_key(rsc)
Definition: internal.h:213
char * task
Definition: actions.h:343
#define PCMK_ROLE_STOPPED
Definition: roles.h:25
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:181
#define promote_key(rsc)
Definition: internal.h:224
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
struct pe_node_shared_s * details
Definition: nodes.h:167
#define PCMK_ACTION_START
Definition: actions.h:72
unsigned long long flags
Definition: resources.h:428
const char * uname
Definition: nodes.h:73
Unpromoted.
Definition: roles.h:38
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1277
Wrappers for and extensions to libxml2.
rsc_role_e
Definition: roles.h:34
#define PCMK_ACTION_STOP
Definition: actions.h:75
GList * actions
Definition: resources.h:444
void pcmk__create_recurring_actions(pcmk_resource_t *rsc)
char * uuid
Definition: actions.h:344
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
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1050
uint32_t id
Definition: cpg.c:48
Service safely stopped.
Definition: results.h:264
#define PCMK_ACTION_CANCEL
Definition: actions.h:45
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.
Definition: pe_actions.c:1129
void pe__add_action_expected_result(pcmk_action_t *action, int expected_result)
Definition: pe_actions.c:1828
#define PCMK_XE_OP
Definition: xml_names.h:143
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
#define PCMK_META_INTERVAL
Definition: options.h:91
#define start_action(rsc, node, optional)
Definition: internal.h:220
#define CRM_ASSERT(expr)
Definition: results.h:42
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)
#define PCMK_ACTION_MIGRATE_FROM
Definition: actions.h:58
Started.
Definition: roles.h:37
pcmk_node_t * allocated_to
Definition: resources.h:447
#define PCMK_ACTION_PROMOTE
Definition: actions.h:66
enum pe_action_flags flags
Definition: actions.h:349
gboolean maintenance
Definition: nodes.h:104
#define PCMK__XA_CALL_ID
#define pcmk__set_action_flags(action, flags_to_set)
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:2134
void pcmk__reschedule_recurring(pcmk_resource_t *rsc, const char *task, guint interval_ms, pcmk_node_t *node)
Resource role is unknown.
Definition: roles.h:35
#define start_key(rsc)
Definition: internal.h:219
pcmk_action_t * pcmk__new_cancel_action(pcmk_resource_t *rsc, const char *task, guint interval_ms, const pcmk_node_t *node)
gboolean unclean
Definition: nodes.h:91
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2108
#define PCMK_XA_ROLE
Definition: xml_names.h:382
#define crm_info(fmt, args...)
Definition: logging.h:399
gboolean online
Definition: nodes.h:80