pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
operations.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #ifndef _GNU_SOURCE
11 # define _GNU_SOURCE
12 #endif
13 
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 
19 #include <crm/crm.h>
20 #include <crm/lrmd.h>
21 #include <crm/msg_xml.h>
22 #include <crm/common/xml.h>
23 #include <crm/common/util.h>
24 
36 char *
37 generate_op_key(const char *rsc_id, const char *op_type, int interval)
38 {
39  CRM_ASSERT(rsc_id != NULL);
40  CRM_ASSERT(op_type != NULL);
41  CRM_ASSERT(interval >= 0);
42  return crm_strdup_printf("%s_%s_%d", rsc_id, op_type, interval);
43 }
44 
45 gboolean
46 parse_op_key(const char *key, char **rsc_id, char **op_type, int *interval)
47 {
48  char *notify = NULL;
49  char *mutable_key = NULL;
50  char *mutable_key_ptr = NULL;
51  int len = 0, offset = 0, ch = 0;
52  int local_interval_ms = 0;
53 
54  // Initialize output variables in case of early return
55  if (rsc_id) {
56  *rsc_id = NULL;
57  }
58  if (op_type) {
59  *op_type = NULL;
60  }
61  if (interval) {
62  *interval = 0;
63  }
64 
65  CRM_CHECK(key && *key, return FALSE);
66 
67  // Parse interval at end of string
68  len = strlen(key);
69  offset = len - 1;
70 
71  crm_trace("Source: %s", key);
72 
73  while (offset > 0 && isdigit(key[offset])) {
74  int digits = len - offset;
75 
76  ch = key[offset] - '0';
77  CRM_CHECK(ch < 10, return FALSE);
78  CRM_CHECK(ch >= 0, return FALSE);
79  while (digits > 1) {
80  digits--;
81  ch = ch * 10;
82  }
83  local_interval_ms += ch;
84  offset--;
85  }
86  crm_trace("Operation key '%s' has interval %ums", key, local_interval_ms);
87  if (interval) {
88  *interval = local_interval_ms;
89  }
90 
91  CRM_CHECK((offset != (len - 1)) && (key[offset] == '_'), return FALSE);
92 
93  mutable_key = strndup(key, offset);
94  offset--;
95 
96  while (offset > 0 && key[offset] != '_') {
97  offset--;
98  }
99 
100  CRM_CHECK(key[offset] == '_',
101  free(mutable_key); return FALSE);
102 
103  mutable_key_ptr = mutable_key + offset + 1;
104 
105  crm_trace(" Action: %s", mutable_key_ptr);
106  if (op_type) {
107  *op_type = strdup(mutable_key_ptr);
108  }
109 
110  mutable_key[offset] = 0;
111  offset--;
112 
113  notify = strstr(mutable_key, "_post_notify");
114  if (notify && safe_str_eq(notify, "_post_notify")) {
115  notify[0] = 0;
116  }
117 
118  notify = strstr(mutable_key, "_pre_notify");
119  if (notify && safe_str_eq(notify, "_pre_notify")) {
120  notify[0] = 0;
121  }
122 
123  crm_trace(" Resource: %s", mutable_key);
124  if (rsc_id) {
125  *rsc_id = mutable_key;
126  } else {
127  free(mutable_key);
128  }
129 
130  return TRUE;
131 }
132 
133 char *
134 generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
135 {
136  int len = 12;
137  char *op_id = NULL;
138 
139  CRM_CHECK(rsc_id != NULL, return NULL);
140  CRM_CHECK(op_type != NULL, return NULL);
141  CRM_CHECK(notify_type != NULL, return NULL);
142 
143  len += strlen(op_type);
144  len += strlen(rsc_id);
145  len += strlen(notify_type);
146  if(len > 0) {
147  op_id = malloc(len);
148  }
149  if (op_id != NULL) {
150  sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type);
151  }
152  return op_id;
153 }
154 
155 char *
156 generate_transition_magic_v202(const char *transition_key, int op_status)
157 {
158  int len = 80;
159  char *fail_state = NULL;
160 
161  CRM_CHECK(transition_key != NULL, return NULL);
162 
163  len += strlen(transition_key);
164 
165  fail_state = malloc(len);
166  if (fail_state != NULL) {
167  snprintf(fail_state, len, "%d:%s", op_status, transition_key);
168  }
169  return fail_state;
170 }
171 
172 char *
173 generate_transition_magic(const char *transition_key, int op_status, int op_rc)
174 {
175  int len = 80;
176  char *fail_state = NULL;
177 
178  CRM_CHECK(transition_key != NULL, return NULL);
179 
180  len += strlen(transition_key);
181 
182  fail_state = malloc(len);
183  if (fail_state != NULL) {
184  snprintf(fail_state, len, "%d:%d;%s", op_status, op_rc, transition_key);
185  }
186  return fail_state;
187 }
188 
189 gboolean
190 decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id,
191  int *op_status, int *op_rc, int *target_rc)
192 {
193  int res = 0;
194  char *key = NULL;
195  gboolean result = TRUE;
196 
197  CRM_CHECK(magic != NULL, return FALSE);
198  CRM_CHECK(op_rc != NULL, return FALSE);
199  CRM_CHECK(op_status != NULL, return FALSE);
200 
201  key = calloc(1, strlen(magic) + 1);
202  res = sscanf(magic, "%d:%d;%s", op_status, op_rc, key);
203  if (res != 3) {
204  crm_warn("Only found %d items in: '%s'", res, magic);
205  free(key);
206  return FALSE;
207  }
208 
209  CRM_CHECK(decode_transition_key(key, uuid, transition_id, action_id, target_rc), result = FALSE);
210 
211  free(key);
212  return result;
213 }
214 
215 char *
216 generate_transition_key(int transition_id, int action_id, int target_rc, const char *node)
217 {
218  int len = 40;
219  char *fail_state = NULL;
220 
221  CRM_CHECK(node != NULL, return NULL);
222 
223  len += strlen(node);
224 
225  fail_state = malloc(len);
226  if (fail_state != NULL) {
227  snprintf(fail_state, len, "%d:%d:%d:%-*s", action_id, transition_id, target_rc, 36, node);
228  }
229  return fail_state;
230 }
231 
232 gboolean
233 decode_transition_key(const char *key, char **uuid, int *transition_id, int *action_id,
234  int *target_rc)
235 {
236  int res = 0;
237  gboolean done = FALSE;
238 
239  CRM_CHECK(uuid != NULL, return FALSE);
240  CRM_CHECK(target_rc != NULL, return FALSE);
241  CRM_CHECK(action_id != NULL, return FALSE);
242  CRM_CHECK(transition_id != NULL, return FALSE);
243 
244  *uuid = calloc(1, 37);
245  res = sscanf(key, "%d:%d:%d:%36s", action_id, transition_id, target_rc, *uuid);
246  switch (res) {
247  case 4:
248  /* Post Pacemaker 0.6 */
249  done = TRUE;
250  break;
251  case 3:
252  case 2:
253  /* this can be tricky - the UUID might start with an integer */
254 
255  /* Until Pacemaker 0.6 */
256  done = TRUE;
257  *target_rc = -1;
258  res = sscanf(key, "%d:%d:%36s", action_id, transition_id, *uuid);
259  if (res == 2) {
260  *action_id = -1;
261  res = sscanf(key, "%d:%36s", transition_id, *uuid);
262  CRM_CHECK(res == 2, done = FALSE);
263 
264  } else if (res != 3) {
265  CRM_CHECK(res == 3, done = FALSE);
266  }
267  break;
268 
269  case 1:
270  /* Prior to Heartbeat 2.0.8 */
271  done = TRUE;
272  *action_id = -1;
273  *target_rc = -1;
274  res = sscanf(key, "%d:%36s", transition_id, *uuid);
275  CRM_CHECK(res == 2, done = FALSE);
276  break;
277  default:
278  crm_crit("Unhandled sscanf result (%d) for %s", res, key);
279  }
280 
281  if (strlen(*uuid) != 36) {
282  crm_warn("Bad UUID (%s) in sscanf result (%d) for %s", *uuid, res, key);
283  }
284 
285  if (done == FALSE) {
286  crm_err("Cannot decode '%s' rc=%d", key, res);
287 
288  free(*uuid);
289  *uuid = NULL;
290  *target_rc = -1;
291  *action_id = -1;
292  *transition_id = -1;
293  }
294 
295  return done;
296 }
297 
298 void
299 filter_action_parameters(xmlNode * param_set, const char *version)
300 {
301  char *key = NULL;
302  char *timeout = NULL;
303  char *interval = NULL;
304 
305  const char *attr_filter[] = {
306  XML_ATTR_ID,
311  "pcmk_external_ip"
312  };
313 
314  gboolean do_delete = FALSE;
315  int lpc = 0;
316  static int meta_len = 0;
317 
318  if (meta_len == 0) {
319  meta_len = strlen(CRM_META);
320  }
321 
322  if (param_set == NULL) {
323  return;
324  }
325 
326  for (lpc = 0; lpc < DIMOF(attr_filter); lpc++) {
327  xml_remove_prop(param_set, attr_filter[lpc]);
328  }
329 
331  interval = crm_element_value_copy(param_set, key);
332  free(key);
333 
335  timeout = crm_element_value_copy(param_set, key);
336 
337  if (param_set) {
338  xmlAttrPtr xIter = param_set->properties;
339 
340  while (xIter) {
341  const char *prop_name = (const char *)xIter->name;
342 
343  xIter = xIter->next;
344  do_delete = FALSE;
345  if (strncasecmp(prop_name, CRM_META, meta_len) == 0) {
346  do_delete = TRUE;
347  }
348 
349  if (do_delete) {
350  xml_remove_prop(param_set, prop_name);
351  }
352  }
353  }
354 
355  if (crm_get_msec(interval) > 0 && compare_version(version, "1.0.8") > 0) {
356  /* Re-instate the operation's timeout value */
357  if (timeout != NULL) {
358  crm_xml_add(param_set, key, timeout);
359  }
360  }
361 
362  free(interval);
363  free(timeout);
364  free(key);
365 }
366 
367 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
368 static void
369 append_digest(lrmd_event_data_t * op, xmlNode * update, const char *version, const char *magic,
370  int level)
371 {
372  /* this will enable us to later determine that the
373  * resource's parameters have changed and we should force
374  * a restart
375  */
376  char *digest = NULL;
377  xmlNode *args_xml = NULL;
378 
379  if (op->params == NULL) {
380  return;
381  }
382 
383  args_xml = create_xml_node(NULL, XML_TAG_PARAMS);
384  g_hash_table_foreach(op->params, hash2field, args_xml);
385  filter_action_parameters(args_xml, version);
386  digest = calculate_operation_digest(args_xml, version);
387 
388 #if 0
389  if (level < get_crm_log_level()
390  && op->interval == 0 && crm_str_eq(op->op_type, CRMD_ACTION_START, TRUE)) {
391  char *digest_source = dump_xml_unformatted(args_xml);
392 
393  do_crm_log(level, "Calculated digest %s for %s (%s). Source: %s\n",
394  digest, ID(update), magic, digest_source);
395  free(digest_source);
396  }
397 #endif
398  crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest);
399 
400  free_xml(args_xml);
401  free(digest);
402 }
403 
404 int
406 {
407  int rc = 0;
408 
409  if (op && op->user_data) {
410  int dummy = 0;
411  char *uuid = NULL;
412 
413  decode_transition_key(op->user_data, &uuid, &dummy, &dummy, &rc);
414  free(uuid);
415  }
416  return rc;
417 }
418 
419 gboolean
420 did_rsc_op_fail(lrmd_event_data_t * op, int target_rc)
421 {
422  switch (op->op_status) {
424  case PCMK_LRM_OP_PENDING:
425  return FALSE;
426  break;
427 
429  case PCMK_LRM_OP_TIMEOUT:
430  case PCMK_LRM_OP_ERROR:
431  return TRUE;
432  break;
433 
434  default:
435  if (target_rc != op->rc) {
436  return TRUE;
437  }
438  }
439 
440  return FALSE;
441 }
442 
454 xmlNode *
455 crm_create_op_xml(xmlNode *parent, const char *prefix, const char *task,
456  const char *interval, const char *timeout)
457 {
458  xmlNode *xml_op;
459 
460  CRM_CHECK(prefix && task && interval, return NULL);
461 
462  xml_op = create_xml_node(parent, XML_ATTR_OP);
463  crm_xml_set_id(xml_op, "%s-%s-%s", prefix, task, interval);
464  crm_xml_add(xml_op, XML_LRM_ATTR_INTERVAL, interval);
465  crm_xml_add(xml_op, "name", task);
466  if (timeout) {
467  crm_xml_add(xml_op, XML_ATTR_TIMEOUT, timeout);
468  }
469  return xml_op;
470 }
471 
472 xmlNode *
473 create_operation_update(xmlNode * parent, lrmd_event_data_t * op, const char * caller_version,
474  int target_rc, const char * node, const char * origin, int level)
475 {
476  char *key = NULL;
477  char *magic = NULL;
478  char *op_id = NULL;
479  char *op_id_additional = NULL;
480  char *local_user_data = NULL;
481  const char *exit_reason = NULL;
482 
483  xmlNode *xml_op = NULL;
484  const char *task = NULL;
485  gboolean dc_munges_migrate_ops = (compare_version(caller_version, "3.0.3") < 0);
486  gboolean dc_needs_unique_ops = (compare_version(caller_version, "3.0.6") < 0);
487 
488  CRM_CHECK(op != NULL, return NULL);
489  do_crm_log(level, "%s: Updating resource %s after %s op %s (interval=%d)",
490  origin, op->rsc_id, op->op_type, services_lrm_status_str(op->op_status),
491  op->interval);
492 
493  crm_trace("DC version: %s", caller_version);
494 
495  task = op->op_type;
496  /* remap the task name under various scenarios
497  * this makes life easier for the PE when trying determine the current state
498  */
499  if (crm_str_eq(task, "reload", TRUE)) {
500  if (op->op_status == PCMK_LRM_OP_DONE) {
501  task = CRMD_ACTION_START;
502  } else {
503  task = CRMD_ACTION_STATUS;
504  }
505 
506  } else if (dc_munges_migrate_ops && crm_str_eq(task, CRMD_ACTION_MIGRATE, TRUE)) {
507  /* if the migrate_from fails it will have enough info to do the right thing */
508  if (op->op_status == PCMK_LRM_OP_DONE) {
509  task = CRMD_ACTION_STOP;
510  } else {
511  task = CRMD_ACTION_STATUS;
512  }
513 
514  } else if (dc_munges_migrate_ops
515  && op->op_status == PCMK_LRM_OP_DONE
516  && crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) {
517  task = CRMD_ACTION_START;
518  }
519 
520  key = generate_op_key(op->rsc_id, task, op->interval);
521  if (dc_needs_unique_ops && op->interval > 0) {
522  op_id = strdup(key);
523 
524  } else if (crm_str_eq(task, CRMD_ACTION_NOTIFY, TRUE)) {
525  const char *n_type = crm_meta_value(op->params, "notify_type");
526  const char *n_task = crm_meta_value(op->params, "notify_operation");
527 
528  CRM_LOG_ASSERT(n_type != NULL);
529  CRM_LOG_ASSERT(n_task != NULL);
530  op_id = generate_notify_key(op->rsc_id, n_type, n_task);
531 
532  if (op->op_status != PCMK_LRM_OP_PENDING) {
533  /* Ignore notify errors.
534  *
535  * @TODO It might be better to keep the correct result here, and
536  * ignore it in process_graph_event().
537  */
539  op->rc = 0;
540  }
541 
542  } else if (did_rsc_op_fail(op, target_rc)) {
543  op_id = generate_op_key(op->rsc_id, "last_failure", 0);
544  if (op->interval == 0) {
545  /* Ensure 'last' gets updated too in case recording-pending="true" */
546  op_id_additional = generate_op_key(op->rsc_id, "last", 0);
547  }
548  exit_reason = op->exit_reason;
549 
550  } else if (op->interval > 0) {
551  op_id = strdup(key);
552 
553  } else {
554  op_id = generate_op_key(op->rsc_id, "last", 0);
555  }
556 
557  again:
558  xml_op = find_entity(parent, XML_LRM_TAG_RSC_OP, op_id);
559  if (xml_op == NULL) {
560  xml_op = create_xml_node(parent, XML_LRM_TAG_RSC_OP);
561  }
562 
563  if (op->user_data == NULL) {
564  crm_debug("Generating fake transition key for:"
565  " %s_%s_%d %d from %s",
566  op->rsc_id, op->op_type, op->interval, op->call_id, origin);
567  local_user_data = generate_transition_key(-1, op->call_id, target_rc, FAKE_TE_ID);
568  op->user_data = local_user_data;
569  }
570 
571  if(magic == NULL) {
572  magic = generate_transition_magic(op->user_data, op->op_status, op->rc);
573  }
574 
575  crm_xml_add(xml_op, XML_ATTR_ID, op_id);
576  crm_xml_add(xml_op, XML_LRM_ATTR_TASK_KEY, key);
577  crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
578  crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin);
579  crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version);
581  crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic);
582  crm_xml_add(xml_op, XML_LRM_ATTR_EXIT_REASON, exit_reason == NULL ? "" : exit_reason);
583  crm_xml_add(xml_op, XML_LRM_ATTR_TARGET, node); /* For context during triage */
584 
586  crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc);
589 
590  if (compare_version("2.1", caller_version) <= 0) {
591  if (op->t_run || op->t_rcchange || op->exec_time || op->queue_time) {
592  crm_trace("Timing data (%s_%s_%d): last=%u change=%u exec=%u queue=%u",
593  op->rsc_id, op->op_type, op->interval,
594  op->t_run, op->t_rcchange, op->exec_time, op->queue_time);
595 
596  if (op->interval == 0) {
597  /* The values are the same for non-recurring ops */
600 
601  } else if(op->t_rcchange) {
602  /* last-run is not accurate for recurring ops */
604 
605  } else {
606  /* ...but is better than nothing otherwise */
608  }
609 
612  }
613  }
614 
615  if (crm_str_eq(op->op_type, CRMD_ACTION_MIGRATE, TRUE)
616  || crm_str_eq(op->op_type, CRMD_ACTION_MIGRATED, TRUE)) {
617  /*
618  * Record migrate_source and migrate_target always for migrate ops.
619  */
620  const char *name = XML_LRM_ATTR_MIGRATE_SOURCE;
621 
622  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
623 
625  crm_xml_add(xml_op, name, crm_meta_value(op->params, name));
626  }
627 
628  append_digest(op, xml_op, caller_version, magic, LOG_DEBUG);
629 
630  if (op_id_additional) {
631  free(op_id);
632  op_id = op_id_additional;
633  op_id_additional = NULL;
634  goto again;
635  }
636 
637  if (local_user_data) {
638  free(local_user_data);
639  op->user_data = NULL;
640  }
641  free(magic);
642  free(op_id);
643  free(key);
644  return xml_op;
645 }
646 
656 bool
657 crm_op_needs_metadata(const char *rsc_class, const char *op)
658 {
659  /* Agent meta-data is used to determine whether a reload is possible, and to
660  * evaluate versioned parameters -- so if this op is not relevant to those
661  * features, we don't need the meta-data.
662  */
663 
664  CRM_CHECK(rsc_class || op, return FALSE);
665 
666  if (rsc_class
667  && is_not_set(pcmk_get_ra_caps(rsc_class), pcmk_ra_cap_params)) {
668  /* Meta-data is only needed for resource classes that use parameters */
669  return FALSE;
670  }
671 
672  /* Meta-data is only needed for these actions */
673  if (op
674  && strcmp(op, CRMD_ACTION_START)
675  && strcmp(op, CRMD_ACTION_STATUS)
676  && strcmp(op, CRMD_ACTION_PROMOTE)
677  && strcmp(op, CRMD_ACTION_DEMOTE)
678  && strcmp(op, CRMD_ACTION_RELOAD)
679  && strcmp(op, CRMD_ACTION_MIGRATE)
680  && strcmp(op, CRMD_ACTION_MIGRATED)
681  && strcmp(op, CRMD_ACTION_NOTIFY)) {
682  return FALSE;
683  }
684 
685  return TRUE;
686 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
#define XML_RSC_OP_LAST_CHANGE
Definition: msg_xml.h:308
A dumping ground.
char * generate_transition_magic_v202(const char *transition_key, int op_status)
Definition: operations.c:156
#define CRMD_ACTION_MIGRATED
Definition: crm.h:165
#define crm_crit(fmt, args...)
Definition: logging.h:273
const char * user_data
Definition: lrmd.h:213
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:629
const char * rsc_id
Definition: lrmd.h:209
#define XML_ATTR_TRANSITION_MAGIC
Definition: msg_xml.h:390
gboolean did_rsc_op_fail(lrmd_event_data_t *op, int target_rc)
Definition: operations.c:420
char * generate_transition_magic(const char *transition_key, int op_status, int op_rc)
Definition: operations.c:173
unsigned int queue_time
Definition: lrmd.h:239
#define FAKE_TE_ID
Definition: operations.c:367
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:324
#define CRMD_ACTION_NOTIFY
Definition: crm.h:178
long long crm_get_msec(const char *input)
Definition: utils.c:589
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
Definition: xml.c:1830
#define XML_RSC_OP_T_EXEC
Definition: msg_xml.h:310
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:957
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:287
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:216
#define XML_LRM_ATTR_OP_DIGEST
Definition: msg_xml.h:301
#define XML_ATTR_TIMEOUT
Definition: msg_xml.h:96
#define CRMD_ACTION_PROMOTE
Definition: crm.h:173
Local Resource Manager.
unsigned int t_rcchange
Definition: lrmd.h:235
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:176
enum ocf_exitcode rc
Definition: lrmd.h:227
gboolean decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, int *op_status, int *op_rc, int *target_rc)
Definition: operations.c:190
#define XML_RSC_OP_T_QUEUE
Definition: msg_xml.h:311
char * strndup(const char *str, size_t len)
char * crm_meta_name(const char *field)
Definition: utils.c:935
char version[256]
Definition: plugin.c:84
unsigned int exec_time
Definition: lrmd.h:237
#define XML_ATTR_ORIGIN
Definition: msg_xml.h:97
xmlNode * crm_create_op_xml(xmlNode *parent, const char *prefix, const char *task, const char *interval, const char *timeout)
Create a CIB XML element for an operation.
Definition: operations.c:455
#define CRMD_ACTION_START
Definition: crm.h:167
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:289
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:288
#define CRMD_ACTION_STOP
Definition: crm.h:170
void * params
Definition: lrmd.h:246
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
Definition: digest.c:175
#define crm_warn(fmt, args...)
Definition: logging.h:275
char * generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
Definition: operations.c:134
op_status
Definition: services.h:133
#define CRMD_ACTION_DEMOTE
Definition: crm.h:175
const char * exit_reason
Definition: lrmd.h:254
#define XML_ATTR_OP
Definition: msg_xml.h:110
#define crm_debug(fmt, args...)
Definition: logging.h:279
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:570
Utility functions.
#define XML_ATTR_ID
Definition: msg_xml.h:102
void filter_action_parameters(xmlNode *param_set, const char *version)
Definition: operations.c:299
#define crm_trace(fmt, args...)
Definition: logging.h:280
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:129
Wrappers for and extensions to libxml2.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1977
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:29
#define XML_LRM_ATTR_MIGRATE_TARGET
Definition: msg_xml.h:314
#define XML_LRM_ATTR_EXIT_REASON
Definition: msg_xml.h:306
void free_xml(xmlNode *child)
Definition: xml.c:2108
gboolean decode_transition_key(const char *key, char **uuid, int *transition_id, int *action_id, int *target_rc)
Definition: operations.c:233
bool crm_op_needs_metadata(const char *rsc_class, const char *op)
Check whether an operation requires resource agent meta-data.
Definition: operations.c:657
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:245
const char * op_type
Definition: lrmd.h:211
char * generate_transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: operations.c:216
#define CRMD_ACTION_RELOAD
Definition: crm.h:163
#define XML_LRM_ATTR_TARGET_UUID
Definition: msg_xml.h:291
unsigned int t_run
Definition: lrmd.h:233
int rsc_op_expected_rc(lrmd_event_data_t *op)
Definition: operations.c:405
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:391
unsigned int get_crm_log_level(void)
Definition: logging.c:951
#define CRM_META
Definition: crm.h:43
#define crm_err(fmt, args...)
Definition: logging.h:274
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, int *interval)
Definition: operations.c:46
xmlNode * create_operation_update(xmlNode *parent, lrmd_event_data_t *op, const char *caller_version, int target_rc, const char *node, const char *origin, int level)
Definition: operations.c:473
void crm_xml_set_id(xmlNode *xml, const char *format,...) __attribute__((__format__(__printf__
void xml_remove_prop(xmlNode *obj, const char *name)
Definition: xml.c:3239
int compare_version(const char *version1, const char *version2)
Definition: utils.c:477
char * dump_xml_unformatted(xmlNode *msg)
Definition: xml.c:3220
#define DIMOF(a)
Definition: crm.h:29
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:300
#define CRMD_ACTION_MIGRATE
Definition: crm.h:164
#define CRM_ASSERT(expr)
Definition: error.h:20
#define XML_LRM_ATTR_OPSTATUS
Definition: msg_xml.h:298
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:84
#define XML_LRM_ATTR_RC
Definition: msg_xml.h:299
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:290
#define XML_LRM_TAG_RSC_OP
Definition: msg_xml.h:256
#define XML_RSC_OP_LAST_RUN
Definition: msg_xml.h:309
#define ID(x)
Definition: msg_xml.h:452
#define safe_str_eq(a, b)
Definition: util.h:74
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
char * generate_op_key(const char *rsc_id, const char *op_type, int interval)
Generate an operation key.
Definition: operations.c:37
#define XML_LRM_ATTR_MIGRATE_SOURCE
Definition: msg_xml.h:313
#define XML_TAG_PARAMS
Definition: msg_xml.h:191
#define CRMD_ACTION_STATUS
Definition: crm.h:181