pacemaker  2.1.7-0f7f88312f
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>
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 {
45 }
46 
58 static bool
59 is_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 
104 static bool
105 op_cannot_recur(const char *name)
106 {
111  NULL);
112 }
113 
124 static bool
125 is_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 
192 static bool
193 active_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 
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 
246 static void
247 recurring_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) {
274  case pcmk_role_started:
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;
283  case pcmk_role_promoted:
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 
376 static void
377 cancel_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) {
391  case pcmk_role_started:
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 
420 static void
421 order_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 
441 static void
442 order_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 
452  && !pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
464  if (pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
483 static void
484 recurring_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,
512  pcmk__str_casei)) {
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 
533  if (pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
564 void
566 {
567  pcmk_action_t *start = NULL;
568 
569  if (pcmk_is_set(rsc->flags, pcmk_rsc_blocked)) {
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)
591  || !pcmk_is_set(rsc->flags, pcmk_rsc_managed)) {
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 
665 void
666 pcmk__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,
684  pcmk__ar_ordered, rsc->cluster);
685 }
686 
696 void
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 
717 bool
719 {
720  guint interval_ms = 0;
721 
722  if (pcmk__guint_from_hash(action->meta,
724  &interval_ms) != pcmk_rc_ok) {
725  return false;
726  }
727  return (interval_ms > 0);
728 }
pcmk_assignment_methods_t * cmds
Resource assignment methods.
Definition: resources.h:417
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
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
#define crm_notice(fmt, args...)
Definition: logging.h:383
&#39;then&#39; is runnable (and migratable) only if &#39;first&#39; is runnable
pcmk_scheduler_t * cluster
Cluster that resource is part of.
Definition: resources.h:412
xmlNode * ops_xml
Configuration of resource operations (possibly expanded from template)
Definition: resources.h:410
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:36
Whether action should not be executed.
Definition: actions.h:244
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:76
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:29
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
Resource&#39;s current role.
Definition: resources.h:468
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
Definition: utils.c:450
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2484
Service active and promoted.
Definition: results.h:250
enum rsc_role_e next_role
Resource&#39;s scheduled next role.
Definition: resources.h:469
#define reload_key(rsc)
Definition: internal.h:383
Implementation of pcmk_action_t.
Definition: actions.h:390
#define pcmk__config_err(fmt...)
char * cancel_task
If task is "cancel", the action being cancelled.
Definition: actions.h:405
#define PCMK_ACTION_MONITOR
Definition: actions.h:59
Whether resource, its node, or entire cluster is in maintenance mode.
Definition: resources.h:181
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:300
#define PCMK_ACTION_MIGRATE_TO
Definition: actions.h:58
Promoted.
Definition: roles.h:32
#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.
Definition: pe_actions.c:1588
const char * action
Definition: pcmk_fence.c:30
GList * nodes
Nodes in cluster.
Definition: scheduler.h:195
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:306
#define PCMK_ACTION_RELOAD_AGENT
Definition: actions.h:69
const char * role2text(enum rsc_role_e role)
Definition: common.c:458
GList * find_actions_exact(GList *input, const char *key, const pcmk_node_t *on_node)
Definition: pe_actions.c:1549
#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)
Implementation of pcmk_resource_t.
Definition: resources.h:399
#define crm_debug(fmt, args...)
Definition: logging.h:386
Actions are ordered (optionally, if no other flags are set)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
#define stop_key(rsc)
Definition: internal.h:378
char * task
Action name.
Definition: actions.h:403
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:85
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:175
#define PCMK__ROLE_STOPPED
#define promote_key(rsc)
Definition: internal.h:389
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
GHashTable * meta
Meta-attributes relevant to action.
Definition: actions.h:414
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:99
struct pe_node_shared_s * details
Basic node information.
Definition: nodes.h:134
#define PCMK_ACTION_START
Definition: actions.h:71
unsigned long long flags
Group of enum pcmk_rsc_flags.
Definition: resources.h:429
const char * uname
Node name in cluster.
Definition: nodes.h:68
Unpromoted.
Definition: roles.h:31
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
rsc_role_e
Definition: roles.h:27
#define PCMK_ACTION_STOP
Definition: actions.h:74
GList * actions
Definition: resources.h:447
void pcmk__create_recurring_actions(pcmk_resource_t *rsc)
char * uuid
Action key.
Definition: actions.h:404
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
Whether resource is blocked from further action.
Definition: resources.h:109
Implementation of pcmk_node_t.
Definition: nodes.h:130
enum rsc_role_e text2role(const char *role)
Definition: common.c:487
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:249
#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:1117
void pe__add_action_expected_result(pcmk_action_t *action, int expected_result)
Definition: pe_actions.c:1861
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
Whether action is runnable.
Definition: actions.h:241
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:508
#define start_action(rsc, node, optional)
Definition: internal.h:385
#define CRM_ASSERT(expr)
Definition: results.h:42
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:271
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:57
Started.
Definition: roles.h:30
#define XML_LRM_ATTR_INTERVAL_MS
Definition: msg_xml.h:304
pcmk_node_t * allocated_to
Node resource is assigned to.
Definition: resources.h:451
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:318
#define PCMK_ACTION_PROMOTE
Definition: actions.h:65
enum pe_action_flags flags
Group of enum pe_action_flags.
Definition: actions.h:409
gboolean maintenance
Whether in maintenance mode.
Definition: nodes.h:81
const char * pcmk__readable_interval(guint interval_ms)
Definition: iso8601.c:1926
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:28
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:37
#define start_key(rsc)
Definition: internal.h:384
pcmk_action_t * pcmk__new_cancel_action(pcmk_resource_t *rsc, const char *task, guint interval_ms, const pcmk_node_t *node)
Whether action is recurring monitor that must be rescheduled if active.
Definition: actions.h:269
#define ID(x)
Definition: msg_xml.h:474
Whether resource is managed.
Definition: resources.h:106
gboolean unclean
Whether node requires fencing.
Definition: nodes.h:76
#define crm_info(fmt, args...)
Definition: logging.h:384
gboolean online
Whether online.
Definition: nodes.h:72
Whether resource is not an anonymous clone instance.
Definition: resources.h:118
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:35
char * id
Resource ID in configuration.
Definition: resources.h:400
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2510