pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
pcmk_injections.c
Go to the documentation of this file.
1 /*
2  * Copyright 2009-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 <stdio.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 
16 #include <sys/stat.h>
17 #include <sys/param.h>
18 #include <sys/types.h>
19 #include <dirent.h>
20 
21 #include <crm/crm.h>
22 #include <crm/cib.h>
23 #include <crm/cib/internal.h>
24 #include <crm/common/util.h>
25 #include <crm/common/iso8601.h>
27 #include <crm/lrmd_events.h> // lrmd_event_data_t, etc.
28 #include <crm/lrmd_internal.h>
29 #include <crm/pengine/status.h>
30 #include <pacemaker-internal.h>
31 
32 #include "libpacemaker_private.h"
33 
35 
36 #define XPATH_NODE_CONFIG "//" PCMK_XE_NODE "[@" PCMK_XA_UNAME "='%s']"
37 #define XPATH_NODE_STATE "//" PCMK__XE_NODE_STATE "[@" PCMK_XA_UNAME "='%s']"
38 #define XPATH_NODE_STATE_BY_ID "//" PCMK__XE_NODE_STATE "[@" PCMK_XA_ID "='%s']"
39 #define XPATH_RSC_HISTORY XPATH_NODE_STATE \
40  "//" PCMK__XE_LRM_RESOURCE "[@" PCMK_XA_ID "='%s']"
41 
42 
52 static void
53 inject_transient_attr(pcmk__output_t *out, xmlNode *cib_node,
54  const char *name, const char *value)
55 {
56  xmlNode *attrs = NULL;
57  xmlNode *instance_attrs = NULL;
58  const char *node_uuid = pcmk__xe_id(cib_node);
59 
60  out->message(out, "inject-attr", name, value, cib_node);
61 
63  NULL);
64  if (attrs == NULL) {
66  crm_xml_add(attrs, PCMK_XA_ID, node_uuid);
67  }
68 
69  instance_attrs = pcmk__xe_first_child(attrs, PCMK_XE_INSTANCE_ATTRIBUTES,
70  NULL, NULL);
71  if (instance_attrs == NULL) {
72  instance_attrs = pcmk__xe_create(attrs, PCMK_XE_INSTANCE_ATTRIBUTES);
73  crm_xml_add(instance_attrs, PCMK_XA_ID, node_uuid);
74  }
75 
76  crm_create_nvpair_xml(instance_attrs, NULL, name, value);
77 }
78 
95 void
96 pcmk__inject_failcount(pcmk__output_t *out, cib_t *cib_conn, xmlNode *cib_node,
97  const char *resource, const char *task,
98  guint interval_ms, int exit_status, bool infinity)
99 {
100  char *name = NULL;
101  char *value = NULL;
102 
103  int failcount = 0;
104  xmlNode *output = NULL;
105 
106  CRM_CHECK((out != NULL) && (cib_conn != NULL) && (cib_node != NULL)
107  && (resource != NULL) && (task != NULL), return);
108 
109  if ((exit_status == PCMK_OCF_OK)
110  || ((exit_status == PCMK_OCF_NOT_RUNNING) && (interval_ms == 0))) {
111  return;
112  }
113 
114  // Get current failcount and increment it
115  name = pcmk__failcount_name(resource, task, interval_ms);
116 
117  if (cib__get_node_attrs(out, cib_conn, PCMK_XE_STATUS,
118  pcmk__xe_id(cib_node), NULL, NULL, NULL, name,
119  NULL, &output) == pcmk_rc_ok) {
120 
121  if (crm_element_value_int(output, PCMK_XA_VALUE, &failcount) != 0) {
122  failcount = 0;
123  }
124  }
125 
126  if (infinity) {
128 
129  } else {
130  value = pcmk__itoa(failcount + 1);
131  }
132 
133  inject_transient_attr(out, cib_node, name, value);
134 
135  free(name);
136  free(value);
137  pcmk__xml_free(output);
138 
139  name = pcmk__lastfailure_name(resource, task, interval_ms);
140  value = pcmk__ttoa(time(NULL));
141  inject_transient_attr(out, cib_node, name, value);
142 
143  free(name);
144  free(value);
145 }
146 
154 static void
155 create_node_entry(cib_t *cib_conn, const char *node)
156 {
157  int rc = pcmk_ok;
158  char *xpath = crm_strdup_printf(XPATH_NODE_CONFIG, node);
159 
160  rc = cib_conn->cmds->query(cib_conn, xpath, NULL, cib_xpath|cib_sync_call);
161 
162  if (rc == -ENXIO) { // Only add if not already existing
163  xmlNode *cib_object = pcmk__xe_create(NULL, PCMK_XE_NODE);
164 
165  crm_xml_add(cib_object, PCMK_XA_ID, node); // Use node name as ID
166  crm_xml_add(cib_object, PCMK_XA_UNAME, node);
167  cib_conn->cmds->create(cib_conn, PCMK_XE_NODES, cib_object,
168  cib_sync_call);
169  /* Not bothering with subsequent query to see if it exists,
170  we'll bomb out later in the call to query_node_uuid()... */
171 
172  pcmk__xml_free(cib_object);
173  }
174 
175  free(xpath);
176 }
177 
191 static lrmd_event_data_t *
192 create_op(const xmlNode *cib_resource, const char *task, guint interval_ms,
193  int outcome)
194 {
195  lrmd_event_data_t *op = NULL;
196  xmlNode *xop = NULL;
197 
198  op = lrmd_new_event(pcmk__xe_id(cib_resource), task, interval_ms);
199  lrmd__set_result(op, outcome, PCMK_EXEC_DONE, "Simulated action result");
200  op->params = NULL; // Not needed for simulation purposes
201  op->t_run = time(NULL);
202  op->t_rcchange = op->t_run;
203 
204  // Use a call ID higher than any existing history entries
205  op->call_id = 0;
206  for (xop = pcmk__xe_first_child(cib_resource, NULL, NULL, NULL);
207  xop != NULL; xop = pcmk__xe_next(xop, NULL)) {
208 
209  int tmp = 0;
210 
212  if (tmp > op->call_id) {
213  op->call_id = tmp;
214  }
215  }
216  op->call_id++;
217 
218  return op;
219 }
220 
232 xmlNode *
234  const char *node, int target_rc)
235 {
236  return pcmk__create_history_xml(cib_resource, op, CRM_FEATURE_SET,
237  target_rc, node, crm_system_name);
238 }
239 
253 xmlNode *
254 pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
255 {
256  int rc = pcmk_ok;
257  xmlNode *cib_object = NULL;
258  char *xpath = crm_strdup_printf(XPATH_NODE_STATE, node);
259  bool duplicate = false;
260  char *found_uuid = NULL;
261 
263  create_node_entry(cib_conn, node);
264  }
265 
266  rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
268 
269  if ((cib_object != NULL) && (pcmk__xe_id(cib_object) == NULL)) {
270  crm_err("Detected multiple " PCMK__XE_NODE_STATE " entries for "
271  "xpath=%s, bailing",
272  xpath);
273  duplicate = true;
274  goto done;
275  }
276 
277  if (rc == -ENXIO) {
278  if (uuid == NULL) {
279  query_node_uuid(cib_conn, node, &found_uuid, NULL);
280  } else {
281  found_uuid = strdup(uuid);
282  }
283 
284  if (found_uuid) {
285  char *xpath_by_uuid = crm_strdup_printf(XPATH_NODE_STATE_BY_ID,
286  found_uuid);
287 
288  /* It's possible that a PCMK__XE_NODE_STATE entry doesn't have a
289  * PCMK_XA_UNAME yet
290  */
291  rc = cib_conn->cmds->query(cib_conn, xpath_by_uuid, &cib_object,
293 
294  if ((cib_object != NULL) && (pcmk__xe_id(cib_object) == NULL)) {
295  crm_err("Can't inject node state for %s because multiple "
296  "state entries found for ID %s", node, found_uuid);
297  duplicate = true;
298  free(xpath_by_uuid);
299  goto done;
300 
301  } else if (cib_object != NULL) {
302  crm_xml_add(cib_object, PCMK_XA_UNAME, node);
303 
304  rc = cib_conn->cmds->modify(cib_conn, PCMK_XE_STATUS,
305  cib_object, cib_sync_call);
306  }
307 
308  free(xpath_by_uuid);
309  }
310  }
311 
312  if (rc == -ENXIO) {
313  cib_object = pcmk__xe_create(NULL, PCMK__XE_NODE_STATE);
314  crm_xml_add(cib_object, PCMK_XA_ID, found_uuid);
315  crm_xml_add(cib_object, PCMK_XA_UNAME, node);
316  cib_conn->cmds->create(cib_conn, PCMK_XE_STATUS, cib_object,
317  cib_sync_call);
318  pcmk__xml_free(cib_object);
319 
320  rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
322  crm_trace("Injecting node state for %s (rc=%d)", node, rc);
323  }
324 
325 done:
326  free(found_uuid);
327  free(xpath);
328 
329  if (duplicate) {
330  crm_log_xml_warn(cib_object, "Duplicates");
332  return NULL; // not reached, but makes static analysis happy
333  }
334 
335  pcmk__assert(rc == pcmk_ok);
336  return cib_object;
337 }
338 
349 xmlNode *
350 pcmk__inject_node_state_change(cib_t *cib_conn, const char *node, bool up)
351 {
352  xmlNode *cib_node = pcmk__inject_node(cib_conn, node, NULL);
353 
354  if (up) {
355  pcmk__xe_set_props(cib_node,
360  NULL);
361  } else {
362  pcmk__xe_set_props(cib_node,
367  NULL);
368  }
370  return cib_node;
371 }
372 
383 static xmlNode *
384 find_resource_xml(xmlNode *cib_node, const char *resource)
385 {
386  const char *node = crm_element_value(cib_node, PCMK_XA_UNAME);
387  char *xpath = crm_strdup_printf(XPATH_RSC_HISTORY, node, resource);
388  xmlNode *match = get_xpath_object(xpath, cib_node, LOG_TRACE);
389 
390  free(xpath);
391  return match;
392 }
393 
410 xmlNode *
412  const char *resource, const char *lrm_name,
413  const char *rclass, const char *rtype,
414  const char *rprovider)
415 {
416  xmlNode *lrm = NULL;
417  xmlNode *container = NULL;
418  xmlNode *cib_resource = NULL;
419 
420  cib_resource = find_resource_xml(cib_node, resource);
421  if (cib_resource != NULL) {
422  /* If an existing LRM history entry uses the resource name,
423  * continue using it, even if lrm_name is different.
424  */
425  return cib_resource;
426  }
427 
428  // Check for history entry under preferred name
429  if (strcmp(resource, lrm_name) != 0) {
430  cib_resource = find_resource_xml(cib_node, lrm_name);
431  if (cib_resource != NULL) {
432  return cib_resource;
433  }
434  }
435 
436  if ((rclass == NULL) || (rtype == NULL)) {
437  // @TODO query configuration for class, provider, type
438  out->err(out,
439  "Resource %s not found in the status section of %s "
440  "(supply class and type to continue)",
441  resource, pcmk__xe_id(cib_node));
442  return NULL;
443 
444  } else if (!pcmk__strcase_any_of(rclass,
449  PCMK_RESOURCE_CLASS_LSB, NULL)) {
450  out->err(out, "Invalid class for %s: %s", resource, rclass);
451  return NULL;
452 
454  && (rprovider == NULL)) {
455  // @TODO query configuration for provider
456  out->err(out, "Please specify the provider for resource %s", resource);
457  return NULL;
458  }
459 
460  crm_info("Injecting new resource %s into node state '%s'",
461  lrm_name, pcmk__xe_id(cib_node));
462 
463  lrm = pcmk__xe_first_child(cib_node, PCMK__XE_LRM, NULL, NULL);
464  if (lrm == NULL) {
465  const char *node_uuid = pcmk__xe_id(cib_node);
466 
467  lrm = pcmk__xe_create(cib_node, PCMK__XE_LRM);
468  crm_xml_add(lrm, PCMK_XA_ID, node_uuid);
469  }
470 
471  container = pcmk__xe_first_child(lrm, PCMK__XE_LRM_RESOURCES, NULL, NULL);
472  if (container == NULL) {
473  container = pcmk__xe_create(lrm, PCMK__XE_LRM_RESOURCES);
474  }
475 
476  cib_resource = pcmk__xe_create(container, PCMK__XE_LRM_RESOURCE);
477 
478  // If we're creating a new entry, use the preferred name
479  crm_xml_add(cib_resource, PCMK_XA_ID, lrm_name);
480 
481  crm_xml_add(cib_resource, PCMK_XA_CLASS, rclass);
482  crm_xml_add(cib_resource, PCMK_XA_PROVIDER, rprovider);
483  crm_xml_add(cib_resource, PCMK_XA_TYPE, rtype);
484 
485  return cib_resource;
486 }
487 
500 static int
501 set_ticket_state_attr(pcmk__output_t *out, const char *ticket_id,
502  const char *attr_name, bool attr_value, cib_t *cib)
503 {
504  int rc = pcmk_rc_ok;
505  xmlNode *xml_top = NULL;
506  xmlNode *ticket_state_xml = NULL;
507 
508  // Check for an existing ticket state entry
509  rc = pcmk__get_ticket_state(cib, ticket_id, &ticket_state_xml);
510 
511  if (rc == pcmk_rc_duplicate_id) {
512  out->err(out, "Multiple " PCMK__XE_TICKET_STATE "s match ticket_id=%s",
513  ticket_id);
514  rc = pcmk_rc_ok;
515  }
516 
517  if (rc == pcmk_rc_ok) { // Ticket state found, use it
518  crm_debug("Injecting attribute into existing ticket state %s",
519  ticket_id);
520  xml_top = ticket_state_xml;
521 
522  } else if (rc == ENXIO) { // No ticket state, create it
523  xmlNode *xml_obj = NULL;
524 
525  xml_top = pcmk__xe_create(NULL, PCMK_XE_STATUS);
526  xml_obj = pcmk__xe_create(xml_top, PCMK_XE_TICKETS);
527  ticket_state_xml = pcmk__xe_create(xml_obj, PCMK__XE_TICKET_STATE);
528  crm_xml_add(ticket_state_xml, PCMK_XA_ID, ticket_id);
529 
530  } else { // Error
531  return rc;
532  }
533 
534  // Add the attribute to the ticket state
535  pcmk__xe_set_bool_attr(ticket_state_xml, attr_name, attr_value);
536  crm_log_xml_debug(xml_top, "Update");
537 
538  // Commit the change to the CIB
539  rc = cib->cmds->modify(cib, PCMK_XE_STATUS, xml_top, cib_sync_call);
540  rc = pcmk_legacy2rc(rc);
541 
542  pcmk__xml_free(xml_top);
543  return rc;
544 }
545 
555 static void
556 inject_action(pcmk__output_t *out, const char *spec, cib_t *cib,
558 {
559  int rc;
560  int outcome = PCMK_OCF_OK;
561  guint interval_ms = 0;
562 
563  char *key = NULL;
564  char *node = NULL;
565  char *task = NULL;
566  char *resource = NULL;
567 
568  const char *rtype = NULL;
569  const char *rclass = NULL;
570  const char *rprovider = NULL;
571 
572  xmlNode *cib_op = NULL;
573  xmlNode *cib_node = NULL;
574  xmlNode *cib_resource = NULL;
575  const pcmk_resource_t *rsc = NULL;
576  lrmd_event_data_t *op = NULL;
577  bool infinity = false;
578 
579  out->message(out, "inject-spec", spec);
580 
581  key = pcmk__assert_alloc(1, strlen(spec) + 1);
582  node = pcmk__assert_alloc(1, strlen(spec) + 1);
583  rc = sscanf(spec, "%[^@]@%[^=]=%d", key, node, &outcome);
584  if (rc != 3) {
585  out->err(out, "Invalid operation spec: %s. Only found %d fields",
586  spec, rc);
587  goto done;
588  }
589 
590  parse_op_key(key, &resource, &task, &interval_ms);
591 
592  rsc = pe_find_resource(scheduler->priv->resources, resource);
593  if (rsc == NULL) {
594  out->err(out, "Invalid resource name: %s", resource);
595  goto done;
596  }
597 
598  rclass = crm_element_value(rsc->priv->xml, PCMK_XA_CLASS);
599  rtype = crm_element_value(rsc->priv->xml, PCMK_XA_TYPE);
600  rprovider = crm_element_value(rsc->priv->xml, PCMK_XA_PROVIDER);
601 
602  cib_node = pcmk__inject_node(cib, node, NULL);
603  pcmk__assert(cib_node != NULL);
604 
605  if (pcmk__str_eq(task, PCMK_ACTION_STOP, pcmk__str_none)) {
606  infinity = true;
607 
608  } else if (pcmk__str_eq(task, PCMK_ACTION_START, pcmk__str_none)
611  infinity = true;
612  }
613 
614  pcmk__inject_failcount(out, cib, cib_node, resource, task, interval_ms,
615  outcome, infinity);
616 
617  cib_resource = pcmk__inject_resource_history(out, cib_node,
618  resource, resource,
619  rclass, rtype, rprovider);
620  pcmk__assert(cib_resource != NULL);
621 
622  op = create_op(cib_resource, task, interval_ms, outcome);
623  pcmk__assert(op != NULL);
624 
625  cib_op = pcmk__inject_action_result(cib_resource, op, node, 0);
626  pcmk__assert(cib_op != NULL);
627  lrmd_free_event(op);
628 
629  rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
630  pcmk__assert(rc == pcmk_ok);
631 
632 done:
633  free(task);
634  free(node);
635  free(key);
636 }
637 
646 void
648  const pcmk_injections_t *injections)
649 {
650  int rc = pcmk_ok;
651  const GList *iter = NULL;
652  xmlNode *cib_node = NULL;
653  pcmk__output_t *out = scheduler->priv->out;
654 
655  out->message(out, "inject-modify-config", injections->quorum,
656  injections->watchdog);
657  if (injections->quorum != NULL) {
658  xmlNode *top = pcmk__xe_create(NULL, PCMK_XE_CIB);
659 
660  /* crm_xml_add(top, PCMK_XA_DC_UUID, dc_uuid); */
661  crm_xml_add(top, PCMK_XA_HAVE_QUORUM, injections->quorum);
662 
663  rc = cib->cmds->modify(cib, NULL, top, cib_sync_call);
664  pcmk__assert(rc == pcmk_ok);
665  }
666 
667  if (injections->watchdog != NULL) {
669  NULL, NULL, NULL, NULL,
670  PCMK_OPT_HAVE_WATCHDOG, injections->watchdog,
671  NULL, NULL);
672  pcmk__assert(rc == pcmk_rc_ok);
673  }
674 
675  for (iter = injections->node_up; iter != NULL; iter = iter->next) {
676  const char *node = (const char *) iter->data;
677 
678  out->message(out, "inject-modify-node", "Online", node);
679 
680  cib_node = pcmk__inject_node_state_change(cib, node, true);
681  pcmk__assert(cib_node != NULL);
682 
683  rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
684  pcmk__assert(rc == pcmk_ok);
685  pcmk__xml_free(cib_node);
686  }
687 
688  for (iter = injections->node_down; iter != NULL; iter = iter->next) {
689  const char *node = (const char *) iter->data;
690  char *xpath = NULL;
691 
692  out->message(out, "inject-modify-node", "Offline", node);
693 
694  cib_node = pcmk__inject_node_state_change(cib, node, false);
695  pcmk__assert(cib_node != NULL);
696 
697  rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
698  pcmk__assert(rc == pcmk_ok);
699  pcmk__xml_free(cib_node);
700 
702  "[@" PCMK_XA_UNAME "='%s']"
703  "/" PCMK__XE_LRM,
704  node);
705  cib->cmds->remove(cib, xpath, NULL, cib_xpath|cib_sync_call);
706  free(xpath);
707 
709  "[@" PCMK_XA_UNAME "='%s']"
711  node);
712  cib->cmds->remove(cib, xpath, NULL, cib_xpath|cib_sync_call);
713  free(xpath);
714  }
715 
716  for (iter = injections->node_fail; iter != NULL; iter = iter->next) {
717  const char *node = (const char *) iter->data;
718 
719  out->message(out, "inject-modify-node", "Failing", node);
720 
721  cib_node = pcmk__inject_node_state_change(cib, node, true);
723  pcmk__assert(cib_node != NULL);
724 
725  rc = cib->cmds->modify(cib, PCMK_XE_STATUS, cib_node, cib_sync_call);
726  pcmk__assert(rc == pcmk_ok);
727  pcmk__xml_free(cib_node);
728  }
729 
730  for (iter = injections->ticket_grant; iter != NULL; iter = iter->next) {
731  const char *ticket_id = (const char *) iter->data;
732 
733  out->message(out, "inject-modify-ticket", "Granting", ticket_id);
734 
735  rc = set_ticket_state_attr(out, ticket_id, PCMK__XA_GRANTED, true, cib);
736  pcmk__assert(rc == pcmk_rc_ok);
737  }
738 
739  for (iter = injections->ticket_revoke; iter != NULL; iter = iter->next) {
740  const char *ticket_id = (const char *) iter->data;
741 
742  out->message(out, "inject-modify-ticket", "Revoking", ticket_id);
743 
744  rc = set_ticket_state_attr(out, ticket_id, PCMK__XA_GRANTED, false,
745  cib);
746  pcmk__assert(rc == pcmk_rc_ok);
747  }
748 
749  for (iter = injections->ticket_standby; iter != NULL; iter = iter->next) {
750  const char *ticket_id = (const char *) iter->data;
751 
752  out->message(out, "inject-modify-ticket", "Standby", ticket_id);
753 
754  rc = set_ticket_state_attr(out, ticket_id, PCMK_XA_STANDBY, true, cib);
755  pcmk__assert(rc == pcmk_rc_ok);
756  }
757 
758  for (iter = injections->ticket_activate; iter != NULL; iter = iter->next) {
759  const char *ticket_id = (const char *) iter->data;
760 
761  out->message(out, "inject-modify-ticket", "Activating", ticket_id);
762 
763  rc = set_ticket_state_attr(out, ticket_id, PCMK_XA_STANDBY, false, cib);
764  pcmk__assert(rc == pcmk_rc_ok);
765  }
766 
767  for (iter = injections->op_inject; iter != NULL; iter = iter->next) {
768  inject_action(out, (const char *) iter->data, cib, scheduler);
769  }
770 
771  if (!out->is_quiet(out)) {
772  out->end_list(out);
773  }
774 }
775 
776 void
778 {
779  if (injections == NULL) {
780  return;
781  }
782 
783  g_list_free_full(injections->node_up, g_free);
784  g_list_free_full(injections->node_down, g_free);
785  g_list_free_full(injections->node_fail, g_free);
786  g_list_free_full(injections->op_fail, g_free);
787  g_list_free_full(injections->op_inject, g_free);
788  g_list_free_full(injections->ticket_grant, g_free);
789  g_list_free_full(injections->ticket_revoke, g_free);
790  g_list_free_full(injections->ticket_standby, g_free);
791  g_list_free_full(injections->ticket_activate, g_free);
792  free(injections->quorum);
793  free(injections->watchdog);
794 
795  free(injections);
796 }
void(* end_list)(pcmk__output_t *out)
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
A dumping ground.
GList * op_inject
Definition: pacemaker.h:61
Internal software bug.
Definition: results.h:251
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml_element.c:42
#define PCMK__XE_LRM_RESOURCES
#define PCMK__XE_TICKET_STATE
#define PCMK_RESOURCE_CLASS_SERVICE
Definition: agents.h:28
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:1044
#define PCMK_VALUE_FALSE
Definition: options.h:153
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition: xml_element.c:1480
#define PCMK_XE_CIB
Definition: xml_names.h:79
#define PCMK_XE_STATUS
Definition: xml_names.h:204
#define PCMK_VALUE_INFINITY
Definition: options.h:164
const char * name
Definition: cib.c:26
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1027
int(* message)(pcmk__output_t *out, const char *message_id,...)
GList * ticket_activate
Definition: pacemaker.h:74
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
Definition: status.c:453
bool(* is_quiet)(pcmk__output_t *out)
#define CRM_FEATURE_SET
Definition: crm.h:66
#define PCMK_XA_HAVE_QUORUM
Definition: xml_names.h:295
xmlNode * pcmk__inject_resource_history(pcmk__output_t *out, xmlNode *cib_node, const char *resource, const char *lrm_name, const char *rclass, const char *rtype, const char *rprovider)
Service safely stopped.
Definition: results.h:186
GList * node_up
Definition: pacemaker.h:52
pcmk__scheduler_private_t * priv
Definition: scheduler.h:99
#define PCMK_XA_PROVIDER
Definition: xml_names.h:364
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
Definition: cib_attrs.c:628
uint64_t flags
Definition: scheduler.h:89
char * crm_system_name
Definition: utils.c:44
#define PCMK_RESOURCE_CLASS_OCF
Definition: agents.h:27
void pcmk__inject_scheduler_input(pcmk_scheduler_t *scheduler, cib_t *cib, const pcmk_injections_t *injections)
GList * ticket_grant
Definition: pacemaker.h:68
#define PCMK_RESOURCE_CLASS_SYSTEMD
Definition: agents.h:30
#define XPATH_NODE_CONFIG
#define PCMK_XA_TYPE
Definition: xml_names.h:430
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:189
#define PCMK_XA_STANDBY
Definition: xml_names.h:406
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml_element.c:407
#define PCMK__XE_TRANSIENT_ATTRIBUTES
void pcmk__xml_free(xmlNode *xml)
Definition: xml.c:789
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: xml_element.c:1015
int cib__get_node_attrs(pcmk__output_t *out, cib_t *cib, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *user_name, xmlNode **result)
Definition: cib_attrs.c:345
void pcmk_free_injections(pcmk_injections_t *injections)
Free a :pcmk_injections_t structure.
#define PCMK__XE_LRM_RESOURCE
#define CRMD_JOINSTATE_DOWN
Definition: crm.h:135
cib_api_operations_t * cmds
Definition: cib_types.h:325
#define crm_debug(fmt, args...)
Definition: logging.h:370
#define PCMK_XA_UNAME
Definition: xml_names.h:431
#define PCMK_XA_EXPECTED
Definition: xml_names.h:278
Utility functions.
xmlNode * pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *event, const char *caller_version, int target_rc, const char *node, const char *origin)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
GList * ticket_standby
Definition: pacemaker.h:72
#define crm_trace(fmt, args...)
Definition: logging.h:372
#define CRMD_JOINSTATE_MEMBER
Definition: crm.h:137
#define PCMK_RESOURCE_CLASS_STONITH
Definition: agents.h:31
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:80
int(* modify)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:169
int(*) int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
#define crm_log_xml_debug(xml, text)
Definition: logging.h:379
#define PCMK_ACTION_START
Definition: actions.h:63
pcmk__resource_private_t * priv
Definition: resources.h:61
int(* create)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:167
ISO_8601 Date handling.
#define crm_log_xml_warn(xml, text)
Definition: logging.h:376
Action completed, result is known.
Definition: results.h:309
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:151
#define PCMK_ACTION_STOP
Definition: actions.h:66
#define PCMK__XA_JOIN
int pcmk__get_ticket_state(cib_t *cib, const char *ticket_id, xmlNode **state)
Definition: pcmk_ticket.c:78
#define PCMK_VALUE_TRUE
Definition: options.h:218
#define PCMK_XA_ID
Definition: xml_names.h:301
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:667
#define PCMK__XE_LRM
#define PCMK_XA_VALUE
Definition: xml_names.h:442
#define pcmk__str_copy(str)
#define PCMK_XE_TICKETS
Definition: xml_names.h:213
bool pcmk__simulate_node_config
void pcmk__inject_failcount(pcmk__output_t *out, cib_t *cib_conn, xmlNode *cib_node, const char *resource, const char *task, guint interval_ms, int exit_status, bool infinity)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
Definition: xml_element.c:106
#define pcmk__assert(expr)
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition: xml_element.c:970
#define PCMK_VALUE_ONLINE
Definition: options.h:186
#define PCMK_XA_CLASS
Definition: xml_names.h:246
#define PCMK_XE_NODE
Definition: xml_names.h:136
Cluster status and scheduling.
GList * ticket_revoke
Definition: pacemaker.h:70
#define crm_err(fmt, args...)
Definition: logging.h:359
pcmk_scheduler_t * scheduler
Success.
Definition: results.h:174
Cluster Configuration.
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
Definition: lrmd_client.c:2617
#define PCMK_XA_CRMD
Definition: xml_names.h:256
Synthetic cluster events that can be injected into the cluster for running simulations.
Definition: pacemaker.h:50
#define PCMK_RESOURCE_CLASS_LSB
Definition: agents.h:29
#define PCMK__XA_GRANTED
void lrmd_free_event(lrmd_event_data_t *event)
Free an executor event.
Definition: lrmd_client.c:246
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: xml_element.c:1201
GList * node_fail
Definition: pacemaker.h:56
This structure contains everything that makes up a single output formatter.
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: actions.c:248
int cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *attr_value, const char *user_name, const char *node_type)
Definition: cib_attrs.c:164
#define PCMK__XA_IN_CCM
#define PCMK_OPT_HAVE_WATCHDOG
Definition: options.h:40
#define XPATH_RSC_HISTORY
#define PCMK__XE_NODE_STATE
xmlNode * pcmk__inject_node_state_change(cib_t *cib_conn, const char *node, bool up)
#define pcmk_ok
Definition: results.h:65
#define PCMK__XA_CALL_ID
#define XPATH_NODE_STATE
GList * op_fail
Definition: pacemaker.h:66
#define PCMK_XE_NODES
Definition: xml_names.h:142
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
Definition: agents.c:27
int(* remove)(cib_t *cib, const char *section, xmlNode *data, int call_options)
Definition: cib_types.h:174
xmlNode * crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name, const char *value)
Create an XML name/value pair.
Definition: nvpair.c:312
xmlNode * pcmk__inject_action_result(xmlNode *cib_resource, lrmd_event_data_t *op, const char *node, int target_rc)
lrmd_event_data_t * lrmd_new_event(const char *rsc_id, const char *task, guint interval_ms)
Create a new lrmd_event_data_t object.
Definition: lrmd_client.c:195
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:257
Resource agent executor events.
#define PCMK_XA_CRM_DEBUG_ORIGIN
Definition: xml_names.h:253
#define PCMK_VALUE_OFFLINE
Definition: options.h:185
#define PCMK_XE_INSTANCE_ATTRIBUTES
Definition: xml_names.h:122
#define XPATH_NODE_STATE_BY_ID
#define crm_info(fmt, args...)
Definition: logging.h:367
xmlNode * pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
GList * node_down
Definition: pacemaker.h:54
#define PCMK_XE_CRM_CONFIG
Definition: xml_names.h:91
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1